Skip to content

ci: add Rust release workflow targeting GitHub Release assets#1297

Merged
mergify[bot] merged 2 commits intomainfrom
devs/jd/worktree-rust-port/add-rust-release-workflow-targeting-github--48adf3e4
Apr 29, 2026
Merged

ci: add Rust release workflow targeting GitHub Release assets#1297
mergify[bot] merged 2 commits intomainfrom
devs/jd/worktree-rust-port/add-rust-release-workflow-targeting-github--48adf3e4

Conversation

@jd
Copy link
Copy Markdown
Member

@jd jd commented Apr 23, 2026

Starts distributing the static Rust binary alongside the existing
PyPI wheel. Both pipelines run on every published GitHub Release
until the Phase 1.6 channel switch makes the binary the sole
install path.

What ships per release

Seven targets as GitHub Release assets, plus matching
.sha256 checksum files:

  • x86_64-unknown-linux-gnu (glibc)
  • x86_64-unknown-linux-musl (static)
  • aarch64-unknown-linux-gnu (glibc, ARM server)
  • aarch64-unknown-linux-musl (static, ARM server)
  • x86_64-apple-darwin (Intel macOS, signed + notarized)
  • aarch64-apple-darwin (Apple Silicon, signed + notarized)
  • x86_64-pc-windows-msvc (Windows)

Archives use the mergify-<tag>-<target>.tar.gz / .zip
naming convention. Linux and Windows builds go through
taiki-e/upload-rust-binary-action which handles
cross-compilation via cross automatically. macOS builds run
natively on Apple Silicon runners with an explicit pipeline
because of the signing + notarization steps.

macOS signing / notarization

The macOS job imports a Developer ID Application certificate into
a throwaway keychain, codesigns the binary with the hardened
runtime + timestamp, then submits it to Apple's notarytool
service. Stapling isn't possible on a bare Mach-O; online
Gatekeeper checks approve notarized binaries on first run.

Required GitHub Actions secrets (all six must be set before the
next release):

APPLE_CERTIFICATE base64 of the .p12 Developer ID cert
APPLE_CERTIFICATE_PASSWORD password set when exporting the .p12
APPLE_SIGNING_IDENTITY "Developer ID Application: Mergify SAS (TEAMID)"
APPLE_API_KEY base64 of the App Store Connect .p8 API key
APPLE_API_KEY_ID 10-char key ID from App Store Connect
APPLE_API_KEY_ISSUER issuer UUID from App Store Connect

Install story today

Users grab a binary from the releases page:
https://github.com/Mergifyio/mergify-cli/releases/latest.
A curl | sh installer script + Homebrew tap land in separate
follow-up PRs once we've seen the first binary release succeed.

Parallel with PyPI

release.yml (existing) keeps publishing to PyPI unchanged.
Both workflows key off the same release: published event.
The Phase 1.6 channel switch is the user-coordinated moment where
we stop publishing to PyPI and direct users to the binary.

Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com

Depends-On: #1296

@jd
Copy link
Copy Markdown
Member Author

jd commented Apr 23, 2026

This pull request is part of a Mergify stack:

# Pull Request Link
1 test: add port-inventory guard to catch un-ported Python commands #1296
2 ci: add Rust release workflow targeting GitHub Release assets #1297 👈
3 feat(rust): port config simulate to native Rust (Phase 1.3b) #1298
4 feat(rust): port ci scopes-send to native Rust (Phase 1.4) #1300
5 feat(rust): port queue pause and unpause to native Rust (Phase 1.5) #1301
6 feat(rust): port ci git-refs and ci queue-info to native Rust (Phase 1.6) #1302

@mergify
Copy link
Copy Markdown
Contributor

mergify Bot commented Apr 23, 2026

Merge Protections

Your pull request matches the following merge protections and will not be merged until they are valid.

🟢 ⛓️ Depends-On Requirements

Wonderful, this rule succeeded.

Requirement based on the presence of Depends-On in the body of the pull request

🟢 🤖 Continuous Integration

Wonderful, this rule succeeded.
  • all of:
    • check-success=ci-gate

🟢 👀 Review Requirements

Wonderful, this rule succeeded.
  • any of:
    • #approved-reviews-by>=2
    • author = dependabot[bot]
    • author = mergify-ci-bot
    • author = renovate[bot]

🟢 Enforce conventional commit

Wonderful, this rule succeeded.

Make sure that we follow https://www.conventionalcommits.org/en/v1.0.0/

  • title ~= ^(fix|feat|docs|style|refactor|perf|test|build|ci|chore|revert|ui)(?:\(.+\))?:

🟢 🔎 Reviews

Wonderful, this rule succeeded.
  • #changes-requested-reviews-by = 0
  • #review-requested = 0
  • #review-threads-unresolved = 0

🟢 📕 PR description

Wonderful, this rule succeeded.
  • body ~= (?ms:.{48,})

@jd jd force-pushed the devs/jd/worktree-rust-port/add-rust-release-workflow-targeting-github--48adf3e4 branch from 2da50c7 to a2cca7a Compare April 23, 2026 13:31
@jd
Copy link
Copy Markdown
Member Author

