Release #67
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Release | |
| on: | |
| workflow_dispatch: | |
| push: | |
| tags: | |
| - "v*" | |
| concurrency: | |
| group: release-${{ github.ref_name }} | |
| cancel-in-progress: false | |
| permissions: | |
| contents: write | |
| packages: write | |
| jobs: | |
| agent: | |
| runs-on: ${{ matrix.runner }} | |
| strategy: | |
| matrix: | |
| include: | |
| - goos: linux | |
| goarch: amd64 | |
| runner: blacksmith-2vcpu-ubuntu-2404 | |
| - goos: linux | |
| goarch: arm64 | |
| runner: blacksmith-2vcpu-ubuntu-2404-arm | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| - name: Setup Go | |
| uses: actions/setup-go@v6 | |
| with: | |
| go-version-file: agent/go.mod | |
| cache-dependency-path: agent/go.sum | |
| - name: Build | |
| working-directory: agent | |
| env: | |
| GOOS: ${{ matrix.goos }} | |
| GOARCH: ${{ matrix.goarch }} | |
| CGO_ENABLED: 0 | |
| run: | | |
| go build -ldflags="-s -w -X techulus/cloud-agent/internal/agent.Version=${{ github.ref_name }}" -o agent-${{ matrix.goos }}-${{ matrix.goarch }} ./cmd/agent | |
| - name: Upload artifact | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: agent-${{ matrix.goos }}-${{ matrix.goarch }} | |
| path: agent/agent-${{ matrix.goos }}-${{ matrix.goarch }} | |
| retention-days: 1 | |
| cli: | |
| runs-on: ${{ matrix.runner }} | |
| strategy: | |
| matrix: | |
| include: | |
| - goos: darwin | |
| goarch: amd64 | |
| runner: blacksmith-2vcpu-ubuntu-2404 | |
| - goos: darwin | |
| goarch: arm64 | |
| runner: blacksmith-2vcpu-ubuntu-2404-arm | |
| - goos: linux | |
| goarch: amd64 | |
| runner: blacksmith-2vcpu-ubuntu-2404 | |
| - goos: linux | |
| goarch: arm64 | |
| runner: blacksmith-2vcpu-ubuntu-2404-arm | |
| - goos: windows | |
| goarch: amd64 | |
| runner: blacksmith-2vcpu-ubuntu-2404 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| - name: Setup Go | |
| uses: actions/setup-go@v6 | |
| with: | |
| go-version-file: cli/go.mod | |
| cache-dependency-path: cli/go.sum | |
| - name: Build | |
| working-directory: cli | |
| env: | |
| GOOS: ${{ matrix.goos }} | |
| GOARCH: ${{ matrix.goarch }} | |
| CGO_ENABLED: 0 | |
| run: | | |
| ext="" | |
| if [ "${{ matrix.goos }}" = "windows" ]; then ext=".exe"; fi | |
| binary="tc-${{ matrix.goos }}-${{ matrix.goarch }}$ext" | |
| go build -ldflags="-s -w -X main.version=${{ github.ref_name }}" -o "$binary" ./cmd/tc | |
| if [ "${{ matrix.goos }}" != "windows" ]; then | |
| version="${GITHUB_REF_NAME#v}" | |
| version="${version//\//-}" | |
| package_dir=$(mktemp -d) | |
| cp "$binary" "$package_dir/tc" | |
| tar -czf "tc_${version}_${{ matrix.goos }}_${{ matrix.goarch }}.tar.gz" -C "$package_dir" tc | |
| rm -rf "$package_dir" | |
| fi | |
| - name: Upload artifact | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: tc-${{ matrix.goos }}-${{ matrix.goarch }} | |
| path: | | |
| cli/tc-${{ matrix.goos }}-${{ matrix.goarch }}* | |
| cli/tc_*_${{ matrix.goos }}_${{ matrix.goarch }}.tar.gz | |
| retention-days: 1 | |
| release: | |
| needs: [agent, cli, containers] | |
| runs-on: blacksmith-2vcpu-ubuntu-2404 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| - name: Download agent artifacts | |
| uses: actions/download-artifact@v8 | |
| with: | |
| path: binaries | |
| pattern: agent-* | |
| merge-multiple: true | |
| - name: Download CLI artifacts | |
| uses: actions/download-artifact@v8 | |
| with: | |
| path: binaries | |
| pattern: tc-* | |
| merge-multiple: true | |
| - name: Download image digests | |
| uses: actions/download-artifact@v8 | |
| with: | |
| path: image-digests | |
| pattern: release-digest-* | |
| merge-multiple: true | |
| - name: Generate SHA256 checksums | |
| run: | | |
| cd binaries | |
| sha256sum agent-* tc-* tc_* > checksums.txt | |
| - name: Generate release manifest | |
| env: | |
| RELEASE_VERSION: ${{ github.ref_name }} | |
| RELEASE_COMMIT: ${{ github.sha }} | |
| run: | | |
| sha256_pattern='^[0-9a-f]{64}$' | |
| digest_pattern='^sha256:[0-9a-f]{64}$' | |
| agent_amd64=$(sha256sum binaries/agent-linux-amd64 | awk '{print $1}') | |
| agent_arm64=$(sha256sum binaries/agent-linux-arm64 | awk '{print $1}') | |
| compose_production=$(sha256sum deployment/compose.production.yml | awk '{print $1}') | |
| compose_postgres=$(sha256sum deployment/compose.postgres.yml | awk '{print $1}') | |
| web_digest=$(cat image-digests/web) | |
| registry_digest=$(cat image-digests/registry) | |
| updater_digest=$(cat image-digests/updater) | |
| for checksum in "$agent_amd64" "$agent_arm64" "$compose_production" "$compose_postgres"; do | |
| [[ "$checksum" =~ $sha256_pattern ]] | |
| done | |
| for digest in "$web_digest" "$registry_digest" "$updater_digest"; do | |
| [[ "$digest" =~ $digest_pattern ]] | |
| done | |
| [[ "$RELEASE_VERSION" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?$ ]] | |
| [[ "$RELEASE_COMMIT" =~ ^[0-9a-f]{40}$ ]] | |
| jq -n \ | |
| --arg version "$RELEASE_VERSION" \ | |
| --arg commit "$RELEASE_COMMIT" \ | |
| --arg agent_amd64 "$agent_amd64" \ | |
| --arg agent_arm64 "$agent_arm64" \ | |
| --arg compose_production "$compose_production" \ | |
| --arg compose_postgres "$compose_postgres" \ | |
| --arg web_digest "$web_digest" \ | |
| --arg registry_digest "$registry_digest" \ | |
| --arg updater_digest "$updater_digest" \ | |
| '{ | |
| version: $version, | |
| commit: $commit, | |
| binaries: { | |
| "agent-linux-amd64": $agent_amd64, | |
| "agent-linux-arm64": $agent_arm64 | |
| }, | |
| composeFiles: { | |
| "deployment/compose.production.yml": $compose_production, | |
| "deployment/compose.postgres.yml": $compose_postgres | |
| }, | |
| images: { | |
| web: $web_digest, | |
| registry: $registry_digest, | |
| updater: $updater_digest | |
| } | |
| }' > binaries/release-manifest.json | |
| - name: Create GitHub release | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| gh release create "${{ github.ref_name }}" \ | |
| --repo ${{ github.repository }} \ | |
| --title "${{ github.ref_name }}" \ | |
| --generate-notes \ | |
| binaries/agent-* binaries/tc-* binaries/tc_* binaries/checksums.txt binaries/release-manifest.json | |
| homebrew: | |
| needs: release | |
| if: startsWith(github.ref, 'refs/tags/v') | |
| runs-on: blacksmith-2vcpu-ubuntu-2404 | |
| concurrency: | |
| group: homebrew-tap | |
| cancel-in-progress: false | |
| steps: | |
| - name: Download CLI artifacts | |
| uses: actions/download-artifact@v8 | |
| with: | |
| path: binaries | |
| pattern: tc-* | |
| merge-multiple: true | |
| - name: Checkout Homebrew tap | |
| uses: actions/checkout@v6 | |
| with: | |
| repository: techulus/homebrew-tap | |
| token: ${{ secrets.HOMEBREW_TAP_TOKEN }} | |
| path: homebrew-tap | |
| - name: Update Homebrew formula | |
| run: | | |
| version="${GITHUB_REF_NAME#v}" | |
| darwin_amd64_sha=$(sha256sum "binaries/tc_${version}_darwin_amd64.tar.gz" | awk '{print $1}') | |
| darwin_arm64_sha=$(sha256sum "binaries/tc_${version}_darwin_arm64.tar.gz" | awk '{print $1}') | |
| linux_amd64_sha=$(sha256sum "binaries/tc_${version}_linux_amd64.tar.gz" | awk '{print $1}') | |
| linux_arm64_sha=$(sha256sum "binaries/tc_${version}_linux_arm64.tar.gz" | awk '{print $1}') | |
| cat > homebrew-tap/Formula/tc.rb <<EOF | |
| # typed: false | |
| # frozen_string_literal: true | |
| # This file was generated by the Techulus Cloud release workflow. DO NOT EDIT. | |
| class Tc < Formula | |
| desc "Techulus Cloud CLI" | |
| homepage "https://github.com/${GITHUB_REPOSITORY}" | |
| version "${version}" | |
| license "AGPL-3.0-only" | |
| on_macos do | |
| if Hardware::CPU.intel? | |
| url "https://github.com/${GITHUB_REPOSITORY}/releases/download/${GITHUB_REF_NAME}/tc_${version}_darwin_amd64.tar.gz" | |
| sha256 "${darwin_amd64_sha}" | |
| define_method(:install) do | |
| bin.install "tc" | |
| end | |
| end | |
| if Hardware::CPU.arm? | |
| url "https://github.com/${GITHUB_REPOSITORY}/releases/download/${GITHUB_REF_NAME}/tc_${version}_darwin_arm64.tar.gz" | |
| sha256 "${darwin_arm64_sha}" | |
| define_method(:install) do | |
| bin.install "tc" | |
| end | |
| end | |
| end | |
| on_linux do | |
| if Hardware::CPU.intel? && Hardware::CPU.is_64_bit? | |
| url "https://github.com/${GITHUB_REPOSITORY}/releases/download/${GITHUB_REF_NAME}/tc_${version}_linux_amd64.tar.gz" | |
| sha256 "${linux_amd64_sha}" | |
| define_method(:install) do | |
| bin.install "tc" | |
| end | |
| end | |
| if Hardware::CPU.arm? && Hardware::CPU.is_64_bit? | |
| url "https://github.com/${GITHUB_REPOSITORY}/releases/download/${GITHUB_REF_NAME}/tc_${version}_linux_arm64.tar.gz" | |
| sha256 "${linux_arm64_sha}" | |
| define_method(:install) do | |
| bin.install "tc" | |
| end | |
| end | |
| end | |
| test do | |
| assert_match version.to_s, shell_output("#{bin}/tc version") | |
| end | |
| end | |
| EOF | |
| cd homebrew-tap | |
| git config user.name "github-actions[bot]" | |
| git config user.email "41898282+github-actions[bot]@users.noreply.github.com" | |
| git add Formula/tc.rb | |
| if git diff --cached --quiet; then | |
| echo "Homebrew formula is already up to date." | |
| exit 0 | |
| fi | |
| git commit -m "Brew formula update for tc version ${GITHUB_REF_NAME}" | |
| for attempt in 1 2 3; do | |
| if git push; then | |
| exit 0 | |
| fi | |
| if [ "$attempt" -eq 3 ]; then | |
| echo "Failed to push the Homebrew formula after $attempt attempts." >&2 | |
| exit 1 | |
| fi | |
| git pull --rebase origin main | |
| done | |
| container: | |
| name: Build ${{ matrix.image }} (${{ matrix.arch }}) | |
| runs-on: ${{ matrix.runner }} | |
| strategy: | |
| matrix: | |
| include: | |
| - image: web | |
| context: web | |
| arch: amd64 | |
| platform: linux/amd64 | |
| runner: blacksmith-2vcpu-ubuntu-2404 | |
| - image: web | |
| context: web | |
| arch: arm64 | |
| platform: linux/arm64 | |
| runner: blacksmith-2vcpu-ubuntu-2404-arm | |
| - image: registry | |
| context: registry | |
| arch: amd64 | |
| platform: linux/amd64 | |
| runner: blacksmith-2vcpu-ubuntu-2404 | |
| - image: registry | |
| context: registry | |
| arch: arm64 | |
| platform: linux/arm64 | |
| runner: blacksmith-2vcpu-ubuntu-2404-arm | |
| - image: updater | |
| context: deployment/updater | |
| arch: amd64 | |
| platform: linux/amd64 | |
| runner: blacksmith-2vcpu-ubuntu-2404 | |
| - image: updater | |
| context: deployment/updater | |
| arch: arm64 | |
| platform: linux/arm64 | |
| runner: blacksmith-2vcpu-ubuntu-2404-arm | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| - name: Set up Docker builder | |
| uses: useblacksmith/setup-docker-builder@v1 | |
| - name: Login to GHCR | |
| uses: docker/login-action@v4 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Build and push | |
| id: build | |
| uses: useblacksmith/build-push-action@v2 | |
| with: | |
| context: ${{ matrix.context }} | |
| tags: ghcr.io/${{ github.repository }}/${{ matrix.image }} | |
| platforms: ${{ matrix.platform }} | |
| build-args: ${{ matrix.image == 'web' && format('APP_VERSION={0}', github.ref_name) || '' }} | |
| outputs: type=image,push-by-digest=true,name-canonical=true,push=true | |
| - name: Export digest | |
| run: | | |
| mkdir -p /tmp/digests | |
| touch "/tmp/digests/${DIGEST#sha256:}" | |
| env: | |
| DIGEST: ${{ steps.build.outputs.digest }} | |
| - name: Upload digest | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: digest-${{ matrix.image }}-${{ matrix.arch }} | |
| path: /tmp/digests/* | |
| if-no-files-found: error | |
| retention-days: 1 | |
| containers: | |
| name: Publish ${{ matrix.image }} manifest | |
| needs: container | |
| runs-on: blacksmith-2vcpu-ubuntu-2404 | |
| strategy: | |
| matrix: | |
| image: [web, registry, updater] | |
| steps: | |
| - name: Download digests | |
| uses: actions/download-artifact@v8 | |
| with: | |
| path: /tmp/digests | |
| pattern: digest-${{ matrix.image }}-* | |
| merge-multiple: true | |
| - name: Login to GHCR | |
| uses: docker/login-action@v4 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Create and push multi-platform manifest | |
| working-directory: /tmp/digests | |
| run: | | |
| image="ghcr.io/${{ github.repository }}/${{ matrix.image }}" | |
| docker buildx imagetools create \ | |
| --tag "$image:${{ github.ref_name }}" \ | |
| --tag "$image:tip" \ | |
| $(printf "$image@sha256:%s " *) | |
| - name: Export multi-platform manifest digest | |
| run: | | |
| image="ghcr.io/${{ github.repository }}/${{ matrix.image }}:${{ github.ref_name }}" | |
| mkdir -p /tmp/release-digests | |
| docker buildx imagetools inspect "$image" --format '{{json .Manifest}}' \ | |
| | jq -er '.digest | select(test("^sha256:[0-9a-f]{64}$"))' \ | |
| > "/tmp/release-digests/${{ matrix.image }}" | |
| - name: Upload multi-platform manifest digest | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: release-digest-${{ matrix.image }} | |
| path: /tmp/release-digests/${{ matrix.image }} | |
| if-no-files-found: error | |
| retention-days: 1 |