Release #13
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: | |
| inputs: | |
| release-type: | |
| description: "Release type" | |
| required: true | |
| type: choice | |
| options: | |
| - patch | |
| - minor | |
| - major | |
| permissions: | |
| contents: write | |
| issues: read | |
| actions: read | |
| defaults: | |
| run: | |
| shell: bash -euxo pipefail {0} | |
| jobs: | |
| prepare-release: | |
| name: Prepare Release | |
| runs-on: ubuntu-latest | |
| outputs: | |
| version: ${{ steps.update-version.outputs.version }} | |
| release-tag: ${{ steps.create-release.outputs.release-tag }} | |
| temp-branch: ${{ steps.create-temp-branch.outputs.branch }} | |
| steps: | |
| - name: Check if running on allowed branch | |
| run: | | |
| if [[ "${{ github.ref_name }}" == "main" || "${{ github.ref_name }}" == "release/"* ]]; then | |
| echo "✅ Running on allowed branch: ${{ github.ref_name }}" | |
| else | |
| echo "❌ Release workflow can only be triggered from 'main' or 'release/*' branches" | |
| echo "Current branch: ${{ github.ref_name }}" | |
| exit 1 | |
| fi | |
| - name: Checkout repository | |
| uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 | |
| with: | |
| token: ${{ github.token }} | |
| fetch-depth: 0 | |
| fetch-tags: true | |
| - name: Create temporary branch | |
| id: create-temp-branch | |
| run: | | |
| TEMP_BRANCH="release-prep-$(date +%s)" | |
| git checkout -b "${TEMP_BRANCH:?}" | |
| echo "branch=${TEMP_BRANCH:?}" >> $GITHUB_OUTPUT | |
| - name: Setup Rust toolchain | |
| uses: actions-rust-lang/setup-rust-toolchain@1780873c7b576612439a134613cc4cc74ce5538c # v1.15.2 | |
| with: | |
| toolchain: stable | |
| rustflags: "" | |
| - name: Install cargo-quickinstall | |
| run: cargo install cargo-quickinstall | |
| - name: Install cargo-edit | |
| run: cargo quickinstall cargo-edit | |
| - name: Update version in Cargo.toml | |
| id: update-version | |
| run: | | |
| cargo set-version --package ${{ github.event.repository.name }} --bump "${{ github.event.inputs.release-type }}" | |
| VERSION=$(cargo metadata --no-deps --format-version 1 | jq -r '.packages[] | select(.name == "${{ github.event.repository.name }}") | .version') | |
| echo "version=${VERSION?}" >> $GITHUB_OUTPUT | |
| - name: Install git-cliff | |
| run: | | |
| # Install git-cliff for generating release notes | |
| CLIFF_VERSION="2.10.1" | |
| curl -sSfL "https://github.com/orhun/git-cliff/releases/download/v${CLIFF_VERSION}/git-cliff-${CLIFF_VERSION}-x86_64-unknown-linux-gnu.tar.gz" | tar -xz | |
| sudo mv git-cliff-*/git-cliff /usr/local/bin/ | |
| git-cliff --version | |
| - name: Generate release notes | |
| id: release-notes | |
| run: | | |
| VERSION=${{ steps.update-version.outputs.version }} | |
| PREVIOUS_TAG=$(git tag -l "v*.*.*" --merged HEAD --sort=-version:refname | head -1 || echo "") | |
| git-cliff --tag "v${VERSION:?}" --output RELEASE_NOTES.md --verbose "${PREVIOUS_TAG:?}..HEAD" | |
| env: | |
| GITHUB_REPO: ${{ github.repository }} | |
| GITHUB_TOKEN: ${{ github.token }} | |
| - name: Create draft release | |
| id: create-release | |
| run: | | |
| VERSION=${{ steps.update-version.outputs.version }} | |
| # Check if version is a pre-release (contains hyphen) | |
| if [[ "${VERSION}" == *-* ]]; then | |
| PRERELEASE_FLAG="--prerelease" | |
| else | |
| PRERELEASE_FLAG="" | |
| fi | |
| gh release create "v${VERSION:?}" \ | |
| --title "v${VERSION:?}" \ | |
| --notes-file RELEASE_NOTES.md \ | |
| --draft \ | |
| ${PRERELEASE_FLAG} | |
| echo "release-tag=v${VERSION:?}" >> $GITHUB_OUTPUT | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| - name: Commit version update | |
| run: | | |
| git config --local user.name "missionis[bot]" | |
| git config --local user.email "234988995+missionis[bot]@users.noreply.github.com" | |
| git add Cargo.toml Cargo.lock | |
| git commit -m "chore(release): bump version to ${{ steps.update-version.outputs.version }}" | |
| git push origin "refs/heads/${{ steps.create-temp-branch.outputs.branch }}" | |
| build: | |
| name: Build and Upload Binaries | |
| needs: prepare-release | |
| uses: ./.github/workflows/build.yml | |
| with: | |
| release: ${{ needs.prepare-release.outputs.release-tag }} | |
| ref: ${{ needs.prepare-release.outputs.temp-branch }} | |
| permissions: | |
| contents: write | |
| issues: read | |
| actions: read | |
| finalize-release: | |
| name: Finalize Release | |
| runs-on: ubuntu-latest | |
| needs: [prepare-release, build] | |
| steps: | |
| - name: Generate GitHub App Token | |
| id: generate-token | |
| uses: actions/create-github-app-token@29824e69f54612133e76f7eaac726eef6c875baf # v2.2.1 | |
| with: | |
| app-id: ${{ secrets.APP_ID }} | |
| private-key: ${{ secrets.APP_PRIVATE_KEY }} | |
| owner: ${{ github.repository_owner }} | |
| repositories: ${{ github.event.repository.name }},action-hub | |
| - name: Checkout repository | |
| uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 | |
| with: | |
| token: ${{ steps.generate-token.outputs.token }} | |
| ref: ${{ needs.prepare-release.outputs.temp-branch }} | |
| fetch-depth: 0 | |
| - name: Install Nix | |
| uses: DeterminateSystems/nix-installer-action@c5a866b6ab867e88becbed4467b93592bce69f8a # v21 | |
| - name: Generate Nix binary hashes file | |
| run: | | |
| VERSION=${{ needs.prepare-release.outputs.version }} | |
| RELEASE_TAG=${{ needs.prepare-release.outputs.release-tag }} | |
| # Install nixfmt for pretty formatting | |
| nix profile add nixpkgs#nixfmt | |
| # Get filtered assets and convert hex hashes to SRI format | |
| gh release view "${RELEASE_TAG:?}" --json assets --jq '.assets | |
| | map(select(.name | test("^${{ github.event.repository.name }}-(linux-(x86_64|arm64)-musl|macos-(x86_64|arm64))\\.tar\\.gz$"))) | |
| | .[] | .name + ":" + (.digest | ltrimstr("sha256:"))' | \ | |
| while IFS=':' read -r name hex; do | |
| echo "${name:?}:sha256-$(echo -n "${hex:?}" | xxd -r -p | base64)" | |
| done > /tmp/assets-sri.txt | |
| # Convert SRI hashes to JSON format | |
| jq -R -s --arg version "${VERSION:?}" ' | |
| {($version): ( | |
| split("\n") | |
| | map(select(length > 0) | split(":") | {key: .[0], value: .[1]}) | |
| | from_entries | |
| )}' < /tmp/assets-sri.txt > /tmp/hashes.json | |
| # Convert JSON to Nix and format | |
| nix eval --impure --expr 'builtins.fromJSON (builtins.readFile "/tmp/hashes.json")' | \ | |
| nixfmt > nix/binary-hashes.nix | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| - name: Commit hash updates and create final tag | |
| run: | | |
| VERSION=${{ needs.prepare-release.outputs.version }} | |
| git config --local user.name "missionis[bot]" | |
| git config --local user.email "234988995+missionis[bot]@users.noreply.github.com" | |
| git add nix/binary-hashes.nix | |
| git commit -m "build(nix): update binary hashes for v${VERSION:?}" | |
| # Push the commit to remote branch | |
| git push origin "refs/heads/${{ needs.prepare-release.outputs.temp-branch }}" | |
| # Create final tag pointing to commit with all changes | |
| git tag "v${VERSION:?}" | |
| - name: Merge into the target branch and publish release | |
| run: | | |
| VERSION=${{ needs.prepare-release.outputs.version }} | |
| RELEASE_TAG=${{ needs.prepare-release.outputs.release-tag }} | |
| TEMP_BRANCH=${{ needs.prepare-release.outputs.temp-branch }} | |
| TARGET_BRANCH=${{ github.ref_name }} | |
| # Merge the temporary branch into the target branch | |
| git checkout -B "${TARGET_BRANCH:?}" "origin/${TARGET_BRANCH:?}" | |
| git merge "refs/heads/${TEMP_BRANCH:?}" | |
| git push origin "refs/heads/${TARGET_BRANCH:?}" | |
| # Push the release tag | |
| git push origin "refs/tags/v${VERSION:?}" | |
| # Check if release is marked as pre-release and publish accordingly | |
| IS_PRERELEASE=$(gh release view "${RELEASE_TAG:?}" --json isPrerelease --jq '.isPrerelease') | |
| # Update latest tag if it exists and release is not a pre-release | |
| if [[ "${IS_PRERELEASE:?}" == "false" ]] && [ "$(git tag -l latest --merged HEAD)" = latest ]; then | |
| gh release edit "${RELEASE_TAG:?}" --tag "v${VERSION:?}" --draft=false --latest | |
| git tag -f latest HEAD | |
| git push -f origin refs/tags/latest | |
| else | |
| gh release edit "${RELEASE_TAG:?}" --tag "v${VERSION:?}" --draft=false | |
| fi | |
| # Delete the temporary branch | |
| git push origin --delete "refs/heads/${TEMP_BRANCH:?}" || true | |
| env: | |
| GH_TOKEN: ${{ steps.generate-token.outputs.token }} | |
| - name: Trigger publish workflow to distribute release | |
| run: | | |
| VERSION=${{ needs.prepare-release.outputs.version }} | |
| RELEASE_TAG=${{ needs.prepare-release.outputs.release-tag }} | |
| IS_PRERELEASE=$(gh release view "${RELEASE_TAG:?}" --json isPrerelease --jq '.isPrerelease') | |
| if [[ "${IS_PRERELEASE:?}" == "false" ]]; then | |
| gh workflow run publish.yml \ | |
| --repo "${{ github.repository_owner }}/action-hub" \ | |
| --field package="${{ github.event.repository.name }}" | |
| fi | |
| env: | |
| GH_TOKEN: ${{ steps.generate-token.outputs.token }} |