diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 54b6584f6..82acb3203 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -84,10 +84,13 @@ jobs: timeout-minutes: 10 check: runs-on: ubuntu-latest + outputs: + is-latest: ${{ steps.check.outputs.is-latest }} steps: - uses: actions/checkout@v3 - uses: ./.github/actions/setup-rust - run: cargo xtask ci-job check + id: check shell: bash generate-matrix: runs-on: ubuntu-latest @@ -256,6 +259,7 @@ jobs: TARGET: ${{ matrix.target }} SUB: ${{ matrix.sub }} LABELS: ${{ steps.docker-meta.outputs.labels }} + IS_LATEST: ${{ needs.check.outputs.is-latest || 'false' }} shell: bash - name: Set Docker image for test if: steps.prepare-meta.outputs.has-image @@ -302,6 +306,7 @@ jobs: TARGET: ${{ matrix.target }} SUB: ${{ matrix.sub }} LABELS: ${{ steps.docker-meta.outputs.labels }} + IS_LATEST: ${{ needs.check.outputs.is-latest || 'false' }} shell: bash publish: diff --git a/Cargo.lock b/Cargo.lock index 0c663fd5b..3bdc61911 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -693,6 +693,7 @@ dependencies = [ "cross", "eyre", "once_cell", + "semver", "serde", "serde_json", "serde_yaml", diff --git a/xtask/Cargo.toml b/xtask/Cargo.toml index 553900399..8cafcedf8 100644 --- a/xtask/Cargo.toml +++ b/xtask/Cargo.toml @@ -19,3 +19,4 @@ serde = { version = "1", features = ["derive"] } serde_yaml = "0.8" serde_json = "1.0" once_cell = "1.12" +semver = "1" diff --git a/xtask/src/build_docker_image.rs b/xtask/src/build_docker_image.rs index 52ebee903..c62923e19 100644 --- a/xtask/src/build_docker_image.rs +++ b/xtask/src/build_docker_image.rs @@ -11,6 +11,8 @@ pub struct BuildDockerImage { ref_type: Option, #[clap(long, hide = true, env = "GITHUB_REF_NAME")] ref_name: Option, + #[clap(long, hide = true, env = "IS_LATEST")] + is_latest: Option, /// Specify a tag to use instead of the derived one, eg `local` #[clap(long)] tag: Option, @@ -80,6 +82,7 @@ pub fn build_docker_image( BuildDockerImage { ref_type, ref_name, + is_latest, tag: tag_override, repository, labels, @@ -164,6 +167,7 @@ pub fn build_docker_image( &repository, ref_type, ref_name, + is_latest.unwrap_or_default(), &version, )?), _ => { @@ -276,6 +280,7 @@ pub fn determine_image_name( repository: &str, ref_type: &str, ref_name: &str, + is_latest: bool, version: &str, ) -> cross::Result> { let mut tags = vec![]; @@ -289,8 +294,7 @@ pub fn determine_image_name( } tags.push(target.image_name(repository, version)); // Check for unstable releases, tag stable releases as `latest` - if !version.contains('-') { - // TODO: Don't tag if version is older than currently released version. + if is_latest { tags.push(target.image_name(repository, "latest")) } } diff --git a/xtask/src/ci.rs b/xtask/src/ci.rs index 43811b9d7..7eb902caa 100644 --- a/xtask/src/ci.rs +++ b/xtask/src/ci.rs @@ -1,5 +1,5 @@ use clap::Subcommand; -use cross::CargoMetadata; +use cross::{cargo_command, CargoMetadata, CommandExt}; #[derive(Subcommand, Debug)] pub enum CiJob { @@ -59,6 +59,7 @@ pub fn ci(args: CiJob, metadata: CargoMetadata) -> cross::Result<()> { cross::docker::CROSS_IMAGE, &ref_type, &ref_name, + false, &version, )?[0], ); @@ -68,9 +69,28 @@ pub fn ci(args: CiJob, metadata: CargoMetadata) -> cross::Result<()> { } } CiJob::Check { ref_type, ref_name } => { - let version = cross_meta.version.clone(); - if ref_type == "tag" && ref_name.starts_with('v') && ref_name != format!("v{version}") { - eyre::bail!("a version tag was published, but the tag does not match the current version in Cargo.toml"); + let version = semver::Version::parse(&cross_meta.version)?; + if ref_type == "tag" { + if ref_name.starts_with('v') && ref_name != format!("v{version}") { + eyre::bail!("a version tag was published, but the tag does not match the current version in Cargo.toml"); + } + let search = cargo_command() + .args(&["search", "--limit", "1"]) + .arg("cross") + .run_and_get_stdout(true)?; + let (cross, rest) = search + .split_once(" = ") + .ok_or_else(|| eyre::eyre!("cargo search failed"))?; + assert_eq!(cross, "cross"); + // Note: this version includes pre-releases. + let latest_version = semver::Version::parse( + rest.split('"') + .nth(1) + .ok_or_else(|| eyre::eyre!("cargo search returned unexpected data"))?, + )?; + if version >= latest_version && version.pre.is_empty() { + gha_output("is-latest", "true") + } } } }