jd commented Apr 23, 2026

Revision history

# Type Changes Reason Date
1 initial 2da50c7 2026-04-23 13:31 UTC
2 content 2da50c7 → a2cca7a 2026-04-23 13:31 UTC
3 rebase a2cca7a → cb257f5 2026-04-23 19:02 UTC
4 rebase cb257f5 → 44fc353 2026-04-24 13:41 UTC
5 rebase bb064d0 → 9e9ef12 2026-04-27 07:03 UTC
6 rebase 9e9ef12 → 6def985 2026-04-28 06:48 UTC
7 rebase 6def985 → 573114b 2026-04-28 14:09 UTC
8 rebase 573114b → 2d9fb8c 2026-04-29 07:02 UTC
9 rebase 2d9fb8c → b8b332d 2026-04-29 09:06 UTC
10 content b8b332d → 7d1a6b3 2026-04-29 11:05 UTC

@mergify mergify Bot had a problem deploying to Mergify Merge Protections April 23, 2026 13:31 Failure
@mergify mergify Bot requested a review from a team April 23, 2026 13:37
@jd jd force-pushed the devs/jd/worktree-rust-port/add-port-inventory-guard-catch-un-ported-python--4a71d672 branch from b887a4a to fddda52 Compare April 23, 2026 19:02
@jd jd force-pushed the devs/jd/worktree-rust-port/add-rust-release-workflow-targeting-github--48adf3e4 branch from a2cca7a to cb257f5 Compare April 23, 2026 19:02
@mergify mergify Bot had a problem deploying to Mergify Merge Protections April 23, 2026 19:03 Failure
@jd jd force-pushed the devs/jd/worktree-rust-port/add-rust-release-workflow-targeting-github--48adf3e4 branch from cb257f5 to 44fc353 Compare April 24, 2026 13:41
@mergify mergify Bot had a problem deploying to Mergify Merge Protections April 24, 2026 13:41 Failure
@jd jd force-pushed the devs/jd/worktree-rust-port/add-rust-release-workflow-targeting-github--48adf3e4 branch from 44fc353 to bb064d0 Compare April 27, 2026 06:18
@mergify mergify Bot had a problem deploying to Mergify Merge Protections April 27, 2026 06:18 Failure
@jd jd force-pushed the devs/jd/worktree-rust-port/add-rust-release-workflow-targeting-github--48adf3e4 branch from bb064d0 to 9e9ef12 Compare April 27, 2026 07:03
@mergify mergify Bot had a problem deploying to Mergify Merge Protections April 27, 2026 07:03 Failure
@jd jd force-pushed the devs/jd/worktree-rust-port/add-rust-release-workflow-targeting-github--48adf3e4 branch from 9e9ef12 to 6def985 Compare April 28, 2026 06:48
@mergify mergify Bot had a problem deploying to Mergify Merge Protections April 28, 2026 06:48 Failure
@jd jd force-pushed the devs/jd/worktree-rust-port/add-port-inventory-guard-catch-un-ported-python--4a71d672 branch from e525b00 to cc28fea Compare April 28, 2026 14:09
@jd jd force-pushed the devs/jd/worktree-rust-port/add-rust-release-workflow-targeting-github--48adf3e4 branch from 6def985 to 573114b Compare April 28, 2026 14:09
@mergify mergify Bot had a problem deploying to Mergify Merge Protections April 28, 2026 14:12 Failure
@jd jd force-pushed the devs/jd/worktree-rust-port/add-rust-release-workflow-targeting-github--48adf3e4 branch from 573114b to 2d9fb8c Compare April 29, 2026 07:02
@jd jd force-pushed the devs/jd/worktree-rust-port/add-port-inventory-guard-catch-un-ported-python--4a71d672 branch from cc28fea to 2521caa Compare April 29, 2026 07:02
@mergify mergify Bot had a problem deploying to Mergify Merge Protections April 29, 2026 07:04 Failure
@jd jd marked this pull request as ready for review April 29, 2026 07:35
During the Rust port, any new click command added to the Python CLI
risks being silently missed if the Rust dispatch isn't updated in
parallel. This adds a CI-enforced inventory at the repo root plus
a pytest that walks the click tree and compares against it.

## How it works

``PORT_STATUS.toml`` lists every click subcommand with an explicit
``status`` of either ``native`` (handled by Rust's dispatch) or
``shimmed`` (forwarded to Python by the py-shim crate).
``mergify_cli/tests/test_port_status.py`` walks ``mergify_cli.cli.cli``
and fires four assertions:

- Every discovered click command has an entry.
- Every entry corresponds to a live click command (no stale rows).
- Every entry uses a valid ``status`` value.
- No entry carries extra keys (catches typos like ``stats``).

Forgetting to update the file when adding a new Python command
becomes a CI failure at test-time rather than a "why is this
missing from the binary?" bug report months later.

## Current baseline

All 30 click subcommands are listed. Only ``config validate`` is
``native`` today (from Phase 1.3 in the same stack). The remaining
29 are ``shimmed`` — each subsequent port PR flips its entry from
``shimmed`` to ``native`` in the same commit that adds the Rust
dispatch, keeping the file and the code in lockstep.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Change-Id: I4a71d672f4795dbb3e2e9523ea01b8d7fbbfbcbe
@jd jd force-pushed the devs/jd/worktree-rust-port/add-rust-release-workflow-targeting-github--48adf3e4 branch from 2d9fb8c to b8b332d Compare April 29, 2026 09:06
@jd jd force-pushed the devs/jd/worktree-rust-port/add-port-inventory-guard-catch-un-ported-python--4a71d672 branch from 2521caa to 631557e Compare April 29, 2026 09:06
@mergify mergify Bot had a problem deploying to Mergify Merge Protections April 29, 2026 09:07 Failure
kozlek
kozlek previously approved these changes Apr 29, 2026
Comment thread .github/workflows/release-rust.yml Outdated
@mergify mergify Bot requested a review from a team April 29, 2026 09:49
Starts distributing the static Rust binary alongside the existing
PyPI wheel. Both pipelines run on every published GitHub Release
until the Phase 1.6 channel switch makes the binary the sole
install path.

## What ships per release

Seven targets as GitHub Release assets, plus matching
``.sha256`` checksum files:

- ``x86_64-unknown-linux-gnu``   (glibc)
- ``x86_64-unknown-linux-musl``  (static)
- ``aarch64-unknown-linux-gnu``  (glibc, ARM server)
- ``aarch64-unknown-linux-musl`` (static, ARM server)
- ``x86_64-apple-darwin``        (Intel macOS, signed + notarized)
- ``aarch64-apple-darwin``       (Apple Silicon, signed + notarized)
- ``x86_64-pc-windows-msvc``     (Windows)

Archives use the ``mergify-<tag>-<target>.tar.gz`` / ``.zip``
naming convention. Linux and Windows builds go through
``taiki-e/upload-rust-binary-action`` which handles
cross-compilation via ``cross`` automatically. macOS builds run
natively on Apple Silicon runners with an explicit pipeline
because of the signing + notarization steps.

## macOS signing / notarization

The macOS job imports a Developer ID Application certificate into
a throwaway keychain, codesigns the binary with the hardened
runtime + timestamp, then submits it to Apple's notarytool
service. Stapling isn't possible on a bare Mach-O; online
Gatekeeper checks approve notarized binaries on first run.

Required GitHub Actions secrets (all six must be set before the
next release):

  APPLE_CERTIFICATE            base64 of the .p12 Developer ID cert
  APPLE_CERTIFICATE_PASSWORD   password set when exporting the .p12
  APPLE_SIGNING_IDENTITY       "Developer ID Application: Mergify SAS (TEAMID)"
  APPLE_API_KEY                base64 of the App Store Connect .p8 API key
  APPLE_API_KEY_ID             10-char key ID from App Store Connect
  APPLE_API_KEY_ISSUER         issuer UUID from App Store Connect

## Install story today

Users grab a binary from the releases page:
``https://github.com/Mergifyio/mergify-cli/releases/latest``.
A ``curl | sh`` installer script + Homebrew tap land in separate
follow-up PRs once we've seen the first binary release succeed.

## Parallel with PyPI

``release.yml`` (existing) keeps publishing to PyPI unchanged.
Both workflows key off the same ``release: published`` event.
The Phase 1.6 channel switch is the user-coordinated moment where
we stop publishing to PyPI and direct users to the binary.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

Change-Id: I48adf3e4ebfb49a1ea4ba171862ec72ba1776d7f
@jd jd force-pushed the devs/jd/worktree-rust-port/add-rust-release-workflow-targeting-github--48adf3e4 branch from b8b332d to 7d1a6b3 Compare April 29, 2026 11:05
@mergify mergify Bot dismissed kozlek’s stale review April 29, 2026 11:06

Pull request has been modified.

@mergify mergify Bot deployed to Mergify Merge Protections April 29, 2026 11:06 Active
Base automatically changed from devs/jd/worktree-rust-port/add-port-inventory-guard-catch-un-ported-python--4a71d672 to main April 29, 2026 12:13
@mergify mergify Bot requested a review from a team April 29, 2026 12:45
@mergify
Copy link
Copy Markdown
Contributor

mergify Bot commented Apr 29, 2026

Merge Queue Status

This pull request spent 8 minutes 8 seconds in the queue, including 7 minutes 38 seconds running CI.

Required conditions to merge

mergify Bot added a commit that referenced this pull request Apr 29, 2026
@mergify mergify Bot added the queued label Apr 29, 2026
@mergify mergify Bot merged commit bd7a116 into main Apr 29, 2026
12 checks passed
@mergify mergify Bot deleted the devs/jd/worktree-rust-port/add-rust-release-workflow-targeting-github--48adf3e4 branch April 29, 2026 13:03
@mergify mergify Bot removed the queued label Apr 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants