Skip to content

Homebrew tap scaffolding for moq binaries and gst plugin#1456

Merged
kixelated merged 10 commits into
mainfrom
claude/homebrew-tap-setup-F9ejS
May 23, 2026
Merged

Homebrew tap scaffolding for moq binaries and gst plugin#1456
kixelated merged 10 commits into
mainfrom
claude/homebrew-tap-setup-F9ejS

Conversation

@kixelated
Copy link
Copy Markdown
Collaborator

@kixelated kixelated commented May 23, 2026

Summary

Adds the wiring needed for brew tap moq-dev/tap && brew install moq-dev/tap/<crate> for moq-relay, moq-cli, moq-clock, moq-token-cli, and the moq-gst GStreamer plugin. The tap repo (moq-dev/homebrew-tap) receives generated formulae on every release tag, so this repo never receives an automated commit.

What's in the PR

  • Formula templates under .github/homebrew/Formula/*.rb.tmpl with __VERSION__ / __SHA256_<TARGET>__ placeholders. One per binary plus moq-gst.rb.tmpl (which installs the plugin into lib/ and prints a caveats block telling users how to point GST_PLUGIN_PATH at it).
  • .github/scripts/render-formula.sh — substitutes the placeholders given a version, a directory of release tarballs, and the crate name. Fails loudly if any placeholder remains.
  • macOS prebuilts. moq-relay.yml was rewritten to build via nix build .#moq-relay for all four target triples (matching moq-gst.yml's matrix), and three new mirrors (moq-cli.yml, moq-clock.yml, moq-token-cli.yml) do the same for the rest. All four reuse the existing .github/scripts/release.sh helper for tag parsing and gh release upload.
  • rs/scripts/package-binary.sh — generic tarball packager modeled on rs/moq-gst/build.sh. Produces <crate>-<version>-<target>.tar.gz containing bin/<crate>, README.md, and both LICENSE files.
  • .github/workflows/release-brew.yml — listens for workflow_run: completed on the five per-crate workflows, parses the tag into crate + version, downloads the four target tarballs from the GitHub Release, renders the formula, and pushes it to moq-dev/homebrew-tap as moq-bot. Seeds a README on first push.

Auth

The workflow mints a short-lived installation token from the existing moq-bot GitHub App (APP_ID + APP_PRIVATE_KEY secrets, same pattern as release-swift.yml). The token is scoped to homebrew-tap only and expires in one hour. No long-lived PAT required.

Before the first release

Rename the existing moq-dev/homebrew-moq repo to moq-dev/homebrew-tap (Settings → Rename). moq-bot's existing access carries through the rename.

Breaking change in moq-relay release artifacts

The moq-relay release workflow previously uploaded bare binaries named moq-relay-v<ver>-<target> (Linux only). It now uploads .tar.gz archives named moq-relay-<ver>-<target>.tar.gz (Linux + macOS, 4 targets). Anyone consuming the old artifact URLs will need to update. The Docker image (moqdev/moq-relay) is unaffected.

Test plan

  • YAML parse of all five new/edited workflows — passes locally.
  • bash -n syntax check on the two new shell scripts — passes locally.
  • Render dry run with synthetic tarballs against both moq-relay.rb.tmpl and moq-gst.rb.tmpl — both render without leftover placeholders.
  • Push a throwaway test tag (e.g. moq-clock-v0.0.0-test1) to confirm the macOS prebuilts build end-to-end and the render workflow pushes the formula.
  • Wait for the next real release-plz tag (e.g. moq-gst-v*) and confirm moq-dev/homebrew-tap receives a moq-gst: bump to v<version> commit.
  • On a macOS arm64 host: brew tap moq-dev/tap && brew install moq-dev/tap/moq-gst && gst-inspect-1.0 moq (after exporting GST_PLUGIN_PATH per the caveats).
  • Smoke install for each binary formula: brew install moq-dev/tap/moq-relay && moq-relay --help (repeat for cli/clock/token-cli).

Out of scope

  • moq-boy (skipped — heavy FFmpeg dependency, demo-only).
  • libmoq (C library; Homebrew is the wrong distribution channel).
  • Homebrew bottles — the formulae use upstream release tarballs directly.

https://claude.ai/code/session_015J5tVAQ7ESjBhnzdeXfhgX

claude added 3 commits May 23, 2026 16:20
Adds formula templates under .github/homebrew/Formula/ plus a
release-brew workflow that renders them with the released version and
tarball sha256s on each per-crate release tag, then pushes the rendered
formula to moq-dev/homebrew-tap.

Extends moq-relay's release workflow with macOS x86_64 + arm64 prebuilts
(matching moq-gst's existing matrix) and adds parallel workflows for
moq-cli, moq-clock, and moq-token-cli, all built reproducibly via
nix build .#<crate>. A new rs/scripts/package-binary.sh produces the
tarball layout expected by the formula templates.

To activate end-to-end the user must:
- Create the moq-dev/homebrew-tap repo (empty).
- Add a HOMEBREW_TAP_TOKEN secret with contents:write on that repo.

https://claude.ai/code/session_015J5tVAQ7ESjBhnzdeXfhgX
Switches the tap repo to moq-dev/homebrew-moq (which exposes as the
moq-dev/moq tap) and authenticates as the moq-bot GitHub App using the
already-configured APP_ID and APP_PRIVATE_KEY secrets, matching the
pattern in release-swift.yml. The minted installation token is scoped
to homebrew-moq only and expires in one hour, so no long-lived PAT is
required.

https://claude.ai/code/session_015J5tVAQ7ESjBhnzdeXfhgX
Switches the destination from moq-dev/homebrew-moq to moq-dev/homebrew-tap,
which Homebrew exposes as the conventional moq-dev/tap (matching how
HashiCorp, GoReleaser, etc. name their taps). The minted moq-bot
installation token is rescoped accordingly.

https://claude.ai/code/session_015J5tVAQ7ESjBhnzdeXfhgX
@kixelated kixelated marked this pull request as ready for review May 23, 2026 16:55
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 23, 2026

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f1c53bfe-edb5-4236-aa3f-ed73e1fd345c

📥 Commits

Reviewing files that changed from the base of the PR and between 38bddb6 and 1aabb66.

📒 Files selected for processing (1)
  • .github/workflows/moq-cli.yml

Walkthrough

This PR adds Homebrew release automation: five Homebrew formula templates (moq-cli, moq-clock, moq-gst, moq-relay, moq-token-cli) with templated URLs/SHA256s; a renderer script that substitutes version and per-target checksums; packaging scripts to build and assemble tarballs from nix-built Rust binaries; updated per-crate GitHub Actions to produce Homebrew-style tarballs for Linux/macOS; and a release-brew workflow that renders formulas and publishes them to the homebrew tap (dry-run on PRs).

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main change: adding Homebrew tap scaffolding for moq binaries and the gst plugin, which aligns with the primary objective of publishing Homebrew formulae.
Description check ✅ Passed The description is comprehensive and directly related to the changeset, providing clear context on what is added (formula templates, renderer script, workflows, packager, and auth setup) and includes operational notes and test plans.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/homebrew-tap-setup-F9ejS
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch claude/homebrew-tap-setup-F9ejS

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.

Copy link
Copy Markdown
Contributor

@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: 9

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/scripts/render-formula.sh:
- Around line 28-34: The case arms in the while loop (handling flags like
--template, --version, --release-dir, --crate, --output) currently dereference
$2 without checking it; update each flag branch in the while ... case block to
first verify there is a following argument (e.g., test $# -ge 2 or that $2 is
non-empty and not another flag) and if missing print a clear usage/error message
and exit non‑zero, rather than allowing set -u failures; keep the same variable
names (TEMPLATE, VERSION, RELEASE_DIR, CRATE, OUTPUT) and ensure shift 2 only
runs after validation.

In @.github/workflows/moq-cli.yml:
- Around line 30-35: The workflow uses unpinned action refs
(actions/checkout@v6, DeterminateSystems/nix-installer-action@main,
DeterminateSystems/magic-nix-cache-action@main, actions/upload-artifact@v7,
actions/download-artifact@v8) and the checkout steps do not set
persist-credentials; update each `uses:` to a specific commit SHA for those
actions and add `persist-credentials: false` to all checkout steps (the steps
invoking actions/checkout) to prevent credential leakage, ensuring you replace
the `@refs` with the corresponding commit SHAs from each action's repo and keep
the step names (actions/checkout) to locate the changes.

In @.github/workflows/moq-clock.yml:
- Line 30: The workflow uses floating GitHub Action refs (e.g.,
actions/checkout@v6, DeterminateSystems/nix-installer-action@main,
DeterminateSystems/magic-nix-cache-action@main, actions/upload-artifact@v7,
actions/download-artifact@v8); replace each floating ref with the corresponding
immutable commit SHA for that release/tag (fetch the action repo and pin the SHA
for the desired tag) so update occurrences of actions/checkout@v6,
DeterminateSystems/nix-installer-action@main,
DeterminateSystems/magic-nix-cache-action@main, actions/upload-artifact@v7, and
actions/download-artifact@v8 to their SHA-pinned equivalents throughout the
workflow file.

In @.github/workflows/moq-relay.yml:
- Line 30: Replace floating refs used in workflow steps (e.g.,
actions/checkout@v6, DeterminateSystems/*`@main`, actions/upload-artifact@v7,
actions/download-artifact@v8) with their corresponding immutable commit SHAs:
locate each uses: entry referencing those tags in the workflow and swap the tag
(e.g., `@v6`, `@main`, `@v7`, `@v8`) for the specific full commit SHA for that action or
repo; ensure each step now uses the exact SHA string (ref: the uses: lines for
actions/checkout, DeterminateSystems/* actions, actions/upload-artifact, and
actions/download-artifact) and run the workflow to confirm no syntax errors.

In @.github/workflows/moq-token-cli.yml:
- Line 30: Replace floating GitHub Actions refs with immutable commit SHAs for
each `uses:` entry to ensure reproducible workflows: find the `uses:` lines
referencing `actions/checkout@v6`,
`DeterminateSystems/nix-installer-action@main`,
`DeterminateSystems/magic-nix-cache-action@main`, `actions/upload-artifact@v7`,
`actions/checkout@v6` (second occurrence), and `actions/download-artifact@v8` in
the workflow and update them to the corresponding full commit SHAs from their
repositories (obtain the SHA from the upstream repo's commits or release tag),
keeping the rest of the step configuration unchanged; commit the updated
workflow so all `uses:` entries point to fixed SHAs.

In @.github/workflows/release-brew.yml:
- Line 34: The conditional currently uses github.event.workflow_run.head_branch
(seen in the if expression) which is not tag-safe; update the workflow to derive
the release tag from a tag-safe source instead (for example, resolve the git tag
for github.event.workflow_run.head_sha or accept a passed-in upstream tag input)
and then parse/match "<crate>-v<semver>" from that resolved tag; specifically,
replace uses of github.event.workflow_run.head_branch in the if check and the
subsequent parsing logic with a resolved variable (obtained via an action step
that runs git tag --points-at/$GITHUB_SHA or uses actions/github-script to list
tags for github.event.workflow_run.head_sha, or accept an explicit workflow
input from the upstream job), export that value as an output or env (e.g.,
RELEASE_TAG) and use startsWith/regex against RELEASE_TAG instead of
github.event.workflow_run.head_branch.
- Line 38: Replace floating action refs with immutable commit SHAs: locate the
usages of "uses: actions/checkout@v6" (both occurrences) and "uses:
actions/create-github-app-token@v3" and update each to the corresponding pinned
commit SHA (e.g., "actions/checkout@<sha>" and
"actions/create-github-app-token@<sha>"). Ensure you fetch the correct commit
SHAs from the respective GitHub Action repositories and replace the tag versions
with those SHAs for each "uses:" entry.

In `@rs/scripts/package-binary.sh`:
- Around line 54-64: The script currently uses the TARGET variable (set from
rustc -vV or user-provided) for naming artifacts but does not verify it matches
the actual build output, which can produce mislabeled archives; update
package-binary.sh to validate the requested/derived TARGET against the real
build target or refuse to proceed: after determining TARGET (the TARGET variable
and the rustc detection branch) run a check against the build output platform
(the nix build invocation for "$WORKSPACE_DIR#$CRATE"/the "$RESULT_LINK"
artifact) and if they differ emit an error and exit (or fallback to the actual
detected target) so that naming uses the true build target rather than an
unchecked --target value. Ensure the check runs before creating BUILD_TMP and
before using TARGET for archive naming.
- Around line 21-26: The flag parsing in package-binary.sh reads $2 for
value-taking flags (--crate, --target, --version, --output) without validating
that a next argument exists, which fails under set -u for malformed invocations;
update the case branch handling these flags in the while loop to verify $# -ge 2
before assigning CRATE/TARGET/VERSION/OUTPUT_DIR (and print a clear usage/error
and exit non-zero if missing) so you never reference an absent $2.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 6699a141-a9c4-4b98-88a8-b7cdbc8b867b

📥 Commits

Reviewing files that changed from the base of the PR and between 357bd87 and cc770f2.

📒 Files selected for processing (12)
  • .github/homebrew/Formula/moq-cli.rb.tmpl
  • .github/homebrew/Formula/moq-clock.rb.tmpl
  • .github/homebrew/Formula/moq-gst.rb.tmpl
  • .github/homebrew/Formula/moq-relay.rb.tmpl
  • .github/homebrew/Formula/moq-token-cli.rb.tmpl
  • .github/scripts/render-formula.sh
  • .github/workflows/moq-cli.yml
  • .github/workflows/moq-clock.yml
  • .github/workflows/moq-relay.yml
  • .github/workflows/moq-token-cli.yml
  • .github/workflows/release-brew.yml
  • rs/scripts/package-binary.sh

Comment thread .github/scripts/render-formula.sh Outdated
Comment thread .github/workflows/moq-cli.yml Outdated
Comment thread .github/workflows/moq-clock.yml Outdated
Comment thread .github/workflows/moq-relay.yml Outdated
Comment thread .github/workflows/moq-token-cli.yml Outdated
Comment thread .github/workflows/release-brew.yml Outdated
jobs:
publish:
name: Publish formula to homebrew-tap
if: ${{ github.event.workflow_run.conclusion == 'success' && startsWith(github.event.workflow_run.head_branch, 'moq-') }}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

In GitHub Actions workflow_runpayloads, what exact value doesworkflow_run.head_branch have when the upstream workflow was triggered by a tag push?

💡 Result:

When the upstream workflow was triggered by a tag push, workflow_run.head_branch is set to the tag’s name (the same “initial ref” that triggered the upstream workflow), accessible as github.event.workflow_run.head_branch in the downstream workflow.[1] Example: if the upstream workflow was triggered by pushing tag v1.2.3, then workflow_run.head_branch will be v1.2.3 (not refs/tags/v1.2.3). [1] Notes: GitHub’s docs for workflow_run focus on the default-branch behavior for GITHUB_REF, and downstream workflows can inspect the original triggering ref via the workflow_run event payload (head_branch).[2][3]

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE=".github/workflows/release-brew.yml"
echo "== File = $FILE =="
nl -ba "$FILE" | sed -n '1,200p'

Repository: moq-dev/moq

Length of output: 164


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE=".github/workflows/release-brew.yml"
echo "== File = $FILE =="
# Show around the referenced lines
sed -n '1,120p' "$FILE" | cat -n

Repository: moq-dev/moq

Length of output: 4838


🌐 Web query:

GitHub Actions workflow_run event payload head_branch value when triggered by tag push (official documentation)

💡 Result:

When a workflow is triggered by the workflow_run event, the event payload’s head_branch value is the branch name for the triggering workflow run (not the tag name). GitHub’s documentation describes that for the workflow_run event, GITHUB_SHA is “Last commit on default branch” and GITHUB_REF is “Default branch”, and the documentation notes that the workflow triggered by workflow_run uses the default branch context rather than preserving the original branch/tag ref [1]. In practical terms for your specific question (“workflow_run event payload head_branch value when triggered by tag push”): head_branch will be the branch that contains the workflow run you’re chaining from. If the upstream workflow was triggered by pushing a tag, the upstream workflow still runs in a ref context that results in the downstream workflow_run context being the default-branch code, so head_branch will not be the pushed tag name; it will be a branch name (the default branch / triggering workflow’s branch in that context) [1][2]. Example usage in a workflow triggered by workflow_run: - github.event.workflow_run.head_branch This is intended to identify the originating branch in a workflow_run chain [2][3].

Citations:


🌐 Web query:

workflow_run head_branch tag name vs branch name GitHub Actions documentation issue

💡 Result:

In a downstream workflow triggered by on: workflow_run, there isn’t a “tag name” context comparable to what you get in a direct push-to-tag workflow; instead you read the ref from the upstream run. 1) Tag vs branch: use the upstream workflow_run ref fields - github.event.workflow_run.head_branch is the “head branch” (source branch) from the upstream run, exposed on the workflow_run event payload. [1][2] - github.event.workflow_run.head_repository.full_name gives the repository for that upstream run. [2] Example pattern to check out the exact ref (branch or tag) from the upstream workflow_run: - uses: actions/checkout@v4 with: repository: ${{ github.event.workflow_run.head_repository.full_name }} ref: ${{ github.event.workflow_run.head_branch }} This uses head_branch as the ref you pass to checkout. [2] 2) Why “GITHUB_REF vs branch name” behaves differently - For workflows triggered directly by push, GitHub sets GITHUB_REF to the fully-qualified ref that was pushed (refs/heads/ for branches, refs/tags/ for tags). That’s why people can derive the tag name from GITHUB_REF in a tag-triggered workflow. [3] - But for on: workflow_run, GitHub’s own docs note that the workflow that’s started uses the default branch of the repository for the repository’s checked-out workflow file execution, and the trigger payload supplies the originating ref via the workflow_run fields (like head_branch). [4][2] So you should not expect the same GITHUB_REF semantics as a tag-triggered push workflow inside a workflow_run-triggered workflow. [4][2] 3) When you do have pull_request events If the upstream trigger was a pull_request / pull_request_target, then the downstream (or other workflows) can expose PR-specific head/base refs via contexts like github.head_ref (but that’s specific to pull_request-based events). [5][6] Bottom line - For workflow_run chaining, treat github.event.workflow_run.head_branch as “the upstream ref identifier to use” (often it will be a branch name; for tag-originated upstream runs you’ll need to confirm what value head_branch contains in your case, and then use it as the checkout ref as shown). [1][2] - To reliably distinguish branches vs tags, don’t rely on GITHUB_REF inside the workflow_run workflow; instead inspect the workflow_run payload fields you’re using (and/or test against an upstream run triggered by tags). [4][2]

Citations:


🌐 Web query:

workflow_run head_branch tag name vs branch name GitHub Actions documentation issue

💡 Result:

In GitHub Actions, there are multiple “branch/tag name” concepts depending on (a) the event type that triggered the workflow and (b) whether you’re looking at the current workflow’s ref context or the upstream workflow’s ref context via workflow_run. 1) Current workflow: tag/branch name contexts - github.ref_name is the short ref name (branch or tag) that triggered the workflow run. It matches the name shown on GitHub (for example, feature-branch-1 for a branch, v1.0.0 for a tag). [1] - For push/other non-pull_request events, github.ref_name corresponds to the branch or tag (i.e., it’s effectively your “branch name vs tag name” discriminator without needing to parse refs/heads or refs/tags). [1] - For pull_request / pull_request_target events, github.head_ref is the pull request’s source branch name, and github.base_ref is the target branch name. [2] 2) Chained workflow (workflow_run event): head_branch vs ref_name With on: workflow_run, your workflow is triggered by completion/request of another workflow. The docs note that you can access the workflow_run event payload, but the workflow_run event’s GITHUB_REF/GITHUB_SHA behaviors are not “the same as” a direct push/tag event. - For the workflow_run trigger, the Actions docs state that the “GITHUB_SHA” is the last commit on the default branch and “GITHUB_REF” is the default branch. [3] This is why “current” contexts like $GITHUB_REF or github.ref_name can be misleading for what you really want (the branch/tag of the upstream workflow run). What to use instead: - github.event.workflow_run.head_branch gives you the upstream workflow run’s head branch value. This is commonly used to access the branch/tag that initiated the upstream workflow when chaining. [4] - The workflow_run payload also has fields for the upstream run (e.g., head_branch was discussed as available in github.event.workflow_run). [5] 3) Specifically: “tag name vs branch name” when chaining via workflow_run Key point: workflow_run is designed to be fed by a particular upstream workflow run, and in many cases the upstream run might have been triggered by a tag push, but your downstream workflow’s “default branch” ref context can obscure that. - A community answer for “How to read tag name using workflow_run” explains that workflow_run does not preserve github.ref the way you might expect, and to access the tag/branch that triggered the workflow_run you should use github.event.workflow_run.head_branch (for example, ${ { github.event.workflow_run.head_branch }}). [4] 4) How to think about “head_branch” vs “branch name” - “branch name” in Actions usually means github.ref_name (current run) when the workflow is directly triggered by a branch/tag event. [1] - “head_branch” (in the workflow_run event payload) refers to the upstream workflow run’s branch context. [4] - If the upstream run was triggered by a tag, you may need to interpret what head_branch contains for your specific case (some users effectively treat it as “the ref name that initiated the upstream workflow run” in chained scenarios). [4] 5) Practical patterns A) If you only care about the ref that triggered the current workflow: - Use github.ref_name for branch-or-tag name. [1] B) If you are chaining and need the upstream ref that triggered the upstream workflow: - Use github.event.workflow_run.head_branch. [4] 6) Answer to the “issue” angle (common confusion) There’s an existing docs clarification request noting that github.ref_name and related ref contexts can be confusing/inconsistent depending on event type; for PR-triggered workflows you need github.head_ref, while for others github.ref_name is appropriate. [1] If you tell me your exact workflow triggers (the upstream on: block and the downstream on: workflow_run/workflows: …), I can give the exact expression to extract the upstream tag vs branch for that specific setup.

Citations:


🌐 Web query:

site:docs.github.com workflow_run head_branch tag

💡 Result:

In GitHub Actions, for the workflow_run event, the triggering branch and tag are available as refs/contexts; the workflow “type” (branch vs tag) is github.ref_type. 1) Branch: use github.head_ref / head_branch - workflow_run provides the triggering ref via github.ref (fully formed). It also provides github.name (short name of branch or tag) and github.ref_type (either branch or tag). The doc explicitly defines github.ref_type as branch or tag and github.ref as the fully-formed refs/heads/<name> or refs/tags/<name> depending on what triggered the run. [1] - In the REST API, workflow runs include a head_branch field (string or null). [2] 2) Tag: use github.ref / github.name when github.ref_type == 'tag' - The github.ref context includes the fully-formed ref for the thing that triggered the workflow; for tags it is refs/tags/<tag>. [1] - github.ref_type tells you whether that ref is a branch or a tag (branch or tag). [1] 3) “head_branch tag” in API terms - The REST workflow-runs endpoint returns head_branch as part of each workflow run object, but it does not use a separate head_tag field in the schema shown; instead the triggering ref/tag information is represented in ref/contexts for the workflow run trigger, and github.ref_type distinguishes branch vs tag. [2][1] Practical check in a workflow YAML (inside the triggered workflow): - Determine whether the triggering ref was a branch or tag: - if: github.ref_type == 'tag' to treat github.ref as refs/tags/... and github.name as the tag name. [1] - if: github.ref_type == 'branch' to treat github.ref as refs/heads/... and github.name as the branch name. [1] Notes specific to filtering on workflow_run - When using the workflow_run trigger, you can restrict which runs trigger your workflow by branch name using on.workflow_run.branches or branches-ignore (glob patterns). [3][4]

Citations:


🌐 Web query:

site:docs.github.com workflow_run head_branch tag

💡 Result:

In GitHub Actions, a workflow_run object includes head branch/sha and a separate ref context for what triggered the run. 1) “head_branch” (branch name of the run’s head commit) - GitHub’s REST API for workflow runs returns a Workflow Run field named head_branch (string or null). It is explicitly part of the response schema for workflow runs [1][2]. 2) “tag” (whether the triggering ref is a tag) - The Actions workflow context github.ref_type tells you whether the ref that triggered the workflow run is a branch or a tag (valid values: branch or tag) [3]. - The corresponding github.ref describes the fully-formed ref (for tags, refs/tags/) and other trigger-specific refs [3]. 3) Relationship / how to answer the combined query “workflow_run head_branch tag” - To get the branch name associated with the workflow run: use workflow_run.head_branch from the workflow runs REST API response [1][2]. - To determine whether the triggering ref was a tag: use github.ref_type == "tag" (and github.ref starts with refs/tags/) in the workflow run context [3]. If you meant “a field literally named tag inside the workflow_run payload/API,” the GitHub API schema we found for workflow runs documents head_branch (and head_sha) but not a separate field named tag; the “tag vs branch” concept is represented via ref_type/ref in the Actions contexts [1][3].

Citations:


🌐 Web query:

workflow_run head_branch tag push value head_branch null

💡 Result:

Answer: In GitHub Actions, the value of github.event.workflow_run.head_branch is populated when the downstream workflow is triggered via the workflow_run event, but for workflow_run specifically GitHub sets the run’s GITHUB_REF to the default branch (not the tag/branch that actually triggered the upstream workflow). Therefore, for the expression “workflow_run head_branch tag push value head_branch null”: head_branch is expected to be present (not null) when the upstream workflow run has a branch context; however, you cannot reliably read a tag from the workflow_run context, and the downstream run’s refs like GITHUB_REF will point to the default branch. Evidence-grounded details: 1) For workflows triggered by workflow_run, GitHub’s documented table of webhook payload values shows GITHUB_REF is “Default branch” and GITHUB_SHA is “Last commit on default branch” for the workflow_run event, not the upstream tag/branch ref [1][2]. 2) GitHub documents that github.head_ref is only available for pull_request or pull_request_target events, and github.ref is “the fully-formed ref of the branch or tag that triggered the workflow run” when available for the event type [3]. For workflow_run events, this means the triggered run’s ref context is not the original push/tag context; it’s the default branch ref (per items above) [1][2]. 3) community discussion and common practice confirms that to access the upstream branch name when chaining via workflow_run you use github.event.workflow_run.head_branch [4]. (This also aligns with the question’s focus on head_branch not being null; if you observe it as null, it’s typically because the upstream run wasn’t associated with a branch context.) Practical implication for your “head_branch null” case: - If your upstream workflow was triggered by a tag push, the downstream workflow triggered by workflow_run still sees the downstream run ref as the default branch (GITHUB_REF), so using GITHUB_REF or github.ref to infer the tag won’t work [1][2]. - To get the upstream branch, use github.event.workflow_run.head_branch (when the upstream run has one) [4]. - If you specifically need the tag name from the upstream, workflow_run does not preserve the original tag ref reliably; you generally need to capture it in the upstream workflow (e.g., pass it as an output/artifact or environment value to the downstream via API/inputs) rather than relying on github.ref/GITHUB_REF in the downstream [1][2].

Citations:


🌐 Web query:

github.event.workflow_run.head_branch tag name not branch

💡 Result:

github.event.workflow_run.head_branch is the source branch (not a tag name) for the workflow_run event; it’s the “head_branch” of the run, not the tag that may have been involved in the triggering event. [1][2] If you need the tag name when the upstream run was triggered by a tag push, GitHub does not document a direct “workflow_run.tag” field; the common workaround is to derive the tag from the original ref available to the workflow_run payload. For example, community guidance shows using github.event.workflow_run.head_branch for chained runs, but this is still “head_branch” semantics (i.e., branch/ref used to run the upstream workflow), and may not represent a tag in all cases. [3][4] In short: “head_branch” is a branch/ref name for the upstream run, so it should not be treated as a tag-name field. [1][2]

Citations:


🌐 Web query:

site:github.com actions workflow_run head_branch tag

💡 Result:

For GitHub Actions, the workflow_run event exposes the source branch that triggered the prior workflow as github.event.workflow_run.head_branch. For example, you can use it with actions/checkout: - ref: ${{ github.event.workflow_run.head_branch }} [1] 1) head_branch (source branch of the triggering workflow_run) - github.event.workflow_run.head_branch is available in the event payload for the workflow_run-triggered workflow (it’s the branch the original workflow run was based on). [1][2] - Related contexts/variables for branch names exist under the github context and variables docs, e.g. github.head_ref / GITHUB_HEAD_REF are for pull_request/pull_request_target events (not workflow_run). [3][4] 2) tag - The workflow syntax supports tags/branches filters for events like push, but for workflow_run specifically there isn’t a first-class tags filter in the official workflow_run trigger documentation; the documented filtering for workflow_run is “branches” / “branches-ignore” (not tags). [5][6] - Community discussion indicates attempting to use a tags key under on: workflow_run generally doesn’t work as expected; workarounds involve triggering on tags in the upstream workflow and chaining with workflow_run (or using branches filters that match tag names as strings, depending on your setup). [7] 3) Practical mapping for your query “actions workflow_run head_branch tag” - Use github.event.workflow_run.head_branch to check out or gate logic based on the triggering workflow’s branch. [1] - For tags: treat them as a separate upstream concern (e.g., upstream workflow triggered by push tags), because workflow_run trigger filtering is documented for branches, not tags. [5][6][7]

Citations:


🌐 Web query:

workflow_run head_branch tag push value head_branch null

💡 Result:

In GitHub Actions, for a workflow triggered by the workflow_run event, the value for the upstream ref that caused the run (branch or tag) is available as github.event.workflow_run.head_branch. This is the property you want for “head_branch tag push value head_branch null” style cases (it can reflect either branch or tag context depending on what triggered the upstream workflow) [1][2]. If you see head_branch = null, that commonly indicates the payload didn’t include a usable head branch—GitHub Docs note that in some API/webhook contexts (for example, pushes not detected in the expected repository scope), head_branch can be null [3]. Additionally, the GitHub Actions push event distinguishes between pushing commits/branches vs pushing tags, but workflow_run itself is a different trigger that runs on the default branch and exposes upstream details via the github.event.workflow_run.* fields [1][4]. Practical extraction examples: - In the downstream workflow, read the upstream ref name with: ${{ github.event.workflow_run.head_branch }} [5][2] - If you need to limit by the upstream workflow’s branch/tag, you typically compare github.event.workflow_run.head_branch (not github.ref) because workflow_run runs on the default branch and does not preserve the original github.ref the way a direct push does [1][5].

Citations:


🌐 Web query:

github.event.workflow_run.head_branch tag name not branch

💡 Result:

In a workflow triggered by the workflow_run event, there is no separate “head_branch tag name” concept in the context; tags and branches are represented as the original ref that triggered the upstream workflow. To get the upstream workflow’s ref name (which will be a branch name for branch runs, or a tag name for tag runs), use: ${{ github.event.workflow_run.head_branch }} This returns the ref name (e.g., a tag’s short name such as v1.2.3 when the upstream run was triggered by that tag). [1] For comparison, the fully-formed ref of the current workflow run (not specifically the upstream workflow_run’s tag) is available as: github.ref github.ref is the fully-formed ref of the branch or tag that triggered the current workflow run. [2] Notes: - The workflow_run event payload is only guaranteed to include the “last commit on default branch” for GITHUB_SHA / GITHUB_REF per the event documentation, but the upstream ref name you want to chain (branch vs tag) is what head_branch is for in practice. [3]

Citations:


🌐 Web query:

site:github.com actions workflow_run head_branch tag

💡 Result:

In GitHub Actions, for the workflow_run trigger, the “triggering workflow’s” branch/tag info is available via the workflow_run event payload (and sometimes as env vars). 1) head_branch: where to find it - The branch that the triggering workflow run was associated with is available as github.event.workflow_run.head_branch in the workflow_run-triggered workflow. This is documented in the workflow_run event payload examples and in community guidance, which shows using github.event.workflow_run.head_branch to checkout the originating branch. [1] 2) tag: how tags relate (and the common gotcha) - A workflow_run trigger is fundamentally based on the completed run of another workflow, and the official trigger documentation focuses on the workflow_run activity types and that the triggered workflow runs when the referenced workflow file exists on the default branch. It does not define a dedicated github.event.workflow_run.tag field in the same way it defines head_branch. [2] - If what you need is “run triggered by a tag,” GitHub Actions typically provides tag information via the push/tag-related contexts/filters (for example, using tags: / tags-ignore: filters on push or release events). The workflow syntax docs explain that tags filters are for including/excluding tag name patterns for the relevant event. [3] - Therefore, if your goal is “run the second workflow only when the first workflow ran for a tag,” you generally need to determine the tag from the triggering workflow’s context (e.g., by passing it as an output/artifact or encoding it into the triggering workflow run data), because workflow_run is not documented as having a direct “tag” selector alongside head_branch. [2] 3) Alternative: use refs/variables available in the workflow_run run context - For branch refs, GitHub documents runner environment variables like GITHUB_HEAD_REF and GITHUB_BASE_REF for pull_request / pull_request_target events (not workflow_run). [4] - For workflow_run itself, the workflow can access the workflow_run event payload via the github context (including head_branch as above). [1] Practical pattern (checkout by head branch) - Use actions/checkout with the originating branch from the triggering workflow run: - ref: ${{ github.event.workflow_run.head_branch }} [1] If you tell me whether your “tag” requirement means (a) “triggered workflow was caused by a git tag push,” or (b) “release tag,” or (c) “the triggering workflow itself set a tag as an output,” I can show the exact recommended wiring (tags filters vs outputs/artifacts) and the precise context fields to use.

Citations:


🏁 Script executed:

sed -n '120,260p' .github/workflows/release-brew.yml | cat -n

Repository: moq-dev/moq

Length of output: 2077


🌐 Web query:

workflow_run.head_branch null when workflow triggered by tag push

💡 Result:

In GitHub Actions, when you trigger a workflow with the workflow_run event (for example, a downstream workflow running after an upstream workflow that was started by a tag push), github.event.workflow_run.head_branch can be null/empty depending on the upstream run’s context. What the official docs say: - The workflow_run event payload is designed so the downstream workflow runs using the default branch ref and commit SHA from the triggering workflow: it uses “Last commit on default branch” for GITHUB_SHA and “Default branch” for GITHUB_REF, and the docs note that it “is triggered regardless of the branch of the previous workflow” [1]. - Separately, the docs explain that github.event.workflow_run.head_branch is the original branch name from the triggering workflow; it’s exposed as a part of the github context (commonly referenced as ${{ github.event.workflow_run.head_branch }}) [2]. Why you can see head_branch as null for tag-push initiated upstream workflows: - When the triggering workflow was started by a tag push, there is no branch “head ref” in the same sense as a normal branch push. Since workflow_run is populated primarily with default-branch execution context [1], the “head branch” field may not have a meaningful value for tag-driven runs, which is consistent with reports where head_branch is not usable for tags in chained workflow scenarios [3]. How to reliably get the tag (instead of relying on head_branch): - Don’t depend on github.event.workflow_run.head_branch for the tag. Instead, capture the tag in the upstream workflow (on push tags) and pass it to the downstream workflow (e.g., via workflow_run artifacts, workflow outputs with workflow_call, or repository dispatch), then have the downstream read that artifact/output. - If you only need the tag within the workflow triggered by the tag push, use GITHUB_REF directly; for example, within the tag-push workflow you can extract the tag name from GITHUB_REF [4]. In short: head_branch is not guaranteed to be populated for tag-triggered upstream runs because workflow_run downstream execution is tied to the default branch context, not the ref type (branch vs tag) that started the upstream workflow [1].

Citations:


🌐 Web query:

workflow_run head_branch value for tag triggered workflow

💡 Result:

In a downstream workflow triggered by workflow_run, the value you want is github.event.workflow_run.head_branch. So the “workflow_run head_branch value” in that tag-triggered chain is: ${{ github.event.workflow_run.head_branch }} Notes / caveats: - The workflow_run event documentation states that for workflow_run the GITHUB_REF/GITHUB_SHA values correspond to the default branch, not necessarily the original tag ref that caused the upstream run. That’s why you shouldn’t rely on github.ref / GITHUB_REF in the downstream workflow to recover the tag; instead use github.event.workflow_run.head_branch to get the branch name from the triggering run [1]. - Community discussion/examples indicate that to access the tag name from the workflow that triggered the workflow_run, you use github.event.workflow_run.head_branch [2]. Example usage (downstream CD workflow): - name: Show triggering ref run: echo "Trigger head_branch is ${{ github.event.workflow_run.head_branch }}"

Citations:


Derive the release tag from a tag-safe source, not github.event.workflow_run.head_branch.
Line 34 and 43–53 assume github.event.workflow_run.head_branch equals <crate>-v<semver>; in workflow_run-triggered downstream workflows the ref context isn’t guaranteed to preserve the upstream tag, and head_branch can be empty/null for tag-originated upstream runs—leading to false skips and/or regex parse failures that block Homebrew formula publishing.

if: ${{ github.event.workflow_run.conclusion == 'success' && startsWith(github.event.workflow_run.head_branch, 'moq-') }}

Fix by deriving the tag from a tag-safe source (e.g., resolve Git tags for github.event.workflow_run.head_sha, or pass the tag explicitly from the upstream release workflow) and then parse/match <crate>-v<semver> from that value.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/release-brew.yml at line 34, The conditional currently
uses github.event.workflow_run.head_branch (seen in the if expression) which is
not tag-safe; update the workflow to derive the release tag from a tag-safe
source instead (for example, resolve the git tag for
github.event.workflow_run.head_sha or accept a passed-in upstream tag input) and
then parse/match "<crate>-v<semver>" from that resolved tag; specifically,
replace uses of github.event.workflow_run.head_branch in the if check and the
subsequent parsing logic with a resolved variable (obtained via an action step
that runs git tag --points-at/$GITHUB_SHA or uses actions/github-script to list
tags for github.event.workflow_run.head_sha, or accept an explicit workflow
input from the upstream job), export that value as an output or env (e.g.,
RELEASE_TAG) and use startsWith/regex against RELEASE_TAG instead of
github.event.workflow_run.head_branch.

Comment thread .github/workflows/release-brew.yml Outdated
Comment thread rs/scripts/package-binary.sh Outdated
Comment thread rs/scripts/package-binary.sh
claude added 3 commits May 23, 2026 17:07
Resolves a conflict in .github/workflows/moq-relay.yml where main pinned
GitHub Actions to commit SHAs (#1455) while this branch rewrote the
workflow to build via Nix for all four target triples. Took the Nix-based
build steps from this branch and pinned the actions to the same SHAs main
uses elsewhere (actions/checkout, upload-artifact, download-artifact,
DeterminateSystems/nix-installer-action, DeterminateSystems/magic-nix-cache-action).

Also pinned the same actions in the four other workflows this branch
adds (moq-cli.yml, moq-clock.yml, moq-token-cli.yml, release-brew.yml),
plus actions/create-github-app-token, to satisfy the same convention.

https://claude.ai/code/session_015J5tVAQ7ESjBhnzdeXfhgX
Addresses CodeRabbit review feedback on PR #1456.

render-formula.sh and package-binary.sh: collapse the value-taking flag
arms into a single branch that verifies a following argument exists
before dereferencing it. Previously a malformed invocation like
`--template` (no value) tripped set -u with an opaque shell error
instead of a clear usage message.

package-binary.sh: refuse to build when an explicit --target differs
from the host. The script wraps `nix build .#<crate>` which produces
the host's native binary; cross-compilation isn't wired up. CI's matrix
already pairs each target with a matching runner, but the script's
contract was looser than that and could silently publish mislabeled
archives.

https://claude.ai/code/session_015J5tVAQ7ESjBhnzdeXfhgX
Brings in the dry-run + persist-credentials + Determinate-Nix opt-out
changes from main (PRs #1463, #1464, #1465). Resolves the recurring
conflict in moq-relay.yml by keeping this branch's Nix-based rewrite
and layering the new patterns on top.

Extends the dry-run pattern to the four workflows this branch adds plus
moq-gst (which #1464 didn't cover):
- moq-relay, moq-cli, moq-clock, moq-token-cli, moq-gst now trigger
  on pull_request when the workflow itself, its build script, the nix
  derivation, or the flake changes. The build job parses the version
  from Cargo.toml on PRs (release.sh parse-version expects a tag). The
  release job is gated on github.event_name == 'push'.
- release-brew.yml gains a dry-run job that, on PRs touching the
  workflow or any formula template, renders every template against
  synthetic tarballs and runs ruby -c on the output. The publish job
  is gated to workflow_run events only.

Also adds persist-credentials: false to all checkouts that don't push,
and `with: { determinate: false }` to nix-installer-action, matching
the main-branch convention.

https://claude.ai/code/session_015J5tVAQ7ESjBhnzdeXfhgX
Copy link
Copy Markdown
Contributor

@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.

♻️ Duplicate comments (2)
.github/scripts/render-formula.sh (1)

31-34: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Reject flag-like values immediately for required options.

Line 31 only checks argument count; it still accepts another flag as the value (for example, --template --version ...) and fails later with a less clear error. Validate that $2 is present and not another option token.

Suggested parser hardening
         --template|--version|--release-dir|--crate|--output)
-            if [[ $# -lt 2 ]]; then
+            if [[ $# -lt 2 || "$2" == --* ]]; then
                 echo "Error: $1 requires a value" >&2
                 exit 1
             fi
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/scripts/render-formula.sh around lines 31 - 34, The current check in
the option parsing block (the if that tests [[ $# -lt 2 ]]) only ensures a
second argument exists but allows another flag as the value; change the guard to
also reject flag-like values by verifying $2 is present and does not start with
a hyphen (e.g., replace the condition with a test that $2 is non-empty and does
not match ^-), then keep the same error message and exit path so calls like
--template --version fail immediately and clearly; update the conditional in the
render-formula.sh option-handling block that currently uses [[ $# -lt 2 ]] to
this strengthened check.
.github/workflows/release-brew.yml (1)

96-107: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Don’t parse release tags from workflow_run.head_branch.

At Line 96 and Line 107, this still assumes github.event.workflow_run.head_branch is the release tag. In workflow_run chains, that value is not a reliable tag source for tag-originated runs, so formula publishing can be skipped or fail parsing. Resolve the tag from a tag-safe source (for example, tags pointing at github.event.workflow_run.head_sha) and parse <crate>-v<semver> from that resolved value.

In GitHub Actions workflow_run events, what is the reliable way to recover the upstream tag for a run triggered by tag push? Is workflow_run.head_branch guaranteed to contain the tag name?
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/release-brew.yml around lines 96 - 107, The workflow
currently treats github.event.workflow_run.head_branch as the release tag (see
the job if: condition and the Parse crate and version step using env TAG), but
head_branch is not a reliable source for upstream tags; change the logic to
resolve the tag that points at github.event.workflow_run.head_sha instead.
Update the if: conditional to not assume startsWith(head_branch, 'moq-') and in
the step with id=parse (and env TAG) call the GitHub API (or use
actions/github-script) to list refs/tags and find the tag whose object.sha
equals github.event.workflow_run.head_sha, then extract and parse the tag
matching the pattern <crate>-v<semver> to set TAG; ensure all downstream steps
use that resolved TAG.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Duplicate comments:
In @.github/scripts/render-formula.sh:
- Around line 31-34: The current check in the option parsing block (the if that
tests [[ $# -lt 2 ]]) only ensures a second argument exists but allows another
flag as the value; change the guard to also reject flag-like values by verifying
$2 is present and does not start with a hyphen (e.g., replace the condition with
a test that $2 is non-empty and does not match ^-), then keep the same error
message and exit path so calls like --template --version fail immediately and
clearly; update the conditional in the render-formula.sh option-handling block
that currently uses [[ $# -lt 2 ]] to this strengthened check.

In @.github/workflows/release-brew.yml:
- Around line 96-107: The workflow currently treats
github.event.workflow_run.head_branch as the release tag (see the job if:
condition and the Parse crate and version step using env TAG), but head_branch
is not a reliable source for upstream tags; change the logic to resolve the tag
that points at github.event.workflow_run.head_sha instead. Update the if:
conditional to not assume startsWith(head_branch, 'moq-') and in the step with
id=parse (and env TAG) call the GitHub API (or use actions/github-script) to
list refs/tags and find the tag whose object.sha equals
github.event.workflow_run.head_sha, then extract and parse the tag matching the
pattern <crate>-v<semver> to set TAG; ensure all downstream steps use that
resolved TAG.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 6af159e2-9a1a-4764-91e5-9ed9770b89c3

📥 Commits

Reviewing files that changed from the base of the PR and between cc770f2 and 512ed25.

📒 Files selected for processing (8)
  • .github/scripts/render-formula.sh
  • .github/workflows/moq-cli.yml
  • .github/workflows/moq-clock.yml
  • .github/workflows/moq-gst.yml
  • .github/workflows/moq-relay.yml
  • .github/workflows/moq-token-cli.yml
  • .github/workflows/release-brew.yml
  • rs/scripts/package-binary.sh

@kixelated kixelated enabled auto-merge (squash) May 23, 2026 19:39
claude added 4 commits May 23, 2026 19:46
The previous broad path filters (nix/**, flake.nix, flake.lock) fanned
out to 5 workflows x 4 targets = 20 parallel Nix builds whenever a PR
touched any of those, overwhelming the magic-nix-cache and producing
"GetCacheEntryDownloadURL: Rate limited" failures on macOS arm64.

Narrow each per-crate workflow's pull_request trigger to just the
workflow file, .github/scripts/release.sh, and the matching build
script - the same minimal pattern libmoq.yml uses. nix/overlay.nix and
the flake itself are already validated by check.yml's `just ci` (which
runs `nix flake check`), so they don't need to fan out here.

Also add a concurrency group to each release workflow that cancels
in-progress PR runs when a new commit lands. Tag-push (release) runs
are exempted (cancel-in-progress: false), since cancelling mid-release
would be destructive.

https://claude.ai/code/session_015J5tVAQ7ESjBhnzdeXfhgX
PR #1464 deliberately left moq-gst out of the dry-run set, and the
reason is clear in practice: moq-gst's Nix build pulls the full
gstreamer dep tree, so its macOS and Linux dry-runs both started
failing under the cache contention this PR creates by triggering five
release workflows in parallel.

Revert moq-gst.yml to exactly the main-branch contents (push-only
trigger, no concurrency block, no PR version fallback). The other four
workflows (moq-relay, moq-cli, moq-clock, moq-token-cli) keep their
dry-runs because their builds are smaller and aren't already on main.

https://claude.ai/code/session_015J5tVAQ7ESjBhnzdeXfhgX
Resolves conflicts between this branch's nix-based tarball workflows
for moq-cli/moq-relay/moq-token-cli and main's #1457 .deb/.rpm
packaging flow added to the same files. The merged workflows now do
both: main's linux cargo build + .deb + .rpm + apt/rpm repo publish
trigger, plus this branch's macOS tarball build via nix for Homebrew.

Per-crate workflow structure (moq-cli, moq-relay, moq-token-cli):
- build job (main's): linux x86_64+aarch64, cargo, plus a new
  "Package tarball (Homebrew)" step that produces a .tar.gz alongside
  the bare binary and .deb/.rpm. Trigger paths cover the workflow,
  release.sh, package-binary.sh, the packaging/<crate>/ directory, and
  the setup-packaging composite action.
- build-tarball-macos job (new): macOS x86_64+arm64 via nix, runs
  package-binary.sh to produce a .tar.gz for the Homebrew tap.
- release job: needs [build, build-tarball-macos], gated to push
  events so PR dry-runs don't try to upload assets or trigger
  apt/rpm repo publish.

moq-clock keeps the all-nix matrix from this branch (main didn't add
.deb/.rpm packaging for it). moq-gst takes main's content verbatim
(.deb/.rpm + nix tarball), with no PR dry-run.

Dry-run versioning: each Parse version step has a pull_request
fallback that reads from rs/<crate>/Cargo.toml instead of release.sh
parse-version (which requires a GITHUB_REF tag).

https://claude.ai/code/session_015J5tVAQ7ESjBhnzdeXfhgX
The merged-in workflow from #1457 references target/release/moq in the
bare-binary copy, .deb BINARY_PATH, and the docker rpm rebuild, but
cargo actually produces target/release/moq-cli (no [[bin]] override on
the moq-cli crate). No moq-cli release has been cut yet so the bug
hadn't been caught, but this PR's dry-run hits it: all four moq-cli
matrix jobs fail at "Package bare binary" with cp: cannot stat 'moq'.

Fix it the smallest way: after cargo build, copy
target/release/moq-cli to target/release/moq on the runner, and inside
the AlmaLinux docker (which does its own cargo build) cp from
target/release/moq-cli straight to target/moq.rpm-build instead of
through a nonexistent target/release/moq. The .deb nfpm BINARY_PATH
keeps pointing at target/release/moq because the host-side rename
makes that path exist.

https://claude.ai/code/session_015J5tVAQ7ESjBhnzdeXfhgX
Copy link
Copy Markdown
Contributor

@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: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
.github/workflows/release-brew.yml (1)

100-100: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Block PR-originated workflow_run from publishing to homebrew-tap.

release-brew.yml’s publish job runs on successful workflow_run and currently gates only on startsWith(github.event.workflow_run.head_branch, 'moq-'). Since upstream workflows (e.g., moq-cli.yml, moq-clock.yml, moq-relay.yml, moq-token-cli.yml) are triggered by pull_request, a successful PR run can satisfy this gate and reach privileged code that mints a GitHub App token with permission-contents: write for moq-dev/homebrew-tap.

Minimal hardening patch
-    if: ${{ github.event_name == 'workflow_run' && github.event.workflow_run.conclusion == 'success' && startsWith(github.event.workflow_run.head_branch, 'moq-') }}
+    if: ${{ github.event_name == 'workflow_run'
+      && github.event.workflow_run.conclusion == 'success'
+      && github.event.workflow_run.event == 'push'
+      && github.event.workflow_run.head_repository.full_name == github.repository
+      && startsWith(github.event.workflow_run.head_branch || '', 'moq-') }}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/release-brew.yml at line 100, The current publish gate
that checks the if condition (github.event_name == 'workflow_run' &&
github.event.workflow_run.conclusion == 'success' &&
startsWith(github.event.workflow_run.head_branch, 'moq-')) allows workflow_runs
originating from pull_request events; tighten this by also requiring the
upstream run to be a push (e.g., add a check that
github.event.workflow_run.event == 'push') so PR-originated workflow_run events
cannot trigger the publish job; update the conditional expression accordingly in
release-brew.yml to include that additional check.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/moq-cli.yml:
- Around line 78-79: The workflow is copying the wrong binary name for several
packaging steps: change instances of the path fragment
"target/${target}/release/moq" to "target/${target}/release/moq-cli" so the
Homebrew tarball and the moq-cli crate produce an executable named moq-cli
(leave nfpm packaging behavior as-is so it can still install it as
/usr/bin/moq); update the cp invocations in the packaging job that currently
reference release/moq to reference release/moq-cli to match the crate and
formula expectations.

---

Outside diff comments:
In @.github/workflows/release-brew.yml:
- Line 100: The current publish gate that checks the if condition
(github.event_name == 'workflow_run' && github.event.workflow_run.conclusion ==
'success' && startsWith(github.event.workflow_run.head_branch, 'moq-')) allows
workflow_runs originating from pull_request events; tighten this by also
requiring the upstream run to be a push (e.g., add a check that
github.event.workflow_run.event == 'push') so PR-originated workflow_run events
cannot trigger the publish job; update the conditional expression accordingly in
release-brew.yml to include that additional check.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: a243c8f9-1095-4f7f-9497-2619cdb89639

📥 Commits

Reviewing files that changed from the base of the PR and between 512ed25 and 38bddb6.

📒 Files selected for processing (5)
  • .github/workflows/moq-cli.yml
  • .github/workflows/moq-clock.yml
  • .github/workflows/moq-relay.yml
  • .github/workflows/moq-token-cli.yml
  • .github/workflows/release-brew.yml

Comment thread .github/workflows/moq-cli.yml
@kixelated kixelated merged commit 88b9225 into main May 23, 2026
12 of 19 checks passed
@kixelated kixelated deleted the claude/homebrew-tap-setup-F9ejS branch May 23, 2026 20:53
kixelated pushed a commit that referenced this pull request May 23, 2026
nfpm's env-var expansion (${VAR}) only fires on a small allow-list of
top-level fields (name, arch, version, ...). For contents[].src and
contents[].dst the value flows straight into the glob handler, which
treats ${BINARY_PATH} as a literal pattern and fails with
"glob failed: ${BINARY_PATH}: no matching files". The Go-template
form {{ .Env.VAR }} doesn't help either: nfpm's templating doc lists
only the same restricted set of fields, not contents[].

Pre-render the YAML with envsubst before passing it to nfpm. envsubst
substitutes ${VAR} in both contents[] and the top-level fields, so
nfpm sees a fully-resolved config.

Use the explicit allow-list form (`envsubst '$VERSION $ARCH ...'`) so
unrelated $-references in the YAML can't be substituted by accident.

Without this fix the .deb and .rpm jobs die at the nfpm pkg step,
which is what surfaced in the dry-run on #1456 and again in this PR's
first attempted fix.

https://claude.ai/code/session_015J5tVAQ7ESjBhnzdeXfhgX
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