Skip to content

ci: block merge when PR is labeled 'do not merge'- #572 - #754

Open
SteinGabriel wants to merge 1 commit into
mainfrom
add-label-merge-rule
Open

ci: block merge when PR is labeled 'do not merge'- #572#754
SteinGabriel wants to merge 1 commit into
mainfrom
add-label-merge-rule

Conversation

@SteinGabriel

@SteinGabriel SteinGabriel commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Summary

Cross-repo CI gate. Adds a block-merge-label job that fails when a PR carries a "do not merge" label (case-insensitive), so it can be wired up as a required status check. Part of a 3-repo rollout (ping-javascript-sdk, forgerock-web-login-framework, sdk-sample-apps) — this PR covers forgerock-web-login-framework.

Note: this job must also be added as a required status check in this repo's GitHub branch protection settings — see Risks / Notes below. Adding the workflow job alone does not enforce merge blocking.

Changes

.github/workflows/ci.yml

  • pull_request trigger added (opened, synchronize, reopened, labeled, unlabeled) alongside existing push trigger.
  • New block-merge-label job: reads PR labels via toJSON(github.event.pull_request.labels.*.name), lowercases with tr, greps for "do not merge". Fails with ::error:: annotation if matched.
  • Implemented as standalone job (not a step in existing build/test-lint-storybook-build jobs) so it can be required independently without coupling to full pipeline result.

Tests

  • No new automated tests — pure CI config change.
  • Prettier-formatted, verified via pnpm exec prettier --check.

How to test

1. Confirm block on labeled PR

Apply "do not merge" (or any casing variant) label to an open PR against this branch. Confirm block-merge-label job fails, error annotation shows "Merge blocked: PR is labeled 'do not merge'."

2. Confirm pass on unlabeled PR

Remove label (unlabeled event fires). Confirm job re-runs and passes.

Risks / Notes

  • Label text hardcoded as do not merge, case-insensitive. Repos using a different label string need manual sync — no config surface.
  • Job needs no checkout/permissions — relies on default pull_request event payload.
  • Manual follow-up required: block-merge-label must be added as a required status check in the repo's GitHub branch protection settings (Settings → Branches → main → require status checks) for this gate to actually block merging. Adding the job alone does not enforce anything.

Summary by CodeRabbit

  • CI Improvements
    • Pull requests labeled “do not merge” are now automatically blocked from merging.
    • Label matching is case-insensitive.
    • Checks run when pull-request labels are added or removed.

@changeset-bot

changeset-bot Bot commented Aug 10, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 86f9d4b

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The CI workflow now runs when pull-request labels change. A new job fails CI when a pull request has a case-insensitive do not merge label.

Changes

Merge Label Enforcement

Layer / File(s) Summary
Add pull-request merge label check
.github/workflows/ci.yml
The workflow listens for labeled and unlabeled pull-request events. The block-merge-label job checks label names and fails when it finds do not merge, regardless of case.

Estimated code review effort: 2 (Simple) | ~10 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the CI change that blocks merges for pull requests labeled 'do not merge'.
Description check ✅ Passed The description explains the changes, tests, usage, risks, and required branch protection follow-up.
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.
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch add-label-merge-rule

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 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/ci.yml:
- Around line 18-20: Add job-level permissions: {} to the block-merge-label
workflow job, alongside runs-on and before steps, leaving the existing
label-reading logic unchanged.
- Line 4: Update the workflow’s pr condition to exclude labeled and unlabeled
actions while preserving execution for the intended pull request actions;
alternatively, isolate block-merge-label in a separate workflow so label-only
events cannot rerun builds, publishing, documentation deployment, or comment
updates.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

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

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 9a6ed1de-ccb6-4c06-87bd-fb54764e0004

📥 Commits

Reviewing files that changed from the base of the PR and between 9afa636 and 85f48fb.

📒 Files selected for processing (1)
  • .github/workflows/ci.yml

Comment thread .github/workflows/ci.yml
name: ForgeRock Pull Request CI
on:
pull_request:
types: [opened, synchronize, reopened, labeled, unlabeled]

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -eu
printf '%s\n' '--- workflow files ---'
git ls-files '.github/workflows/*'
printf '%s\n' '--- ci.yml outline ---'
wc -l .github/workflows/ci.yml
printf '%s\n' '--- relevant workflow content ---'
cat -n .github/workflows/ci.yml

Repository: ForgeRock/ping-javascript-sdk

Length of output: 9170


🏁 Script executed:

#!/bin/bash
set -eu
python3 - <<'PY'
from pathlib import Path
import re

path = Path(".github/workflows/ci.yml")
text = path.read_text()

types_match = re.search(r"(?m)^\s+types:\s*\[([^\]]+)\]", text)
pr_match = re.search(
    r"(?ms)^  pr:\n(?P<body>.*?)(?=^  \S[^ \n]*:|\Z)",
    text,
)
if not types_match or not pr_match:
    raise SystemExit("Could not locate the pull_request types or pr job")

event_types = [item.strip() for item in types_match.group(1).split(",")]
pr_body = pr_match.group("body")
pr_if = re.search(r"(?m)^\s+if:\s*(.+)$", pr_body)
if not pr_if:
    raise SystemExit("The pr job has no condition")

print("pull_request activity types:", event_types)
print("label-only activity types enabled:",
      {"labeled", "unlabeled"}.issubset(event_types))
print("pr condition:", pr_if.group(1).strip())
print("pr condition checks event.action:",
      "github.event.action" in pr_if.group(1))

side_effect_lines = []
for number, line in enumerate(pr_body.splitlines(), start=1):
    if re.search(r"(preview-pages|sticky-pull-request-comment|create-or-update-comment|pkg-pr-new|contents:\s*write)", line):
        side_effect_lines.append(line.strip())
print("pr side-effect or write-capability references:")
for line in side_effect_lines:
    print("  ", line)
PY

Repository: ForgeRock/ping-javascript-sdk

Length of output: 826


🌐 Web query:

GitHub Actions pull_request activity types workflow-level filtering and job-level if condition for labeled and unlabeled events

💡 Result:

To manage GitHub Actions workflows based on pull request label events, you must configure the workflow-level trigger to include the labeled and unlabeled activity types, and then use job-level if conditions to inspect the specific labels. Workflow-Level Filtering The pull_request event, by default, only triggers on opened, synchronize, and reopened activity types [1][2]. To react to changes in pull request labels, you must explicitly include the labeled and unlabeled types in the workflow definition using the types keyword [1][2]: on: pull_request: types: [opened, synchronize, labeled, unlabeled] There is no native capability to filter for specific labels at the workflow trigger level (e.g., triggering only when a label named 'ready' is added) [3]. You must include these activity types, which causes the workflow to trigger whenever any label is added or removed from a pull request [3]. Job-Level Condition Filtering Because the workflow triggers on all label changes, you must use the jobs.<job_id>.if condition to restrict execution to your desired logic [4][3]. You can inspect the github.event payload within the if expression to check for the presence or absence of specific labels [4][3]. Example: jobs: run-if-labeled: if: contains(github.event.pull_request.labels.*.name, 'my-target-label') runs-on: ubuntu-latest steps: - run: echo "The label is present." In this example, the job will run only if the pull request has the label 'my-target-label' at the time of the event [3]. When a label is removed, the unlabeled event triggers the workflow, the if condition evaluates to false, and the job is skipped [3]. Skipped jobs are reported as successful, which is important to consider if the job is part of a required status check [4][5].

Citations:


Guard pr against label-only events.

labeled and unlabeled trigger the entire workflow. The existing pr condition only checks the repository, so same-repository label changes rerun builds, publishing, documentation deployment, and comment updates. Add an github.event.action guard to pr, or move block-merge-label to a separate workflow.

🤖 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/ci.yml at line 4, Update the workflow’s pr condition to
exclude labeled and unlabeled actions while preserving execution for the
intended pull request actions; alternatively, isolate block-merge-label in a
separate workflow so label-only events cannot rerun builds, publishing,
documentation deployment, or comment updates.

Source: MCP tools

Comment thread .github/workflows/ci.yml
Comment on lines +18 to +20
block-merge-label:
runs-on: ubuntu-latest
steps:

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -eu
printf '%s\n' '--- .github/workflows/ci.yml ---'
cat -n .github/workflows/ci.yml
printf '%s\n' '--- workflow permission and trigger references ---'
rg -n -C 3 '(^|[[:space:]])(permissions|on:|types:|block-merge-label|GITHUB_TOKEN|github\.event)' .github/workflows/ci.yml
printf '%s\n' '--- repository workflow files ---'
git ls-files '.github/workflows/*'

Repository: ForgeRock/ping-javascript-sdk

Length of output: 12109


🌐 Web query:

GitHub Actions workflow syntax job-level permissions permissions: {} GITHUB_TOKEN official documentation

💡 Result:

In GitHub Actions, the permissions: {} syntax is used within a workflow file to explicitly disable all permissions for the GITHUB_TOKEN [1][2]. When you use the permissions key in your workflow—either at the top level or within a specific job—all permissions are set to none by default unless you explicitly grant them [1][2]. Consequently, defining permissions: {} effectively removes all access rights for the GITHUB_TOKEN within that scope [1][3]. Key points regarding this syntax include: - Scope: You can apply permissions: {} globally at the workflow level or restrict it to an individual job by placing it under jobs.<job_id>.permissions [1][2]. - Behavior: If you define the permissions key, any permissions not explicitly specified are set to none [1][2]. By providing an empty object ({}), you ensure that no permissions are granted [1]. - Security: This is a recommended security practice to follow the principle of least privilege, ensuring that the GITHUB_TOKEN does not have access to resources it does not need [4][5]. - Default behavior: Without an explicit permissions block, the GITHUB_TOKEN defaults to the permissions configured at the repository or organization level [6]. For detailed reference, you can consult the official GitHub Actions workflow syntax documentation [2].

Citations:


🏁 Script executed:

#!/bin/bash
set -eu
python3 - <<'PY'
from pathlib import Path

path = Path(".github/workflows/ci.yml")
lines = path.read_text().splitlines()

def block(start, indent):
    out = []
    for line in lines[start + 1:]:
        if line.strip() and len(line) - len(line.lstrip()) <= indent:
            break
        out.append(line)
    return out

jobs = {}
for i, line in enumerate(lines):
    if line.startswith("  ") and not line.startswith("    ") and line.rstrip().endswith(":"):
        name = line.strip()[:-1]
        if name in {"block-merge-label", "pr"}:
            jobs[name] = block(i, 2)

for name, body in jobs.items():
    keys = [line.strip().split(":", 1)[0] for line in body
            if line.startswith("    ") and not line.startswith("      ")
            and line.strip() and not line.lstrip().startswith("#")]
    print(f"{name}: top-level job keys={keys}")
    print(f"{name}: has permissions key={'permissions' in keys}")

root_env = []
in_env = False
for line in lines:
    if line == "env:":
        in_env = True
        continue
    if in_env:
        if line and len(line) - len(line.lstrip()) <= 0:
            break
        if line.startswith("  ") and not line.startswith("    "):
            root_env.append(line.strip().split(":", 1)[0])
print(f"workflow-level env keys={root_env}")
PY

Repository: ForgeRock/ping-javascript-sdk

Length of output: 484


Set permissions: {} for block-merge-label.

This job only reads pull request labels and does not use GITHUB_TOKEN. Without job-level permissions, it inherits repository or organization defaults. Add permissions: {} to disable all token permissions.

🧰 Tools
🪛 zizmor (1.29.0)

[warning] 18-28: overly broad permissions (excessive-permissions): default permissions used due to no permissions: block

(excessive-permissions)

🤖 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/ci.yml around lines 18 - 20, Add job-level permissions: {}
to the block-merge-label workflow job, alongside runs-on and before steps,
leaving the existing label-reading logic unchanged.

Sources: MCP tools, Linters/SAST tools

ci: make Do-not-merge label check case-insensitive

ci: standardize block-merge-label error message
@nx-cloud

nx-cloud Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

View your CI Pipeline Execution ↗ for commit 86f9d4b

Command Status Duration Result
nx run-many -t build --no-agents ✅ Succeeded <1s View ↗
nx affected -t build lint test typecheck e2e-ci ✅ Succeeded 6m 38s View ↗

💡 Verify your cache is correct by running tasks in a sandbox. Read docs ↗


☁️ Nx Cloud last updated this comment at 2026-08-10 22:39:21 UTC

@pkg-pr-new

pkg-pr-new Bot commented Aug 10, 2026

Copy link
Copy Markdown

Open in StackBlitz

@forgerock/davinci-client

pnpm add https://pkg.pr.new/@forgerock/davinci-client@754

@forgerock/device-client

pnpm add https://pkg.pr.new/@forgerock/device-client@754

@forgerock/journey-client

pnpm add https://pkg.pr.new/@forgerock/journey-client@754

@forgerock/oidc-client

pnpm add https://pkg.pr.new/@forgerock/oidc-client@754

@forgerock/protect

pnpm add https://pkg.pr.new/@forgerock/protect@754

@forgerock/sdk-types

pnpm add https://pkg.pr.new/@forgerock/sdk-types@754

@forgerock/sdk-utilities

pnpm add https://pkg.pr.new/@forgerock/sdk-utilities@754

@forgerock/iframe-manager

pnpm add https://pkg.pr.new/@forgerock/iframe-manager@754

@forgerock/sdk-logger

pnpm add https://pkg.pr.new/@forgerock/sdk-logger@754

@forgerock/sdk-oidc

pnpm add https://pkg.pr.new/@forgerock/sdk-oidc@754

@forgerock/sdk-request-middleware

pnpm add https://pkg.pr.new/@forgerock/sdk-request-middleware@754

@forgerock/storage

pnpm add https://pkg.pr.new/@forgerock/storage@754

commit: 86f9d4b

@codecov-commenter

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 23.94%. Comparing base (eafe277) to head (86f9d4b).
⚠️ Report is 58 commits behind head on main.

❌ Your project status has failed because the head coverage (23.94%) is below the target coverage (40.00%). You can increase the head coverage or adjust the target coverage.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #754      +/-   ##
==========================================
+ Coverage   18.07%   23.94%   +5.87%     
==========================================
  Files         155      162       +7     
  Lines       24398    25722    +1324     
  Branches     1203     1669     +466     
==========================================
+ Hits         4410     6160    +1750     
+ Misses      19988    19562     -426     

see 17 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@github-actions

Copy link
Copy Markdown
Contributor

Deployed d8bb22a to https://ForgeRock.github.io/ping-javascript-sdk/pr-754/d8bb22a8cfbb1b116935101cf59a6dad6fe0ad42 branch gh-pages in ForgeRock/ping-javascript-sdk

@github-actions

Copy link
Copy Markdown
Contributor

📦 Bundle Size Analysis

📦 Bundle Size Analysis

🆕 New Packages

🆕 @forgerock/journey-client - 92.6 KB (new)
🆕 @forgerock/journey-client - 0.0 KB (new)
🆕 @forgerock/device-client - 10.0 KB (new)
🆕 @forgerock/device-client - 0.0 KB (new)

➖ No Changes

@forgerock/davinci-client - 56.7 KB
@forgerock/sdk-types - 9.1 KB
@forgerock/sdk-logger - 1.6 KB
@forgerock/iframe-manager - 3.2 KB
@forgerock/sdk-oidc - 5.7 KB
@forgerock/storage - 1.5 KB
@forgerock/sdk-request-middleware - 4.6 KB
@forgerock/sdk-utilities - 18.6 KB
@forgerock/oidc-client - 35.4 KB
@forgerock/protect - 144.6 KB


14 packages analyzed • Baseline from latest main build

Legend

🆕 New package
🔺 Size increased
🔻 Size decreased
➖ No change

ℹ️ How bundle sizes are calculated
  • Current Size: Total gzipped size of all files in the package's dist directory
  • Baseline: Comparison against the latest build from the main branch
  • Files included: All build outputs except source maps and TypeScript build cache
  • Exclusions: .map, .tsbuildinfo, and .d.ts.map files

🔄 Updated automatically on each push to this PR

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants