125 lines
4.1 KiB
Rust
125 lines
4.1 KiB
Rust
//! Google Play Developer API publisher.
|
|
//!
|
|
//! Models the Google Play Developer API calls. Stubs the actual HTTP.
|
|
//!
|
|
//! API reference: https://developers.google.com/android-publisher
|
|
|
|
use crate::{
|
|
config::{GoogleConfig, PublishConfig},
|
|
metadata::StoreMetadata,
|
|
PublishError, PublishOutcome, PublishResult,
|
|
};
|
|
|
|
/// Publishes app bundles to Google Play Store.
|
|
pub struct GooglePublisher {
|
|
pub google_config: GoogleConfig,
|
|
pub publish_config: PublishConfig,
|
|
}
|
|
|
|
impl GooglePublisher {
|
|
pub fn new(publish_config: PublishConfig) -> PublishResult<Self> {
|
|
let google_config = publish_config.google.clone().ok_or_else(|| {
|
|
PublishError::Config("no [publish.google] section in el.toml".into())
|
|
})?;
|
|
Ok(Self { google_config, publish_config })
|
|
}
|
|
|
|
/// Create a new edit session on Google Play.
|
|
///
|
|
/// In production: POST https://androidpublisher.googleapis.com/v3/applications/{packageName}/edits
|
|
pub fn create_edit(&self) -> PublishResult<String> {
|
|
// TODO: OAuth2 authentication via service account JSON
|
|
let edit_id = format!("edit-{}", self.publish_config.build_number);
|
|
Ok(edit_id)
|
|
}
|
|
|
|
/// Upload an AAB (Android App Bundle) to an edit session.
|
|
///
|
|
/// In production: POST .../edits/{editId}/bundles (multipart upload)
|
|
pub fn upload_bundle(
|
|
&self,
|
|
edit_id: &str,
|
|
aab_path: &str,
|
|
) -> PublishResult<u32> {
|
|
let _ = (edit_id, aab_path);
|
|
// Returns the version code of the uploaded bundle
|
|
Ok(self.publish_config.build_number)
|
|
}
|
|
|
|
/// Assign a bundle to a track.
|
|
///
|
|
/// In production: PUT .../edits/{editId}/tracks/{track}
|
|
pub fn assign_to_track(
|
|
&self,
|
|
edit_id: &str,
|
|
version_code: u32,
|
|
track: &str,
|
|
rollout_fraction: f64,
|
|
) -> PublishResult<()> {
|
|
let _ = (edit_id, version_code, track, rollout_fraction);
|
|
if !matches!(track, "internal" | "alpha" | "beta" | "production") {
|
|
return Err(PublishError::Config(format!(
|
|
"unknown Google Play track: '{}'. Use internal/alpha/beta/production",
|
|
track
|
|
)));
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
/// Upload store listing (metadata) for a locale.
|
|
///
|
|
/// In production: PATCH .../edits/{editId}/listings/{language}
|
|
pub fn upload_listing(
|
|
&self,
|
|
edit_id: &str,
|
|
locale: &str,
|
|
metadata: &StoreMetadata,
|
|
) -> PublishResult<()> {
|
|
let _ = (edit_id, locale, metadata);
|
|
Ok(())
|
|
}
|
|
|
|
/// Commit an edit (makes the changes live).
|
|
///
|
|
/// In production: POST .../edits/{editId}:commit
|
|
pub fn commit_edit(&self, edit_id: &str) -> PublishResult<String> {
|
|
// Returns the resulting version code
|
|
Ok(format!("{}-committed", edit_id))
|
|
}
|
|
|
|
/// Update rollout percentage for a track (for staged rollouts).
|
|
pub fn update_rollout(&self, track: &str, percent: u8) -> PublishResult<()> {
|
|
if percent > 100 {
|
|
return Err(PublishError::Config(format!(
|
|
"rollout percent {} exceeds 100",
|
|
percent
|
|
)));
|
|
}
|
|
let _ = (track, percent);
|
|
// TODO: PATCH .../tracks/{track} with rollout fraction
|
|
Ok(())
|
|
}
|
|
|
|
/// Full publish flow: create edit → upload bundle → assign to track → commit.
|
|
pub fn publish(&self, aab_path: &str) -> PublishResult<PublishOutcome> {
|
|
let metadata = StoreMetadata::load_from_dir(&self.publish_config.metadata_dir)?;
|
|
let edit_id = self.create_edit()?;
|
|
let version_code = self.upload_bundle(&edit_id, aab_path)?;
|
|
|
|
let track = &self.google_config.track;
|
|
let rollout_fraction = self
|
|
.publish_config
|
|
.rollout
|
|
.as_ref()
|
|
.map(|r| r.initial_percent as f64 / 100.0)
|
|
.unwrap_or(1.0);
|
|
|
|
self.assign_to_track(&edit_id, version_code, track, rollout_fraction)?;
|
|
self.upload_listing(&edit_id, "en-US", &metadata)?;
|
|
let commit_id = self.commit_edit(&edit_id)?;
|
|
|
|
Ok(PublishOutcome::new("google", &self.publish_config, track)
|
|
.with_submission_id(commit_id))
|
|
}
|
|
}
|