Add release workflow for macOS universal binary - #4
Conversation
Adds a manually-triggered workflow that builds an arm64 + x86_64 universal macOS binary and publishes it as a GitHub Release with auto-generated notes. Updates README with release instructions. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
FranciscoArredondo
left a comment
There was a problem hiding this comment.
Code Review
Overall, this is a solid addition that automates the release process. However, there are several important improvements needed for production readiness. I've added inline comments for each issue.
FranciscoArredondo
left a comment
There was a problem hiding this comment.
Code Review
Overall, this is a solid addition that automates the release process. However, there are several important improvements needed for production readiness. I've added inline comments for each issue.
|
🔴 Critical: Missing error handling in shell commands Location: If any command fails, the workflow may continue and produce invalid artifacts. Recommendation: Add - name: Create universal binary
run: |
set -euo pipefail
lipo -create \
target/release/pokedex \
target/x86_64-apple-darwin/release/pokedex \
-output pokedex |
|
🔴 Critical: Tag creation will fail if tag already exists Location: The workflow will fail if you try to re-run it with the same version, preventing workflow re-execution. Recommendation: Add a check to handle existing tags: - name: Create tag
run: |
set -euo pipefail
# Delete tag if it exists (allows re-running workflow)
git tag -d "v${{ inputs.version }}" 2>/dev/null || true
git push origin ":refs/tags/v${{ inputs.version }}" 2>/dev/null || true
git tag "v${{ inputs.version }}"
git push origin "v${{ inputs.version }}" |
|
🟡 Important: Missing cargo dependency caching Location: The test workflow caches dependencies, but this workflow doesn't, which will significantly slow down builds. Recommendation: Add caching after the "Checkout code" step: - name: Cache cargo dependencies
uses: actions/cache@v4
with:
path: |
~/.cargo/bin/
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
target/
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo- |
|
🟡 Important: No version format validation Location: The version input accepts any string, which could create invalid tags or cause issues. Recommendation: Add validation after checkout: - name: Validate version format
run: |
set -euo pipefail
if ! [[ "${{ inputs.version }}" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "Error: Version must be in semver format (e.g., 1.0.0)"
exit 1
fi |
|
🟡 Important: Missing binary verification Location: The workflow doesn't verify the binary works before releasing it. Recommendation: Add verification after creating the universal binary: - name: Verify binary
run: |
set -euo pipefail
file pokedex
./pokedex --help || ./pokedex --version || echo "Binary verification skipped (no --help/--version flags)" |
|
🟢 Minor: Missing cleanup Location: The Recommendation: Clean up after packaging: - name: Package archive
run: |
set -euo pipefail
tar czf pokedex-macos.tar.gz pokedex
rm pokedex # Clean up binary file |
|
🟢 Minor: Consider adding explicit Location: For clarity, even though Recommendation: permissions:
contents: write
contents: read |
|
💡 Suggestion: Version consistency check Location: Consider adding a check to verify the input version matches Cargo.toml (optional but useful for catching mistakes). Recommendation: - name: Check version consistency
run: |
set -euo pipefail
CARGO_VERSION=$(grep '^version = ' Cargo.toml | cut -d'"' -f2)
INPUT_VERSION="${{ inputs.version }}"
if [ "$CARGO_VERSION" != "$INPUT_VERSION" ]; then
echo "Warning: Cargo.toml version ($CARGO_VERSION) differs from input version ($INPUT_VERSION)"
fi |
- Add semver format validation for version input - Add cargo dependency caching (matching test workflow) - Add set -euo pipefail to multi-line shell scripts - Handle existing tags gracefully for workflow re-runs Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Addressed in 2301d09:
|
|
Re: Error handling in shell commands (@FranciscoArredondo) Added |
|
Re: Tag creation will fail if tag already exists (@FranciscoArredondo) Good catch. The tag step now deletes the existing tag (local + remote) before creating it, allowing safe re-runs. Done in 2301d09. |
|
Re: Missing cargo dependency caching (@FranciscoArredondo) Added cargo caching matching the test workflow. Done in 2301d09. |
|
Re: No version format validation (@FranciscoArredondo) Added a semver regex check as the first step after checkout. Invalid input now fails fast. Done in 2301d09. |
|
Re: Missing binary verification (@FranciscoArredondo) Skipping this one — the app is a TUI with no |
|
Re: Missing cleanup (@FranciscoArredondo) Skipping — the runner is ephemeral so leftover files are discarded automatically after the job. |
|
Re: Explicit Skipping — duplicate YAML keys ( |
|
Re: Version consistency check (@FranciscoArredondo) Skipping — the release version may intentionally differ from |

Summary
workflow_dispatch-triggered GitHub Actions workflow that builds a universal macOS binary (arm64 + x86_64) and publishes it as a GitHub ReleaseTest plan
0.1.0) and confirm the release is created with the correct tarball🤖 Generated with Claude Code