UID2-7426: add check_jira_key composite action (commit-based Jira-key required check)#254
Open
jon8787 wants to merge 5 commits into
Open
UID2-7426: add check_jira_key composite action (commit-based Jira-key required check)#254jon8787 wants to merge 5 commits into
jon8787 wants to merge 5 commits into
Conversation
…Jira-key gate) IABTechLab is a GitHub team plan, where commit-metadata ruleset rules (commit_message_pattern) are Enterprise-gated and silently inert, so the native require-jira-key rule used on UnifiedID2/EUID (UID2-7312) does not enforce there. This reusable workflow reproduces the same rule as a required status check, the only team-plan-compatible mechanism. It reconstructs the squash commit GitHub will actually land (per each repo's squash_merge_commit_title/message) and requires a UID2-<n> key or a reasoned [no-jira - reason: <reason>] opt-out, mirroring the native ruleset and the commit_pr_and_merge marker (UID2-7400) so CI release PRs pass with no CI change. Commit-based, not PR-title, because in-scope repos use COMMIT_OR_PR_TITLE, where a single-commit PR lands the commit message rather than the PR title. Reconstruction logic validated against 12 cases (single/multi-commit, CI marker, android-sdk PR_TITLE/PR_BODY, blank opt-out, FOOUID2-1). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…live title/body, first-line subject, locale, conditional guidance; align SSOT regex - Read squash settings and FAIL CLOSED (never default) when null. A token without administration:read gets null and would silently mis-evaluate PR_TITLE/PR_BODY repos (e.g. uid2-android-sdk: false-block a key-in-title PR, false-pass a key-in-commit one). Add administration:read to permissions; callers must grant it. - Fetch PR title/body LIVE (not the frozen github.event payload) so a manual re-run after a title edit re-evaluates the current title/body. - Use the commit's FIRST LINE (not the whole message) as the squash subject — a key only in a commit body does not land on BLANK / PR_BODY body modes. - Pin LC_ALL=C.UTF-8 for grep -P (matches commit_pr_and_merge; PCRE errors on non-UTF-8 locale). - Branch the failure guidance on squash title mode / commit count so authors aren't told to amend a commit when the PR title is what lands (or vice-versa). - Document rollout prerequisites in the header: require-squash-merge must be active, and commit_pr_and_merge needs a wait-for-checks (or the release actor a bypass) before this is flipped to a required check (its immediate merge API call would otherwise 405). - Align the SSOT: add \b to the commit_pr_and_merge self-assertion regex so the two in-repo copies are byte-identical (previously it lacked \b). Reconstruction logic re-verified against 16 cases (incl. first-line/body-mode and android-sdk). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…orkflow permissions key); reword fail-closed message [no-jira - reason: review fix]
…ow token can't read squash_merge_commit_*); simplify reconstruction [no-jira - reason: review fix]
…e matcher Replaces the shared-check-jira-key reusable workflow with actions/check_jira_key (composite action), so the shipped logic lives in a script that is genuinely unit-tested rather than mirrored: - match.sh: pure matcher (inputs via env, no I/O) — the reconstruction + SSOT regex. - action.yaml: gathers inputs (gh api) + a runtime squash-config TRIPWIRE, then calls match.sh. - tests/match.test.sh: 11 cases against the real match.sh (auto-run by test-scripts.yaml). - tests/regex_identity.test.sh: asserts the SSOT regex is byte-identical to the commit_pr_and_merge self-assertion (reads the real files, so it can't drift). Also: - Runtime tripwire: attempt to read squash settings; fail loudly ONLY if they are readable AND differ from the assumed COMMIT_OR_PR_TITLE/COMMIT_MESSAGES (null = unreadable = trust the audit). Turns a silent UI settings-flip into an immediate red check at zero cost on the normal path. - Fix cosmetic success message (dropped the misleading github.ref_name "<n>/merge"). - .gitattributes: *.sh eol=lf so shebangs work on Linux runners. - Callers pin job name `check_jira_key` -> one status-check context for the terraform required check. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Adds
actions/check_jira_key— a composite action that fails a PR unless the squash commit that will land carries aUID2-<n>Jira key or a reasoned[no-jira - reason: <reason>]opt-out. This is the required-status-check enforcement path for IABTechLab (UID2-7426). Callers wire it as apull_requestjob namedcheck_jira_key.(Originally drafted as a reusable workflow; converted to a composite action during review so the shipped logic lives in a unit-tested script rather than un-guarded inline bash.)
Why an Action instead of the native ruleset
UnifiedID2 / EUID (Enterprise) enforce this natively via a
commit_message_patternruleset (UID2-7312). IABTechLab is a GitHub team plan, where commit-metadata ruleset rules are Enterprise-gated and never evaluated — proven live (and a rulesetrequired_status_checksrule does enforce on team plan, so this Action + a required check is viable).What it checks — and the squash-config assumption
match.shreconstructs the squash commit GitHub will land: subject = the single commit's first line (1-commit PR) or the PR title (multi-commit); body = all commit messages. It requires the key/opt-out there (checking the PR title alone is wrong — a single-commit PR lands the commit message, and the CI marker lands in the commit).It assumes
squash_merge_commit_title = COMMIT_OR_PR_TITLE+squash_merge_commit_message = COMMIT_MESSAGES(the config every gated repo uses) rather than reading it, because the workflowGITHUB_TOKENcannot readsquash_merge_commit_*(null without admin;administrationis not a grantable workflowpermissions:key — verified live). A runtime tripwire inaction.yamlreads the settings anyway and fails loudly only if they are readable and differ from the assumption (null = unreadable = trust the enforcement) — so a UI settings-flip becomes an immediate red check at zero cost on the normal path.Structure
actions/check_jira_key/action.yaml— gathers inputs (live PR title + commits) + the tripwire, calls the matcher.actions/check_jira_key/match.sh— pure matcher (inputs via env, no I/O), holds the SSOT regex.actions/check_jira_key/tests/match.test.sh— 11 cases against the realmatch.sh.actions/check_jira_key/tests/regex_identity.test.sh— asserts the SSOT regex is byte-identical to thecommit_pr_and_mergeself-assertion (reads the real files → can't drift)..gitattributes—*.sh eol=lf(shebangs on Linux runners).Both tests are auto-run by the existing
test-scripts.yaml(no new CI wiring).Review response (external review)
commit_pr_and_mergemerges via an immediate PUT with no wait-for-checks. Documented as a required-flip prerequisite (add wait-for-checks, or bypass the release actor). Earlier "no CI change" claim corrected.uid2-android-sdk(wasPR_TITLE/PR_BODY) is normalized to match, enforced via terraform.require-squash-mergemust be active first (documented prerequisite).\btocommit_pr_and_merge's assertion; a test now asserts the two copies stay byte-identical.LC_ALL=C.UTF-8forgrep -P.Rollout prerequisites (before flipping to a REQUIRED check)
COMMIT_OR_PR_TITLE+COMMIT_MESSAGES(normalizeuid2-android-sdk; enforce via terraform).require-squash-mergeisactive.commit_pr_and_mergewaits for checks, or the release actor is bypassed on the required-check rule.Validation
test-scripts.yamlon Linux:match.test.sh11/11 pass;regex_identity.test.shbyte-identical.uid2-attestation-api: no-key PR →check_jira_keyfails;UID2-1234-in-commit PR → passes. Required-check context:check_jira_key.