Skip to content

Copilot/setup GitHub build release#35

Draft
vordenken wants to merge 4 commits intodevelopfrom
copilot/setup-github-build-release
Draft

Copilot/setup GitHub build release#35
vordenken wants to merge 4 commits intodevelopfrom
copilot/setup-github-build-release

Conversation

@vordenken
Copy link
Copy Markdown
Owner

@vordenken vordenken commented Apr 2, 2026

  • Understand current workflow and issues
  • Rewrite .github/workflows/build-release.yml:
    • Replace "Prepare zip" with create-dmg to produce AutoPiP.dmg
    • Move Sparkle EdDSA signing BEFORE the GitHub Release step
    • Sign the DMG locally (no re-download), then attach the signed artifact to the release
    • Update all references from .zip.dmg
    • Update appcast download URL to .dmg
  • Update README.md to reference AutoPiP.dmg instead of AutoPiP.zip
  • Code review — passed (1 minor doc suggestion, already addressed by existing example)
  • CodeQL security check — no alerts

Copilot AI and others added 3 commits April 2, 2026 21:06
- Build and archive the macOS app on macos-15 runners
- Support optional code signing via repository secrets
- Create GitHub Release with AutoPiP.zip on tag push (v*)
- Support manual workflow dispatch for testing
- Add build & release documentation to README

Agent-Logs-Url: https://github.com/vordenken/AutoPiP/sessions/47b39758-17c2-47bd-bdc1-4212a817ceb9

Co-authored-by: vordenken <62395860+vordenken@users.noreply.github.com>
…flow

- Add semver.txt as single source of truth for versioning
- Push to main → stable release (v{version}), push to develop → beta release (v{version}-beta)
- Auto-set MARKETING_VERSION and CURRENT_PROJECT_VERSION in Xcode project
- Auto-create git tags and GitHub Releases
- Auto-update appcast.xml on main for Sparkle (with beta channel support)
- Optional Sparkle EdDSA signing via SPARKLE_PRIVATE_KEY secret
- Update README with new release workflow documentation

Agent-Logs-Url: https://github.com/vordenken/AutoPiP/sessions/47b39758-17c2-47bd-bdc1-4212a817ceb9

Co-authored-by: vordenken <62395860+vordenken@users.noreply.github.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 2, 2026

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 97c43c7c-8cce-485c-b3da-4a63641e3b1d

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • ✅ Review completed - (🔄 Check again to review again)
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch copilot/setup-github-build-release

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@sourcery-ai
Copy link
Copy Markdown

sourcery-ai bot commented Apr 2, 2026

Reviewer's Guide

Adds a macOS GitHub Actions workflow that automates versioned builds, GitHub releases, and Sparkle appcast updates driven by a new semver.txt file, and documents the process in the README.

Sequence diagram for automated build, release, and appcast update

sequenceDiagram
  actor Developer
  participant GitHubRepo
  participant Workflow as BuildReleaseWorkflow
  participant Runner as MacOSRunner
  participant Xcode as Xcodebuild
  participant GH as GitHubReleases
  participant Sparkle as SparkleTools

  Developer->>GitHubRepo: Update semver.txt
  Developer->>GitHubRepo: Push to main or develop
  GitHubRepo-->>Workflow: Trigger on push (semver.txt)

  Workflow->>Runner: Start job build-and-release
  Runner->>GitHubRepo: Checkout repository
  Runner->>Runner: Read semver.txt
  Runner->>Runner: Derive tag/channel (stable or beta)
  Runner->>GitHubRepo: Check if tag already exists
  alt Tag exists
    Runner->>Runner: Skip release creation
  else New tag
    Runner->>Runner: Import signing certificate (if secret present)
    Runner->>GitHubRepo: Update MARKETING_VERSION and CURRENT_PROJECT_VERSION
    Runner->>Xcode: Resolve packages and archive app
    Xcode-->>Runner: AutoPiP.xcarchive
    Runner->>Runner: Create AutoPiP.zip
    Runner->>GH: Create tag and GitHub Release with AutoPiP.zip

    opt SPARKLE_PRIVATE_KEY configured
      Runner->>Sparkle: Download Sparkle tools
      Runner->>Sparkle: sign_update AutoPiP.zip
      Sparkle-->>Runner: EdDSA signature
    end

    Runner->>GitHubRepo: Update appcast.xml with new item
    Runner->>GitHubRepo: Commit and push appcast.xml to main
  end

  Runner->>Runner: Cleanup temporary keychain
