greentic-deployer 0.5.21

Greentic deployer runtime for plan construction and deployment-pack dispatch
Documentation
name: Publish and Release

# Tag-triggered: fires after `tag-on-version-bump.yml` detects a Cargo.toml
# version change on main and pushes `v{version}`. Covers binary release
# assets, GHCR OCI .gtpack publishing, and crates.io publish (gated on the
# GH release job).
on:
  push:
    tags: ["v*"]
  workflow_dispatch:

permissions:
  contents: read

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: false

jobs:
  ci:
    uses: ./.github/workflows/ci.yml

  binary-release-assets:
    name: Build binary release assets
    runs-on: ${{ matrix.os }}
    needs: ci
    permissions:
      contents: write
    strategy:
      fail-fast: false
      matrix:
        include:
          - os: ubuntu-latest
            target: x86_64-unknown-linux-gnu
            archive_ext: tar.gz
            asset_suffix: linux-amd64
            binary_name: greentic-deployer
          - os: ubuntu-24.04-arm
            target: aarch64-unknown-linux-gnu
            archive_ext: tar.gz
            asset_suffix: linux-arm64
            binary_name: greentic-deployer
          - os: windows-latest
            target: x86_64-pc-windows-msvc
            archive_ext: zip
            asset_suffix: windows-amd64
            binary_name: greentic-deployer.exe
          - os: windows-11-arm
            target: aarch64-pc-windows-msvc
            archive_ext: zip
            asset_suffix: windows-arm64
            binary_name: greentic-deployer.exe
          - os: macos-15-intel
            target: x86_64-apple-darwin
            archive_ext: tar.gz
            asset_suffix: macos-amd64
            binary_name: greentic-deployer
          - os: macos-15
            target: aarch64-apple-darwin
            archive_ext: tar.gz
            asset_suffix: macos-arm64
            binary_name: greentic-deployer
    steps:
      - uses: actions/checkout@v4
      - name: Read crate version
        id: version
        shell: bash
        run: |
          set -euo pipefail
          version=$(sed -n 's/^version = "\(.*\)"/\1/p' Cargo.toml | head -n 1)
          if [ -z "$version" ]; then
            echo "Failed to read version from Cargo.toml" >&2
            exit 1
          fi
          echo "value=$version" >> "$GITHUB_OUTPUT"
          echo "tag=v$version" >> "$GITHUB_OUTPUT"
      - uses: dtolnay/rust-toolchain@1.95.0
        with:
          toolchain: 1.95.0
          targets: ${{ matrix.target }}
      - uses: Swatinem/rust-cache@v2
      - name: Build release binary
        run: cargo build --locked --release --target ${{ matrix.target }}
      - name: Package Unix asset
        if: matrix.archive_ext == 'tar.gz'
        shell: bash
        env:
          ASSET_BASENAME: greentic-deployer-${{ matrix.target }}-${{ steps.version.outputs.tag }}
        run: |
          set -euo pipefail
          mkdir "$ASSET_BASENAME"
          cp "target/${{ matrix.target }}/release/${{ matrix.binary_name }}" "$ASSET_BASENAME/"
          tar -czf "${ASSET_BASENAME}.tar.gz" "$ASSET_BASENAME"
      - name: Package Windows ARM asset
        if: matrix.archive_ext == 'zip'
        shell: pwsh
        env:
          ASSET_BASENAME: greentic-deployer-${{ matrix.target }}-${{ steps.version.outputs.tag }}
        run: |
          New-Item -ItemType Directory -Path $env:ASSET_BASENAME | Out-Null
          Copy-Item "target/${{ matrix.target }}/release/${{ matrix.binary_name }}" "$env:ASSET_BASENAME/"
          Compress-Archive -Path $env:ASSET_BASENAME -DestinationPath "$env:ASSET_BASENAME.zip"
      - name: Upload build artifact
        uses: actions/upload-artifact@v4
        with:
          name: greentic-deployer-${{ matrix.target }}-${{ steps.version.outputs.tag }}
          path: greentic-deployer-${{ matrix.target }}-${{ steps.version.outputs.tag }}.${{ matrix.archive_ext }}

  publish-version-release:
    name: Publish version release
    runs-on: ubuntu-latest
    needs: binary-release-assets
    permissions:
      contents: write
    steps:
      - uses: actions/checkout@v4
      - name: Read crate version
        id: version
        shell: bash
        run: |
          set -euo pipefail
          version=$(sed -n 's/^version = "\(.*\)"/\1/p' Cargo.toml | head -n 1)
          if [ -z "$version" ]; then
            echo "Failed to read version from Cargo.toml" >&2
            exit 1
          fi
          echo "value=$version" >> "$GITHUB_OUTPUT"
          echo "tag=v$version" >> "$GITHUB_OUTPUT"
      - uses: actions/download-artifact@v4
        with:
          pattern: greentic-deployer-*-${{ steps.version.outputs.tag }}
          path: dist
          merge-multiple: true
      - name: Publish GitHub release assets
        uses: softprops/action-gh-release@v2
        with:
          tag_name: v${{ steps.version.outputs.value }}
          target_commitish: ${{ github.sha }}
          name: v${{ steps.version.outputs.value }}
          prerelease: false
          make_latest: true
          fail_on_unmatched_files: true
          overwrite_files: true
          files: |
            dist/*.tar.gz
            dist/*.zip

  gtpack-publish:
    runs-on: ubuntu-latest
    needs: ci
    permissions:
      contents: read
      packages: write
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@1.95.0
        with:
          toolchain: 1.95.0
      - uses: Swatinem/rust-cache@v2
      - name: Install cargo-binstall
        uses: cargo-bins/cargo-binstall@main
      - name: Add Cargo bin to PATH
        run: echo "${CARGO_HOME:-$HOME/.cargo}/bin" >> "$GITHUB_PATH"
      - name: Install Greentic fixture tools
        run: ci/ensure_fixture_tools.sh
      - uses: oras-project/setup-oras@v1
      - name: Build fixture gtpacks
        id: build-gtpacks
        run: |
          set -euo pipefail
          cargo run --features internal-tools --bin build_fixture_gtpacks | tee /tmp/build_fixture_gtpacks.log
      - name: Log in to GHCR
        uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - name: Publish gtpacks to GHCR
        env:
          GHCR_NAMESPACE: ghcr.io/${{ github.repository_owner }}/packs/deployer
          REVISION: ${{ github.sha }}
        run: |
          set -euo pipefail
          mapfile -t pack_lines < <(grep $'^PACK\t' /tmp/build_fixture_gtpacks.log || true)
          if [ "${#pack_lines[@]}" -eq 0 ]; then
            echo "No PACK metadata found in build output"
            exit 1
          fi

          for pack_line in "${pack_lines[@]}"; do
            IFS=$'\t' read -r _ pack_id pack_version pack_path <<<"${pack_line}"
            pack_file="$(basename "$pack_path")"
            version_ref="${GHCR_NAMESPACE}/${pack_id}:${pack_version}"
            latest_ref="${GHCR_NAMESPACE}/${pack_id}:latest"
            stable_ref="${GHCR_NAMESPACE}/${pack_id}:stable"

            echo "Publishing ${pack_file} -> ${version_ref}"
            oras push "${version_ref}" \
              --artifact-type application/vnd.greentic.gtpack.v1 \
              --annotation "org.opencontainers.image.title=${pack_file}" \
              --annotation "org.opencontainers.image.revision=${REVISION}" \
              "${pack_path}:application/vnd.greentic.gtpack.layer.v1+tar"

            echo "Publishing ${pack_file} -> ${latest_ref}"
            oras push "${latest_ref}" \
              --artifact-type application/vnd.greentic.gtpack.v1 \
              --annotation "org.opencontainers.image.title=${pack_file}" \
              --annotation "org.opencontainers.image.revision=${REVISION}" \
              "${pack_path}:application/vnd.greentic.gtpack.layer.v1+tar"

            echo "Publishing ${pack_file} -> ${stable_ref}"
            oras push "${stable_ref}" \
              --artifact-type application/vnd.greentic.gtpack.v1 \
              --annotation "org.opencontainers.image.title=${pack_file}" \
              --annotation "org.opencontainers.image.revision=${REVISION}" \
              "${pack_path}:application/vnd.greentic.gtpack.layer.v1+tar"
          done

  publish_crates:
    name: Publish to crates.io
    needs: [publish-version-release]
    permissions:
      contents: read
    uses: greenticai/.github/.github/workflows/crates-publish.yml@main
    with:
      crates: "greentic-deployer"
    secrets: inherit