fix: resolve --force-transfer-mode being a no-op for missing transfer… #81
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: | |
| push: | |
| branches: | |
| - main | |
| workflow_dispatch: | |
| concurrency: | |
| group: release | |
| cancel-in-progress: false | |
| permissions: | |
| contents: write | |
| pull-requests: write | |
| packages: write | |
| jobs: | |
| # Step 1: Detect changesets and either create a version PR or flag for release | |
| changesets: | |
| runs-on: ubuntu-latest | |
| outputs: | |
| should_release: ${{ steps.detect.outputs.should_release }} | |
| has_cli_release: ${{ steps.detect.outputs.has_cli_release }} | |
| has_docker_release: ${{ steps.detect.outputs.has_docker_release }} | |
| cli_version: ${{ steps.detect.outputs.cli_version }} | |
| docker_version: ${{ steps.detect.outputs.docker_version }} | |
| hasChangesets: ${{ steps.changesets.outputs.hasChangesets }} | |
| steps: | |
| - name: Generate app token | |
| id: app-token | |
| uses: actions/create-github-app-token@v1 | |
| with: | |
| app-id: ${{ secrets.APP_ID }} | |
| private-key: ${{ secrets.APP_PRIVATE_KEY }} | |
| - uses: actions/checkout@v4 | |
| with: | |
| token: ${{ steps.app-token.outputs.token }} | |
| - uses: oven-sh/setup-bun@v2 | |
| with: | |
| bun-version: latest | |
| - name: Install dependencies | |
| run: bun install --frozen-lockfile --ignore-scripts | |
| - name: Create release Pull Request or detect release merge | |
| id: changesets | |
| uses: changesets/action@v1 | |
| with: | |
| version: bun run version | |
| publish: echo "publish-placeholder" | |
| title: 'Version Packages' | |
| env: | |
| GITHUB_TOKEN: ${{ steps.app-token.outputs.token }} | |
| - name: Detect if this is a release merge | |
| id: detect | |
| run: | | |
| CLI_VERSION=$(jq -r '.version' packages/podkit-cli/package.json) | |
| CLI_TAG="podkit@$CLI_VERSION" | |
| DOCKER_VERSION=$(jq -r '.version' packages/podkit-docker/package.json) | |
| DOCKER_TAG="docker@$DOCKER_VERSION" | |
| echo "cli_version=$CLI_VERSION" >> "$GITHUB_OUTPUT" | |
| echo "docker_version=$DOCKER_VERSION" >> "$GITHUB_OUTPUT" | |
| if [ "${{ steps.changesets.outputs.hasChangesets }}" = "false" ]; then | |
| # No pending changesets — check if this is a release-worthy commit | |
| COMMIT_MSG=$(git log -1 --format="%s") | |
| echo "Commit message: $COMMIT_MSG" | |
| IS_RELEASE=false | |
| # Release if: Version Packages merge OR manual dispatch with unreleased version | |
| if echo "$COMMIT_MSG" | grep -q "Version Packages"; then | |
| IS_RELEASE=true | |
| echo "Release detected — Version Packages merge" | |
| elif [ "${{ github.event_name }}" = "workflow_dispatch" ]; then | |
| IS_RELEASE=true | |
| echo "Manual dispatch — checking for unreleased versions" | |
| fi | |
| if [ "$IS_RELEASE" = "true" ]; then | |
| git fetch --tags | |
| if git rev-parse "$CLI_TAG" >/dev/null 2>&1; then | |
| echo "has_cli_release=false" >> "$GITHUB_OUTPUT" | |
| echo "CLI version $CLI_VERSION already released" | |
| else | |
| echo "has_cli_release=true" >> "$GITHUB_OUTPUT" | |
| echo "CLI version $CLI_VERSION is new — will release" | |
| fi | |
| if git rev-parse "$DOCKER_TAG" >/dev/null 2>&1; then | |
| echo "has_docker_release=false" >> "$GITHUB_OUTPUT" | |
| echo "Docker version $DOCKER_VERSION already released" | |
| else | |
| echo "has_docker_release=true" >> "$GITHUB_OUTPUT" | |
| echo "Docker version $DOCKER_VERSION is new — will release" | |
| fi | |
| else | |
| echo "has_cli_release=false" >> "$GITHUB_OUTPUT" | |
| echo "has_docker_release=false" >> "$GITHUB_OUTPUT" | |
| echo "No changesets and not a version merge — nothing to do" | |
| fi | |
| else | |
| echo "has_cli_release=false" >> "$GITHUB_OUTPUT" | |
| echo "has_docker_release=false" >> "$GITHUB_OUTPUT" | |
| echo "Pending changesets found — version PR will be created/updated" | |
| fi | |
| # Set should_release based on whether either component needs releasing. | |
| # Re-read the outputs file since they were just written above. | |
| if grep -q "has_cli_release=true" "$GITHUB_OUTPUT" || grep -q "has_docker_release=true" "$GITHUB_OUTPUT"; then | |
| echo "should_release=true" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "should_release=false" >> "$GITHUB_OUTPUT" | |
| fi | |
| # Step 2: Build native prebuilds + compile CLI binaries for each platform | |
| # Prebuild cache is shared with verify-release.yml — on typical version | |
| # merges (no native code changes), prebuilds hit cache and only TypeScript | |
| # build + Bun compile runs. | |
| build: | |
| needs: changesets | |
| if: needs.changesets.outputs.should_release == 'true' | |
| uses: ./.github/workflows/build-platform.yml | |
| with: | |
| upload-artifacts: true | |
| # Step 3: Create GitHub Release with all platform tarballs (CLI releases only) | |
| release: | |
| needs: [changesets, build] | |
| if: needs.build.result == 'success' && needs.changesets.outputs.has_cli_release == 'true' | |
| runs-on: ubuntu-latest | |
| name: Create GitHub Release | |
| outputs: | |
| version: ${{ needs.changesets.outputs.cli_version }} | |
| tag: ${{ steps.tag.outputs.tag }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set tag | |
| id: tag | |
| run: | | |
| echo "tag=podkit@${{ needs.changesets.outputs.cli_version }}" >> "$GITHUB_OUTPUT" | |
| - name: Download all tarballs | |
| uses: actions/download-artifact@v4 | |
| with: | |
| pattern: podkit-* | |
| path: release-assets/ | |
| merge-multiple: true | |
| - name: List release assets | |
| run: ls -la release-assets/ | |
| - name: Generate SHA256 checksums | |
| working-directory: release-assets | |
| run: | | |
| sha256sum podkit-*.tar.gz > SHA256SUMS.txt | |
| cat SHA256SUMS.txt | |
| - name: Build release notes | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| NOTES_FILE="release-notes.md" | |
| VERSION="${{ needs.changesets.outputs.cli_version }}" | |
| : > "$NOTES_FILE" | |
| # Add version PR description at the top if available | |
| PR_BODY=$(gh pr list --state merged --search "\"Version Packages\" in:title" --limit 1 --json body --jq '.[0].body // empty') | |
| if [ -n "$PR_BODY" ]; then | |
| echo "$PR_BODY" >> "$NOTES_FILE" | |
| echo "" >> "$NOTES_FILE" | |
| echo "---" >> "$NOTES_FILE" | |
| echo "" >> "$NOTES_FILE" | |
| fi | |
| # Add changelog from CHANGELOG.md | |
| echo "## Changelog" >> "$NOTES_FILE" | |
| echo "" >> "$NOTES_FILE" | |
| CHANGELOG_FILE="packages/podkit-cli/CHANGELOG.md" | |
| if [ -f "$CHANGELOG_FILE" ]; then | |
| # Extract the latest version section (from first ## to the next ##) | |
| awk '/^## [0-9]/{if(found) exit; found=1; next} found{print}' "$CHANGELOG_FILE" >> "$NOTES_FILE" | |
| else | |
| echo "Release $VERSION" >> "$NOTES_FILE" | |
| fi | |
| echo "" >> "$NOTES_FILE" | |
| # Add checksums | |
| echo "## Checksums (SHA256)" >> "$NOTES_FILE" | |
| echo "" >> "$NOTES_FILE" | |
| echo '```' >> "$NOTES_FILE" | |
| cat release-assets/SHA256SUMS.txt >> "$NOTES_FILE" | |
| echo '```' >> "$NOTES_FILE" | |
| echo "--- Release notes ---" | |
| cat "$NOTES_FILE" | |
| - name: Create tag and GitHub Release | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| TAG="${{ steps.tag.outputs.tag }}" | |
| VERSION="${{ needs.changesets.outputs.cli_version }}" | |
| if git rev-parse "$TAG" >/dev/null 2>&1; then | |
| echo "Tag $TAG already exists — skipping release" | |
| exit 0 | |
| fi | |
| git tag "$TAG" | |
| git push origin "$TAG" | |
| gh release create "$TAG" \ | |
| --title "podkit $VERSION" \ | |
| --notes-file release-notes.md \ | |
| release-assets/podkit-*.tar.gz \ | |
| release-assets/SHA256SUMS.txt | |
| # Step 4: Build and push Docker image to GHCR (Docker releases only) | |
| docker: | |
| needs: [changesets, build] | |
| if: needs.build.result == 'success' && needs.changesets.outputs.has_docker_release == 'true' | |
| uses: ./.github/workflows/docker.yml | |
| with: | |
| version: ${{ needs.changesets.outputs.docker_version }} | |
| push: true | |
| permissions: | |
| contents: read | |
| packages: write | |
| # Step 4b: Tag Docker release after successful push | |
| docker-tag: | |
| needs: [changesets, docker] | |
| if: needs.docker.result == 'success' | |
| runs-on: ubuntu-latest | |
| name: Tag Docker Release | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Create Docker release tag | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| TAG="docker@${{ needs.changesets.outputs.docker_version }}" | |
| if git rev-parse "$TAG" >/dev/null 2>&1; then | |
| echo "Tag $TAG already exists" | |
| else | |
| git tag "$TAG" | |
| git push origin "$TAG" | |
| echo "Created tag $TAG" | |
| fi | |
| # Step 5: Update the Homebrew formula in the tap repository (CLI releases only) | |
| update-homebrew: | |
| needs: [changesets, release] | |
| if: needs.release.result == 'success' | |
| runs-on: ubuntu-latest | |
| continue-on-error: true | |
| name: Update Homebrew Formula | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Download checksums from release | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| TAG="${{ needs.release.outputs.tag }}" | |
| mkdir -p checksums | |
| gh release download "$TAG" --pattern "SHA256SUMS.txt" --dir checksums | |
| - name: Checkout homebrew-podkit | |
| uses: actions/checkout@v4 | |
| with: | |
| repository: jvgomg/homebrew-podkit | |
| path: homebrew-tap | |
| ssh-key: ${{ secrets.HOMEBREW_TAP_DEPLOY_KEY }} | |
| - name: Update formula | |
| run: | | |
| VERSION="${{ needs.release.outputs.version }}" | |
| ./tools/update-homebrew-formula.sh "$VERSION" homebrew-tap/Formula/podkit.rb checksums/SHA256SUMS.txt | |
| - name: Commit and push | |
| working-directory: homebrew-tap | |
| run: | | |
| VERSION="${{ needs.release.outputs.version }}" | |
| git config user.name "github-actions[bot]" | |
| git config user.email "github-actions[bot]@users.noreply.github.com" | |
| git add Formula/podkit.rb | |
| git diff --cached --quiet && echo "No changes to commit" && exit 0 | |
| git commit -m "Update podkit to $VERSION" | |
| git push |