-
-
Notifications
You must be signed in to change notification settings - Fork 13
chore(ci): merge queue support and release --yes (#378) #849
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,68 @@ | ||
| { | ||
| "name": "main merge queue", | ||
| "target": "branch", | ||
| "enforcement": "active", | ||
| "conditions": { | ||
| "ref_name": { | ||
| "include": ["refs/heads/main"], | ||
| "exclude": [] | ||
| } | ||
| }, | ||
| "bypass_actors": [ | ||
| { | ||
| "actor_id": 5, | ||
| "actor_type": "RepositoryRole", | ||
| "bypass_mode": "always" | ||
| }, | ||
| { | ||
| "actor_id": 15368, | ||
| "actor_type": "Integration", | ||
| "bypass_mode": "always" | ||
| } | ||
| ], | ||
| "rules": [ | ||
| { | ||
| "type": "deletion" | ||
| }, | ||
| { | ||
| "type": "non_fast_forward" | ||
| }, | ||
| { | ||
| "type": "pull_request", | ||
| "parameters": { | ||
| "required_approving_review_count": 0, | ||
| "dismiss_stale_reviews": false, | ||
| "require_code_owner_review": false, | ||
| "require_last_push_approval": false, | ||
| "required_review_thread_resolution": false, | ||
| "allowed_merge_methods": ["squash", "rebase"] | ||
| } | ||
| }, | ||
| { | ||
| "type": "required_status_checks", | ||
| "parameters": { | ||
| "strict_required_status_checks_policy": true, | ||
| "do_not_enforce_on_create": false, | ||
| "required_status_checks": [ | ||
| { "context": "Build & Test" }, | ||
| { "context": "Coverage (renderer-ui)" }, | ||
| { "context": "Coverage (renderer-logic)" }, | ||
| { "context": "Coverage (main)" }, | ||
| { "context": "Merge coverage" } | ||
| ] | ||
|
Comment on lines
+46
to
+52
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win 🧩 Analysis chain🏁 Script executed: #!/usr/bin/env bash
set -euo pipefail
repo=Colorado-Mesh/mesh-client
sha="${1:?usage: $0 MERGE_GROUP_SHA}"
for context in \
"Build & Test" \
"Coverage (renderer-ui)" \
"Coverage (renderer-logic)" \
"Coverage (main)" \
"Merge coverage"
do
echo "== ${context} =="
gh api "repos/${repo}/commits/${sha}/check-runs" --paginate \
--jq ".check_runs[] | select(.name == \"${context}\") | [.name, (.app.id // 0), (.app.slug // \"\")] | `@tsv`"
doneRepository: Colorado-Mesh/mesh-client Length of output: 208 🏁 Script executed: #!/usr/bin/env bash
set -euo pipefail
printf '%s\n' '== ruleset =='
cat -n .github/rulesets/main-merge-queue.json
printf '%s\n' '== workflow and ruleset references =='
rg -n -C 3 '15368|third-party-licenses|merge_group|Build & Test|Coverage \(renderer-ui\)|Coverage \(renderer-logic\)|Coverage \(main\)|Merge coverage|integration_id|required_status_checks|bypass' \
.github README.md docs 2>/dev/null || true
printf '%s\n' '== candidate workflow files =='
git ls-files '.github/workflows/*' '.github/rulesets/*' | sortRepository: Colorado-Mesh/mesh-client Length of output: 23552 🏁 Script executed: #!/usr/bin/env bash
set -euo pipefail
repo=Colorado-Mesh/mesh-client
printf '%s\n' '== GitHub Actions app identity =='
gh api "apps/github-actions" --jq '[.id, .slug, .name] | `@tsv`'
printf '%s\n' '== recent merge_group workflow runs =='
gh api "repos/${repo}/actions/runs?event=merge_group&per_page=20" \
--jq '.workflow_runs[] | [.id, .head_sha, .name, .status, .conclusion] | `@tsv`'
printf '%s\n' '== recent merge_group check runs =='
gh api "repos/${repo}/actions/runs?event=merge_group&per_page=10" \
--jq '.workflow_runs[] | [.head_sha, .id] | `@tsv`' |
while IFS=$'\t' read -r sha run_id; do
[ -n "$sha" ] || continue
echo "SHA ${sha} (run ${run_id})"
gh api "repos/${repo}/commits/${sha}/check-runs" --paginate \
--jq '.check_runs[] | [.name, (.app.id // 0), (.app.slug // ""), .status, (.conclusion // "")] | `@tsv`'
done
printf '%s\n' '== workflow job names and merge_group triggers =='
for file in .github/workflows/ci.yaml .github/workflows/tests.yaml; do
echo "--- ${file}"
cat -n "${file}" | sed -n '1,180p'
doneRepository: Colorado-Mesh/mesh-client Length of output: 10529 🌐 Web query:
💡 Result: In GitHub repository rulesets, the integration_id is an optional parameter within the required_status_checks rule [1][2][3]. This field allows you to specify that a required status check must originate from a particular GitHub App [1][4]. When you configure a required status check rule, you can use the integration_id to ensure that only statuses submitted by the identified GitHub App will satisfy the requirement [4]. If this parameter is omitted or not set to a specific app, the rule may accept status checks from other sources, depending on your configuration, or it may require manual verification of the status author [4][5]. For the REST API, the required_status_checks object contains an array of objects, where each object includes [1][2][6]: - context: The name of the status check [1][3]. - integration_id: The optional ID of the integration (GitHub App) that must provide this status check [1][7]. This provides a mechanism to enforce that critical CI/CD checks originate from trusted applications rather than any user or integration with write permissions [4][5]. Citations:
Pin each required check to GitHub Actions. Add 🤖 Prompt for AI Agents |
||
| } | ||
| }, | ||
| { | ||
| "type": "merge_queue", | ||
| "parameters": { | ||
| "merge_method": "SQUASH", | ||
| "max_entries_to_build": 5, | ||
| "min_entries_to_merge": 1, | ||
| "max_entries_to_merge": 5, | ||
| "min_entries_to_merge_wait_minutes": 0, | ||
| "check_response_timeout_minutes": 90, | ||
| "grouping_strategy": "ALLGREEN" | ||
| } | ||
| } | ||
| ] | ||
| } | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,124 @@ | ||||||||||||||||||||||||||||||||||||
| # Optional maintainer path: cut a release from Actions. | ||||||||||||||||||||||||||||||||||||
| # Prefer local `pnpm run release --yes` when practical — full preflight needs | ||||||||||||||||||||||||||||||||||||
| # cargo, flatpak-node-generator, actionlint, and several minutes of Vitest. | ||||||||||||||||||||||||||||||||||||
| # | ||||||||||||||||||||||||||||||||||||
| # Requires repository secret RELEASE_PUSH_TOKEN (PAT / GitHub App) with | ||||||||||||||||||||||||||||||||||||
| # contents:write + workflows:write so the tag push can trigger release.yaml / | ||||||||||||||||||||||||||||||||||||
| # flatpak.yaml. Default GITHUB_TOKEN will not re-trigger those workflows. | ||||||||||||||||||||||||||||||||||||
| # | ||||||||||||||||||||||||||||||||||||
| # Does NOT publish the draft GitHub Release — review artifacts, then Publish. | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| name: Cut release | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| env: | ||||||||||||||||||||||||||||||||||||
| FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| on: | ||||||||||||||||||||||||||||||||||||
| workflow_dispatch: | ||||||||||||||||||||||||||||||||||||
| inputs: | ||||||||||||||||||||||||||||||||||||
| bump: | ||||||||||||||||||||||||||||||||||||
| description: 'Version bump (auto, patch, minor, major, or exact X.Y.Z)' | ||||||||||||||||||||||||||||||||||||
| required: false | ||||||||||||||||||||||||||||||||||||
| default: auto | ||||||||||||||||||||||||||||||||||||
| type: string | ||||||||||||||||||||||||||||||||||||
| skip_dep_update: | ||||||||||||||||||||||||||||||||||||
| description: 'Skip pnpm update/dedupe (use when lockfile is already current)' | ||||||||||||||||||||||||||||||||||||
| required: false | ||||||||||||||||||||||||||||||||||||
| default: false | ||||||||||||||||||||||||||||||||||||
| type: boolean | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| concurrency: | ||||||||||||||||||||||||||||||||||||
| group: cut-release | ||||||||||||||||||||||||||||||||||||
| cancel-in-progress: false | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| jobs: | ||||||||||||||||||||||||||||||||||||
| release: | ||||||||||||||||||||||||||||||||||||
| name: Cut release (--yes) | ||||||||||||||||||||||||||||||||||||
| runs-on: ubuntu-latest | ||||||||||||||||||||||||||||||||||||
| permissions: | ||||||||||||||||||||||||||||||||||||
| contents: read | ||||||||||||||||||||||||||||||||||||
| steps: | ||||||||||||||||||||||||||||||||||||
| - name: Require RELEASE_PUSH_TOKEN | ||||||||||||||||||||||||||||||||||||
| env: | ||||||||||||||||||||||||||||||||||||
| RELEASE_PUSH_TOKEN: ${{ secrets.RELEASE_PUSH_TOKEN }} | ||||||||||||||||||||||||||||||||||||
| run: | | ||||||||||||||||||||||||||||||||||||
| if [ -z "${RELEASE_PUSH_TOKEN}" ]; then | ||||||||||||||||||||||||||||||||||||
| echo '::error::Set repository secret RELEASE_PUSH_TOKEN (contents+workflows).' | ||||||||||||||||||||||||||||||||||||
| echo 'Default GITHUB_TOKEN cannot trigger release.yaml / flatpak.yaml on tag push.' | ||||||||||||||||||||||||||||||||||||
| echo 'Prefer local: pnpm run release --yes' | ||||||||||||||||||||||||||||||||||||
| exit 1 | ||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| - name: Checkout main | ||||||||||||||||||||||||||||||||||||
| uses: actions/checkout@v6 | ||||||||||||||||||||||||||||||||||||
| with: | ||||||||||||||||||||||||||||||||||||
| ref: main | ||||||||||||||||||||||||||||||||||||
| fetch-depth: 0 | ||||||||||||||||||||||||||||||||||||
| token: ${{ secrets.RELEASE_PUSH_TOKEN }} | ||||||||||||||||||||||||||||||||||||
| persist-credentials: true | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| - name: Setup pnpm | ||||||||||||||||||||||||||||||||||||
| uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| - name: Setup Node | ||||||||||||||||||||||||||||||||||||
| uses: actions/setup-node@v6 | ||||||||||||||||||||||||||||||||||||
| with: | ||||||||||||||||||||||||||||||||||||
| node-version: '22' | ||||||||||||||||||||||||||||||||||||
| cache: 'pnpm' | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| - name: Install dependencies | ||||||||||||||||||||||||||||||||||||
| run: pnpm install --frozen-lockfile | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| - name: Install actionlint | ||||||||||||||||||||||||||||||||||||
| run: pnpm run setup:actionlint | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| - name: Install yamllint | ||||||||||||||||||||||||||||||||||||
| run: pip install yamllint | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| - name: Install flatpak-node-generator | ||||||||||||||||||||||||||||||||||||
| run: | | ||||||||||||||||||||||||||||||||||||
| FBTOOLS=git+https://github.com/flatpak/flatpak-builder-tools | ||||||||||||||||||||||||||||||||||||
| # Keep in sync with scripts/flatpakPnpmStoreVersion.mjs FLATPAK_NODE_GENERATOR_COMMIT. | ||||||||||||||||||||||||||||||||||||
| pip3 install --force-reinstall --no-cache-dir \ | ||||||||||||||||||||||||||||||||||||
| "${FBTOOLS}@b97a6e66f3fa46efad54738168e34e61b2b8c6f4#subdirectory=node" | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| - name: Install Linux build deps (sidecar / Flatpak checks) | ||||||||||||||||||||||||||||||||||||
| run: sudo apt-get update && sudo apt-get install -y libdbus-1-dev pkg-config | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| - name: Setup Rust | ||||||||||||||||||||||||||||||||||||
| uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| - name: Add actionlint to PATH | ||||||||||||||||||||||||||||||||||||
| run: echo "${{ github.workspace }}/.githooks/bin" >> "$GITHUB_PATH" | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| - name: Configure git identity | ||||||||||||||||||||||||||||||||||||
| run: | | ||||||||||||||||||||||||||||||||||||
| git config user.name 'github-actions[bot]' | ||||||||||||||||||||||||||||||||||||
| git config user.email '41898282+github-actions[bot]@users.noreply.github.com' | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| - name: Run release (MESH_CLIENT_RELEASE_YES) | ||||||||||||||||||||||||||||||||||||
| env: | ||||||||||||||||||||||||||||||||||||
| MESH_CLIENT_RELEASE_YES: '1' | ||||||||||||||||||||||||||||||||||||
| run: | | ||||||||||||||||||||||||||||||||||||
| set -euo pipefail | ||||||||||||||||||||||||||||||||||||
| BUMP='${{ inputs.bump }}' | ||||||||||||||||||||||||||||||||||||
| EXTRA=() | ||||||||||||||||||||||||||||||||||||
| if [ '${{ inputs.skip_dep_update }}' = 'true' ]; then | ||||||||||||||||||||||||||||||||||||
|
Comment on lines
+99
to
+106
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win Do not interpolate workflow inputs into shell source.
Pass inputs through Proposed fix - name: Run release (MESH_CLIENT_RELEASE_YES)
env:
MESH_CLIENT_RELEASE_YES: '1'
+ BUMP: ${{ inputs.bump }}
+ SKIP_DEP_UPDATE: ${{ inputs.skip_dep_update }}
run: |
set -euo pipefail
- BUMP='${{ inputs.bump }}'
EXTRA=()
- if [ '${{ inputs.skip_dep_update }}' = 'true' ]; then
+ if [ "$SKIP_DEP_UPDATE" = 'true' ]; then
EXTRA+=(--skip-dep-update)
fi📝 Committable suggestion
Suggested change
🧰 Tools🪛 zizmor (1.29.0)[error] 104-104: code injection via template expansion (template-injection): may expand into attacker-controllable code (template-injection) 🤖 Prompt for AI AgentsSource: Linters/SAST tools |
||||||||||||||||||||||||||||||||||||
| EXTRA+=(--skip-dep-update) | ||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||
| case "$BUMP" in | ||||||||||||||||||||||||||||||||||||
| auto|'') | ||||||||||||||||||||||||||||||||||||
| pnpm run release -- --auto "${EXTRA[@]}" | ||||||||||||||||||||||||||||||||||||
| ;; | ||||||||||||||||||||||||||||||||||||
| patch|minor|major) | ||||||||||||||||||||||||||||||||||||
| pnpm run release -- "$BUMP" "${EXTRA[@]}" | ||||||||||||||||||||||||||||||||||||
| ;; | ||||||||||||||||||||||||||||||||||||
| *) | ||||||||||||||||||||||||||||||||||||
| if [[ "$BUMP" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then | ||||||||||||||||||||||||||||||||||||
| pnpm run release -- "$BUMP" "${EXTRA[@]}" | ||||||||||||||||||||||||||||||||||||
| else | ||||||||||||||||||||||||||||||||||||
| echo "::error::Invalid bump input: $BUMP" | ||||||||||||||||||||||||||||||||||||
| exit 1 | ||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||
| ;; | ||||||||||||||||||||||||||||||||||||
| esac | ||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9,3 +9,4 @@ ignore: | | |
| pnpm-lock.yaml | ||
| node_modules/ | ||
| .rsstack/ | ||
| .github/rulesets/ | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,21 +8,22 @@ Mesh-Client uses GitHub Actions for continuous integration and deployment. | |
|
|
||
| | Workflow | Trigger | Purpose | | ||
| | --------------------------- | -------------------------------------------- | ------------------------------------------------------------------------------- | | ||
| | `ci.yaml` | Push/PR to `main` | Lint, typecheck, build, Flatpak manifest validation | | ||
| | `tests.yaml` | Push/PR to `main` | Vitest coverage + merge; Reticulum sidecar `llvm-cov` when sidecar paths change | | ||
| | `ci.yaml` | Push/PR/`merge_group` to `main` | Lint, typecheck, build, Flatpak manifest validation | | ||
| | `tests.yaml` | Push/PR/`merge_group` to `main` | Vitest coverage + merge; Reticulum sidecar `llvm-cov` when sidecar paths change | | ||
| | `e2e.yaml` | Daily on `main` + manual `workflow_dispatch` | Playwright Electron E2E (unpackaged build, 3-OS; not a PR gate) | | ||
| | `build.yaml` | Manual `workflow_dispatch` | Native 3-OS packaging smoke build (+ schema compare vs last official) | | ||
| | `reticulum-sidecar.yaml` | Path-filtered push/PR to `main` | Sidecar fmt + Clippy (ubuntu); multi-OS matrix build/test | | ||
| | `release.yaml` | Version tags (`v*`) | Build & publish releases (AppImage/deb/rpm) | | ||
| | `flatpak.yaml` | Version tags (`v*`), manual | Build Flatpak (+ schema compare vs last official); publish to release on tags | | ||
| | `cut-release.yaml` | Manual `workflow_dispatch` | Optional Actions-driven `pnpm run release --yes` (needs `RELEASE_PUSH_TOKEN`) | | ||
| | `docs.yml` | Push to `main` | Deploy MkDocs to GitHub Pages | | ||
| | `third-party-licenses.yaml` | Path-filtered push to `main` + dispatch | Regenerate `docs/third-party-licenses.md` after dependency changes | | ||
|
|
||
| --- | ||
|
|
||
| ## CI Build (`ci.yaml`) | ||
|
|
||
| Runs on every push and pull request to `main` (and `workflow_dispatch`): | ||
| Runs on every push, pull request, and merge-queue `merge_group` for `main` (and `workflow_dispatch`): | ||
|
|
||
| 1. Checkout code | ||
| 2. Setup pnpm | ||
|
|
@@ -45,7 +46,7 @@ All blocking steps must pass before a PR can be merged. | |
|
|
||
| ## Tests (`tests.yaml`) | ||
|
|
||
| Runs on every push and pull request to `main`: | ||
| Runs on every push, pull request, and merge-queue `merge_group` for `main`: | ||
|
|
||
| 1. Checkout code, setup pnpm + Node 22, install dependencies | ||
| 2. **Parallel matrix** — coverage per Vitest project (`renderer-ui`, `renderer-logic`, `main`) with blob reporter (`VITEST_COVERAGE_SHARD=1` skips per-shard threshold checks) | ||
|
|
@@ -273,16 +274,80 @@ Note: The test results artifact upload step is automatically skipped when runnin | |
|
|
||
| --- | ||
|
|
||
| ## Required Status Checks | ||
| ## Pipeline status (issue #378) | ||
|
|
||
| | Area | Status | | ||
| | ------------------------------------------------ | ------------------------------------------------------------------- | | ||
| | PR lint / typecheck / build / tests | Done (`ci.yaml`, `tests.yaml`) | | ||
| | CodeQL / CodeRabbit | Done (CodeQL **default setup** — PR/push/schedule; not merge-queue) | | ||
| | Tag → draft multi-OS + Flatpak + packaging smoke | Done (`release.yaml`, `flatpak.yaml`, `build.yaml`) | | ||
| | `pnpm run release` preflight + bump/tag | Done (`scripts/release.sh`; `--yes` for non-interactive) | | ||
| | Manual draft **Publish** on GitHub | Intentional (human review of artifacts) | | ||
| | Dep bumps | Manual (`pnpm run update`; Dependabot PRs disabled) | | ||
| | Merge queue + required status checks | Repository ruleset on `main` (see below) | | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win 🧩 Analysis chain🏁 Script executed: #!/usr/bin/env bash
set -euo pipefail
gh api repos/Colorado-Mesh/mesh-client/rulesets \
--jq '.[] | select(.name == "main merge queue") | [.id, .enforcement, (.conditions.ref_name.include // [] | join(","))] | `@tsv`'Repository: Colorado-Mesh/mesh-client Length of output: 163 🏁 Script executed: #!/usr/bin/env bash
set -euo pipefail
printf '%s\n' '--- docs/ci-cd.md relevant sections ---'
sed -n '1,75p;270,365p' docs/ci-cd.md
printf '%s\n' '--- workflow triggers ---'
for f in .github/workflows/ci.yaml .github/workflows/cut-release.yaml; do
if [ -f "$f" ]; then
echo "### $f"
sed -n '1,45p' "$f"
fi
done
printf '%s\n' '--- ruleset files and references ---'
git ls-files | rg '(^|/)(AGENTS\.md|.*ruleset.*|.*merge.*queue.*|.*ci.*cd.*)$' || true
rg -n 'main merge queue|enforcement|merge_group|workflow_dispatch|test:coverage(:merge)?|post-merge|pending' .github docs README.md 2>/dev/null || true
printf '%s\n' '--- remote ruleset API response ---'
gh api repos/Colorado-Mesh/mesh-client/rulesets --include 2>&1 | sed -n '1,120p'Repository: Colorado-Mesh/mesh-client Length of output: 42624 Mark the ruleset rollout as pending. The repository currently has no remote 🤖 Prompt for AI Agents |
||
| | E2E | Daily / `workflow_dispatch` only — **not** a merge gate | | ||
|
|
||
| --- | ||
|
|
||
| ## Merge queue and rulesets | ||
|
|
||
| `main` is protected by a **repository ruleset** (not classic branch protection) that: | ||
|
|
||
| 1. Requires a pull request before merging | ||
| 2. Requires a **merge queue** | ||
| 3. Requires **strict** status checks (must pass on the merge group / up-to-date tip) | ||
| 4. Blocks force-pushes and branch deletion on `main` | ||
|
|
||
| ### Required check names (always-on) | ||
|
|
||
| Only checks that report on every PR and every `merge_group` run are required: | ||
|
|
||
| | Check name | Workflow | | ||
| | --------------------------- | ------------ | | ||
| | `Build & Test` | `ci.yaml` | | ||
| | `Coverage (renderer-ui)` | `tests.yaml` | | ||
| | `Coverage (renderer-logic)` | `tests.yaml` | | ||
| | `Coverage (main)` | `tests.yaml` | | ||
| | `Merge coverage` | `tests.yaml` | | ||
|
|
||
| **Do not** add these as required (they skip or are not PR/`merge_group` gates and would stall the queue): | ||
|
|
||
| - `Reticulum sidecar coverage` (path-filtered) | ||
| - `fmt + clippy` / sidecar build matrix (`reticulum-sidecar.yaml`, path-filtered) | ||
| - CodeQL `Analyze (*)` — **default setup does not run on `merge_group`**; CodeQL still runs on PRs/pushes. Requiring it would hang the merge queue until advanced setup + `merge_group` exists. | ||
| - E2E, packaging smoke, Flatpak, release jobs | ||
|
|
||
| All PRs to `main` must pass: | ||
| `ci.yaml` and `tests.yaml` both listen for `merge_group` so the queue’s temporary ref re-runs the same gates. | ||
|
|
||
| ### Applying / updating the ruleset | ||
|
|
||
| Canonical JSON lives at [`.github/rulesets/main-merge-queue.json`](../.github/rulesets/main-merge-queue.json). | ||
|
|
||
| ```bash | ||
| # Create (first time) | ||
| gh api repos/Colorado-Mesh/mesh-client/rulesets \ | ||
| --method POST \ | ||
| --input .github/rulesets/main-merge-queue.json | ||
|
|
||
| # Update (after noting the ruleset id from `gh api .../rulesets`) | ||
| gh api repos/Colorado-Mesh/mesh-client/rulesets/RULESET_ID \ | ||
| --method PUT \ | ||
| --input .github/rulesets/main-merge-queue.json | ||
| ``` | ||
|
|
||
| Bypass actors: repository **Admin** role (`actor_id` 5) and the **GitHub Actions** app (`Integration` 15368) for `third-party-licenses.yaml` pushes. | ||
|
|
||
| **Rollout:** merge the PR that adds `merge_group` triggers to `ci.yaml` / `tests.yaml` **before** flipping this ruleset to `enforcement: active`. Enabling the queue without those triggers leaves required checks pending forever. | ||
|
|
||
| --- | ||
|
|
||
| ## Required Status Checks | ||
|
|
||
| - Lint (`pnpm run lint`) | ||
| - Typecheck (`pnpm run typecheck`) | ||
| - Build (`pnpm run build`) | ||
| - Tests with coverage (`pnpm run test:coverage` — same as CI; `locale-quality.test.ts` runs `check:i18n` as part of the Vitest suite) | ||
| All PRs (and merge-queue groups) for `main` must pass the **required check names** listed above. Those jobs cover: | ||
|
|
||
| Branch protection is configured to require these checks before merging. | ||
| - Lint, format, markdown, licenses, actionlint, yamllint (`pnpm run lint` and related steps in `ci.yaml`) | ||
| - Typecheck and build (`pnpm run typecheck`, `pnpm run build`) | ||
| - Tests with coverage (`pnpm run test:coverage` merge — `locale-quality.test.ts` runs `check:i18n` as part of the Vitest suite) | ||
|
|
||
| --- | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift
🧩 Analysis chain
🏁 Script executed:
Repository: Colorado-Mesh/mesh-client
Length of output: 17746
🏁 Script executed:
Repository: Colorado-Mesh/mesh-client
Length of output: 20240
🌐 Web query:
GitHub repository rulesets bypass_actors Integration workflow-specific bypass GitHub Actions app ruleset API💡 Result:
To bypass repository rulesets in a GitHub Actions workflow, you must use a GitHub App, as the built-in
github-actions[bot]is a system actor that cannot be added to a bypass list [1]. ### Implementation Workflow To configure a workflow to bypass enforced rules (e.g., "Require a pull request"), follow these steps: 1. Create a GitHub App: Register a new GitHub App under your user or organization with the necessary permissions (e.g.,Contents: read & write) [2][1]. 2. Install the App: Install the app on the specific repository where the ruleset is enforced [2][1]. 3. Configure Bypass Actors: In the repository's ruleset settings, add the GitHub App to the "Bypass list" [3][1]. You can choose the bypass mode: -always: The app can bypass rules at all times [4]. -pull_request: The app can only bypass rules on pull requests [4]. -exempt: The app silently skips enforcement, and no bypass audit entry is created [5][4]. 4. Mint Installation Tokens: In your workflow, use an action such asactions/create-github-app-tokento generate a short-lived installation token for the App [6][2]. 5. Authenticate Git Operations: Use this installation token in youractions/checkoutstep (or by configuring the git remote URL) so that subsequent git operations (like push or commit) are performed as the App, not the defaultGITHUB_TOKEN[7][6][2]. ### Key Technical Notes * Identity Matters: The bypass grant is tied to the identity of the actor performing the action [1]. Using a personal access token (PAT) is an alternative, but using a GitHub App is the recommended practice for automation because it avoids tying repository permissions to a human user [8][1]. * API Interaction: When configuring rulesets via the GitHub REST API, use thebypass_actorsarray within the ruleset object, specifyingactor_type: "Integration"and theactor_id(the numeric App ID) [9][4]. * Limitation: Note that while bypass actors can override push/merge restrictions, these bypass grants are not honored by asynchronous auto-merge completion processes (e.g.,gh pr merge --auto) [10]. Automations relying on bypass should instead use the merge API directly [10].Citations:
🏁 Script executed:
Repository: Colorado-Mesh/mesh-client
Length of output: 8444
🌐 Web query:
site:docs.github.com repository rulesets bypass actors GitHub Actions GITHUB_TOKEN integration actor workflow scope💡 Result:
Repository rulesets do not provide a mechanism to bypass rules using the default GITHUB_TOKEN [1][2]. Ruleset bypass permissions are managed by explicitly granting access to specific "bypass actors," which are limited to defined Roles, Teams, or GitHub Apps [3][4][5]. The GITHUB_TOKEN is a machine-generated token associated with the repository's GitHub Actions App installation [6], and it is not a configurable "bypass actor" that can be added to a ruleset's bypass list [4]. Key considerations regarding this integration: 1. Bypass Actor Scope: You can grant bypass permissions to GitHub Apps [3][5]. If you require a workflow to bypass rulesets (for example, to perform actions that would otherwise be blocked, like force-pushing), you must use a dedicated GitHub App installation access token or a personal access token (PAT) with appropriate permissions, rather than the standard GITHUB_TOKEN [6][7][8]. 2. GITHUB_TOKEN Limitations: The GITHUB_TOKEN is restricted to the repository where the workflow runs [6]. It is specifically designed to prevent recursive workflow triggers and lacks the administrative bypass privileges required to override repository rulesets [6][7]. 3. Troubleshooting: If your workflows are failing due to ruleset constraints, ensure that the token being used has been granted explicit bypass permissions in the ruleset settings [3][9]. If you are using a GitHub App, you must add that app as a bypass actor in the ruleset configuration [3][4]. For scenarios where automated processes need to bypass rules, the recommended practice is to create a GitHub App, grant it the necessary bypass permissions in the ruleset [3][5], and authenticate using its installation access token within your GitHub Actions workflow [7][8].
Citations:
🏁 Script executed:
Repository: Colorado-Mesh/mesh-client
Length of output: 20344
🌐 Web query:
site:docs.github.com "GitHub Actions" "bypass" "ruleset" "GITHUB_TOKEN"💡 Result:
The GITHUB_TOKEN used in GitHub Actions cannot inherently bypass repository rulesets. Repository rulesets are designed to enforce branch and tag protection policies, and they operate independently of the GITHUB_TOKEN's permissions [1][2][3]. Key points regarding GITHUB_TOKEN and rulesets: 1. Ruleset Enforcement: Rulesets apply to all actors, including those using the GITHUB_TOKEN [1][3]. While you can grant bypass permissions in a ruleset, these permissions are specifically assigned to users, teams, or GitHub Apps; the GITHUB_TOKEN itself is not a valid principal for receiving bypass bypass rights [4]. 2. Token Limitations: The GITHUB_TOKEN is a machine-to-machine token restricted to the scope and permissions defined within the workflow file (or default settings) [5][6]. It does not possess the identity or administrative authority of a user or a GitHub App, meaning it cannot "override" or "bypass" ruleset requirements such as required status checks or branch protection [1][2][3]. 3. Ruleset Workflows: Note that ruleset-triggered workflows themselves do not run on events triggered by the GITHUB_TOKEN to prevent potential recursive loops or security bypasses [1][3]. If you find that a workflow is failing due to a ruleset, you must either adjust the workflow to comply with the rules (e.g., ensure required status checks pass) or grant bypass permissions to a specific GitHub App or authorized human user who can perform the necessary actions [1][2][4]. If the GITHUB_TOKEN requires permissions not available to it, you should use a personal access token (PAT) or a GitHub App installation token, though these also must comply with existing rulesets unless specifically granted bypass rights [6].
Citations:
🏁 Script executed:
Repository: Colorado-Mesh/mesh-client
Length of output: 8627
🌐 Web query:
"actor_id": 15368" GitHub Actions ruleset bypass GITHUB_TOKEN💡 Result:
The ID 15368 corresponds to the built-in GitHub Actions integration (often referred to as the GitHub Actions App) [1][2]. When configuring GitHub repository rulesets, this identifier is used to allow GitHub Actions workflows to bypass branch protection rules [1][3]. It is a common misconception that the default GITHUB_TOKEN itself is a bypass actor that can be directly added to a ruleset [4]. In reality, the GITHUB_TOKEN is the authentication credential used by the GitHub Actions integration [3]. To allow workflows using the default GITHUB_TOKEN to perform actions that would otherwise be blocked by rulesets (such as pushing directly to a protected branch), you must add the GitHub Actions integration to the bypass list of your ruleset using its actor_id (15368) and actor_type (Integration) [4][1][3]. Key details regarding this configuration include: - Bypass Configuration: You must add an entry to the bypass_actors array in your ruleset configuration with actor_id: 15368 and actor_type: Integration [5][1][3]. - Bypass Mode: Depending on your workflow's requirements, you may set the bypass_mode to always (if the workflow performs direct pushes) or pull_request (if it primarily interacts with pull requests) [6][4]. - Permissions: Simply adding the Integration to the bypass list does not grant it permissions it does not otherwise possess; the workflow must still have the necessary repository permissions (e.g., contents: write) to perform the intended action [7][8]. - Identification: This ID is a global, constant value for the GitHub Actions integration across GitHub [2]. It can be verified using the GitHub API by querying /apps/github-actions [2].
Citations:
actor_id/integration_idcan be found integrations/terraform-provider-github#2474🌐 Web query:
site:github.com/github/docs ruleset bypass GitHub Actions app GITHUB_TOKEN contents write protected branch💡 Result:
The GITHUB_TOKEN is a GitHub App installation access token [1] that operates within the constraints of your repository's branch protection and ruleset configurations [2][3]. Simply assigning contents: write permission to the GITHUB_TOKEN does not allow a workflow to bypass branch protection or rulesets [4][3]. Branch protection rules and rulesets are designed to enforce security policies (such as requiring pull request reviews or signed commits) regardless of the identity or token used to attempt a push [5][6]. Even with contents: write access, if a workflow attempts to push directly to a protected branch that forbids such actions, the push will be rejected by GitHub [5][6]. To interact with protected branches or bypass rulesets via GitHub Actions, you must account for the following: 1. Bypass Permissions: Rulesets allow you to explicitly grant bypass permissions to specific actors, including GitHub Apps or teams [6]. If you need a workflow to bypass a ruleset, you must grant the workflow's underlying identity (or a service account) the appropriate bypass permissions [3][6]. 2. Token Limitations: Because the GITHUB_TOKEN is tied to the workflow run and automatically created, it cannot be granted bypass permissions in the same way a personal access token (PAT) or a custom GitHub App installation token can [1][3]. If an automated process requires bypassing rules, using a dedicated GitHub App installation token or a PAT (with necessary permissions and bypass rights) is the recommended alternative to the GITHUB_TOKEN [1][7]. 3. Workflow-Triggered Events: Workflows triggered by the GITHUB_TOKEN do not run on events that would otherwise trigger another workflow, preventing infinite loops [3]. This is a platform-level constraint independent of the contents: write permission [3]. In summary, contents: write is necessary for pushing to a repository, but it does not grant authorization to ignore branch protection or rulesets [5][3]. You must manage bypass access through the repository's ruleset or branch protection settings, typically using a more persistent identity like a GitHub App or PAT if the GITHUB_TOKEN is insufficient [6][7].
Citations:
🏁 Script executed:
Repository: Colorado-Mesh/mesh-client
Length of output: 10896
Scope the GitHub Actions bypass to a dedicated identity.
bypass_mode: "always"grants the GitHub Actions integration access to bypass every rule targetingmain. Rulesets cannot restrict this grant tothird-party-licenses.yaml. Other workflows also requestcontents: write, so a modified or compromised workflow could bypass pull-request, status-check, deletion, and non-fast-forward rules. Remove this bypass and make the license workflow open a pull request, or use a dedicated GitHub App installation token that no other workflow can access.🤖 Prompt for AI Agents