Loading

File-Level Changes

Change Details Files
Introduce GitHub Actions workflow to build, sign, package, and release stable and beta artifacts, including Sparkle appcast updates.
  • Trigger workflow on pushes to main/develop that modify semver.txt and on manual workflow_dispatch
  • Read and validate semantic version from semver.txt, derive tag/prerelease/channel based on branch, and skip if tag already exists
  • Optionally import a base64-encoded signing certificate into a temporary keychain and toggle ad‑hoc signing when unavailable
  • Inject MARKETING_VERSION and CURRENT_PROJECT_VERSION into the Xcode project, resolve Swift packages, archive the app, and zip the resulting .app
  • Upload the zip as a build artifact and publish a Git tag and GitHub Release with prerelease flag for beta channel
  • Generate an optional Sparkle EdDSA signature, insert a new entry into appcast.xml with channel-specific metadata, and push the updated appcast back to main
  • Clean up the temporary signing keychain at the end of the job
.github/workflows/build-release.yml
Add semver.txt as the single source of truth for release versioning.
  • Create semver.txt to hold the semantic version string consumed by the workflow for tag and release generation
semver.txt
Document the new automated build and release workflow and required secrets.
  • Describe the GitHub Actions-based build and release process for stable and beta channels, driven by semver.txt
  • Explain how to bump versions, trigger releases from branches or manually via the Actions tab, and what the workflow does end-to-end
  • List and describe optional repository secrets for signing and Sparkle integration, including how to export and encode the necessary keys
  • Clarify behavior when signing and/or Sparkle keys are missing (ad-hoc signing and unsigned appcast entries)
README.md

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (2)
README.md (1)

90-90: Consider adding the Sparkle key generation command.

The documentation mentions the Sparkle generate_keys tool but doesn't show the command. Adding the actual command would improve usability.

📝 Suggested addition
-**Export your Sparkle key:** The EdDSA private key generated by Sparkle's `generate_keys` tool. Store it as the `SPARKLE_PRIVATE_KEY` secret.
+**Export your Sparkle key:**
+
+```bash
+# Generate Sparkle keys (if not already generated)
+# ./bin/generate_keys
+# Then copy the private key for use as the secret
+cat ~/sparkle_private_key
+```
+
+Store the EdDSA private key as the `SPARKLE_PRIVATE_KEY` secret.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@README.md` at line 90, Update the README to show the exact Sparkle key
generation and retrieval steps: add a short snippet invoking the generate_keys
tool (e.g., run the project's generate_keys binary/script), then show the
command to output the generated EdDSA private key so users can copy it, and
finally instruct to store that private key value as the SPARKLE_PRIVATE_KEY
secret; reference the generate_keys tool name and the SPARKLE_PRIVATE_KEY secret
in the text so readers can locate the actions.
.github/workflows/build-release.yml (1)

218-241: Consider adding retry logic for concurrent workflow runs.

If two workflows run concurrently (e.g., manual trigger during an automatic run), both may attempt to push to main simultaneously. The second push would fail with a non-fast-forward error. While this is a rare scenario and the workflow would show a clear failure, adding a retry loop with git pull --rebase would improve robustness.

🔄 Proposed enhancement for concurrent safety
           git add appcast.xml
           if git diff --cached --quiet; then
             echo "appcast.xml unchanged — nothing to push"
           else
             git commit -m "chore: update appcast for ${{ steps.version.outputs.tag }}"
-            git push origin main
+            
+            # Retry push in case of concurrent workflow runs
+            for i in 1 2 3; do
+              if git push origin main; then
+                break
+              fi
+              if [ $i -lt 3 ]; then
+                echo "Push failed, retrying after pull..."
+                git pull --rebase origin main
+              else
+                echo "::error::Failed to push after 3 attempts"
+                exit 1
+              fi
+            done
           fi
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/build-release.yml around lines 218 - 241, The "Push
appcast to main" step can fail on concurrent pushes; wrap the git push origin
main in a short retry loop that on failure runs git pull --rebase (or git fetch
&& git rebase origin/main), re-applies the staged changes, re-commits if
necessary, and retries up to N times with a small sleep; specifically modify the
block that does git add appcast.xml / git commit -m "chore: update appcast..." /
git push origin main to catch non-fast-forward errors, perform git pull --rebase
(or fetch+rebase), and retry the git push a few times before giving up. Ensure
the logic preserves the commit message from the existing commit invocation and
only retries when git push fails due to remote conflicts.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/build-release.yml:
- Line 194: The DOWNLOAD_URL value currently uses the lowercase repo name
"vordenken/autopip"; update the DOWNLOAD_URL string to use the repository's
correct casing ("vordenken/AutoPiP") so the variable DOWNLOAD_URL =
"https://github.com/vordenken/AutoPiP/releases/download/${TAG}/AutoPiP.zip"
reflects the proper repository name; adjust only the repository segment in the
DOWNLOAD_URL assignment.
- Around line 210-216: After running the awk insertion that writes to
"$RUNNER_TEMP/appcast_new.xml", validate that the insertion actually occurred
(for example by checking that the generated file contains the NEW_ITEM or that
the expected anchor "<title>AutoPiP Updates</title>" was present and the new
item string appears) before moving it over appcast.xml; if the check fails, emit
a clear error message and exit non‑zero so the workflow stops instead of
silently continuing. Target the awk invocation and the subsequent mv/echo steps
(NEW_ITEM, appcast.xml, "$RUNNER_TEMP/appcast_new.xml") and add a conditional
that greps or otherwise verifies the inserted content, failing fast when absent.

---

Nitpick comments:
In @.github/workflows/build-release.yml:
- Around line 218-241: The "Push appcast to main" step can fail on concurrent
pushes; wrap the git push origin main in a short retry loop that on failure runs
git pull --rebase (or git fetch && git rebase origin/main), re-applies the
staged changes, re-commits if necessary, and retries up to N times with a small
sleep; specifically modify the block that does git add appcast.xml / git commit
-m "chore: update appcast..." / git push origin main to catch non-fast-forward
errors, perform git pull --rebase (or fetch+rebase), and retry the git push a
few times before giving up. Ensure the logic preserves the commit message from
the existing commit invocation and only retries when git push fails due to
remote conflicts.

In `@README.md`:
- Line 90: Update the README to show the exact Sparkle key generation and
retrieval steps: add a short snippet invoking the generate_keys tool (e.g., run
the project's generate_keys binary/script), then show the command to output the
generated EdDSA private key so users can copy it, and finally instruct to store
that private key value as the SPARKLE_PRIVATE_KEY secret; reference the
generate_keys tool name and the SPARKLE_PRIVATE_KEY secret in the text so
readers can locate the actions.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9d5517c3-68fe-4178-ac22-7e306486cd46

📥 Commits

Reviewing files that changed from the base of the PR and between bfdbcce and 766d8cf.

📒 Files selected for processing (3)
  • .github/workflows/build-release.yml
  • README.md
  • semver.txt

CHANNEL_EL=$'\n'" <sparkle:channel>beta</sparkle:channel>"
fi

DOWNLOAD_URL="https://github.com/vordenken/autopip/releases/download/${TAG}/AutoPiP.zip"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Repository name case inconsistency in download URL.

The download URL uses vordenken/autopip (lowercase) while the repository appears to be vordenken/AutoPiP (based on README line 28). GitHub typically redirects lowercase URLs to the proper case, but for consistency and to avoid potential issues, use the correct casing.

🔧 Proposed fix
-          DOWNLOAD_URL="https://github.com/vordenken/autopip/releases/download/${TAG}/AutoPiP.zip"
+          DOWNLOAD_URL="https://github.com/vordenken/AutoPiP/releases/download/${TAG}/AutoPiP.zip"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
DOWNLOAD_URL="https://github.com/vordenken/autopip/releases/download/${TAG}/AutoPiP.zip"
DOWNLOAD_URL="https://github.com/vordenken/AutoPiP/releases/download/${TAG}/AutoPiP.zip"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/build-release.yml at line 194, The DOWNLOAD_URL value
currently uses the lowercase repo name "vordenken/autopip"; update the
DOWNLOAD_URL string to use the repository's correct casing ("vordenken/AutoPiP")
so the variable DOWNLOAD_URL =
"https://github.com/vordenken/AutoPiP/releases/download/${TAG}/AutoPiP.zip"
reflects the proper repository name; adjust only the repository segment in the
DOWNLOAD_URL assignment.

Comment on lines +210 to +216
# Insert after <title>AutoPiP Updates</title>
awk -v item="$NEW_ITEM" \
'/<title>AutoPiP Updates<\/title>/{print; print item; next} {print}' \
appcast.xml > "$RUNNER_TEMP/appcast_new.xml"

mv "$RUNNER_TEMP/appcast_new.xml" appcast.xml
echo "appcast.xml updated — $CHANNEL $VERSION"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Add validation for appcast insertion success.

The awk command silently fails if the anchor line <title>AutoPiP Updates</title> is missing or malformed in appcast.xml. This would result in the release being created but Sparkle updates not being distributed. Add validation to ensure the new item was actually inserted.

✅ Proposed fix to validate insertion
           awk -v item="$NEW_ITEM" \
             '/<title>AutoPiP Updates<\/title>/{print; print item; next} {print}' \
             appcast.xml > "$RUNNER_TEMP/appcast_new.xml"
 
+          # Validate that the new version was inserted
+          if ! grep -q "sparkle:version=\"${VERSION}\"" "$RUNNER_TEMP/appcast_new.xml"; then
+            echo "::error::Failed to insert new item into appcast.xml - anchor not found"
+            exit 1
+          fi
+
           mv "$RUNNER_TEMP/appcast_new.xml" appcast.xml
           echo "appcast.xml updated — $CHANNEL $VERSION"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
# Insert after <title>AutoPiP Updates</title>
awk -v item="$NEW_ITEM" \
'/<title>AutoPiP Updates<\/title>/{print; print item; next} {print}' \
appcast.xml > "$RUNNER_TEMP/appcast_new.xml"
mv "$RUNNER_TEMP/appcast_new.xml" appcast.xml
echo "appcast.xml updated — $CHANNEL $VERSION"
# Insert after <title>AutoPiP Updates</title>
awk -v item="$NEW_ITEM" \
'/<title>AutoPiP Updates<\/title>/{print; print item; next} {print}' \
appcast.xml > "$RUNNER_TEMP/appcast_new.xml"
# Validate that the new version was inserted
if ! grep -q "sparkle:version=\"${VERSION}\"" "$RUNNER_TEMP/appcast_new.xml"; then
echo "::error::Failed to insert new item into appcast.xml - anchor not found"
exit 1
fi
mv "$RUNNER_TEMP/appcast_new.xml" appcast.xml
echo "appcast.xml updated — $CHANNEL $VERSION"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/build-release.yml around lines 210 - 216, After running
the awk insertion that writes to "$RUNNER_TEMP/appcast_new.xml", validate that
the insertion actually occurred (for example by checking that the generated file
contains the NEW_ITEM or that the expected anchor "<title>AutoPiP
Updates</title>" was present and the new item string appears) before moving it
over appcast.xml; if the check fails, emit a clear error message and exit
non‑zero so the workflow stops instead of silently continuing. Target the awk
invocation and the subsequent mv/echo steps (NEW_ITEM, appcast.xml,
"$RUNNER_TEMP/appcast_new.xml") and add a conditional that greps or otherwise
verifies the inserted content, failing fast when absent.

- Replace zip with create-dmg for .dmg output (matching local workflow)
- Move Sparkle signing + appcast update BEFORE GitHub Release
- Only the final signed DMG is attached to the release
- Update all references from .zip to .dmg
- Update README accordingly

Agent-Logs-Url: https://github.com/vordenken/AutoPiP/sessions/75397440-3f68-478a-9731-f4c2f9843792

Co-authored-by: vordenken <62395860+vordenken@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants