@plainconceptsplatform/workflows 1.4.0 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/catalog-installation.d.ts +2 -0
- package/dist/catalog-installation.js +44 -2
- package/dist/index.js +3 -0
- package/dist/route-processing.js +9 -2
- package/dist/stack-defaults.d.ts +1 -0
- package/dist/stack-defaults.js +13 -1
- package/dist/workflow-catalog.js +1 -1
- package/loops/actions/apply-agent-output/action.yml +5 -0
- package/loops/actions/classify-route/classify-route.sh +34 -13
- package/loops/actions/identify-gate-subject/action.yml +50 -7
- package/loops/actions/merge-train/action.yml +66 -0
- package/loops/actions/merge-train/merge-train.sh +424 -0
- package/loops/actions/push-agent-branch/action.yml +60 -45
- package/loops/actions/validate-merge-gate-output/action.yml +5 -0
- package/loops/actions/validate-merge-gate-output/validate-merge-gate-output.sh +8 -2
- package/loops/actions/verify-route-matrix/verify-route-matrix.sh +131 -80
- package/loops/docs/diagrams.md +55 -13
- package/loops/templates/ci/app-ci-dotnet-next.yml +13 -14
- package/loops/templates/ci/app-ci-node-monorepo.yml +13 -14
- package/loops/workflows/agent-implement.md +6 -1
- package/loops/workflows/agent-merge-gate.md +102 -56
- package/loops/workflows/work-router.yml +246 -464
- package/package.json +8 -9
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
# Managed by @plainconceptsplatform/workflows. Source: loops/workflows/agent-merge-gate.md. Update with `workflows update --force`; consumer edits may be overwritten.
|
|
3
3
|
env:
|
|
4
4
|
VERIFY_COMMANDS: ""
|
|
5
|
-
REPO_RULES: "Review the selected
|
|
5
|
+
REPO_RULES: "Review the selected pull request for defects and report what you verified. Do not decide the outcome: the workflow computes it from your report and from facts it measured before you ran."
|
|
6
6
|
# Where to look first, not what to escalate on. This list used to be the check that decided
|
|
7
7
|
# whether a machine merged without a human, and it decided by category: the prompt told the
|
|
8
8
|
# agent that a match "is not a defect, it is a reason this pull request needs a person". In a
|
|
@@ -13,34 +13,35 @@ env:
|
|
|
13
13
|
# One line: gh-aw joins a multi-line env value onto a single line when it compiles the lock.
|
|
14
14
|
RISK_INDICATORS: "Any diff touching authentication, authorization or session handling. Any change to a calculation or pricing engine, or to code handling money. Any database migration, or a change to an entity or schema. Any change to an audit or event log, or anything that could break its continuity. Any change to a public API contract or a shared library other repositories consume."
|
|
15
15
|
# Paths a bot may change but never merge on its own: an extended regular expression matched
|
|
16
|
-
# against every changed path in the pull request.
|
|
17
|
-
#
|
|
18
|
-
#
|
|
19
|
-
#
|
|
20
|
-
#
|
|
21
|
-
|
|
16
|
+
# against every changed path in the pull request. A match holds the merge for a human; it does
|
|
17
|
+
# not stop the agent repairing failed CI on the same files.
|
|
18
|
+
#
|
|
19
|
+
# Only the automation itself. This list used to hold every dependency manifest, lockfile and
|
|
20
|
+
# dotted directory as well, and with a size threshold and an owner list as wide it parked most
|
|
21
|
+
# of a night's pull requests for a person who then merged them by hand, unread, on Monday:
|
|
22
|
+
# in Pliny-Bot 32 of 40 bot pull requests in two days. What stops a merge now is what is
|
|
23
|
+
# genuinely dangerous to merge unseen: the workflows, the secrets, and a change too big to
|
|
24
|
+
# review in one pass.
|
|
25
|
+
PROTECTED_PATHS: '^\.github/'
|
|
22
26
|
# Paths whose change needs the person who owns them. A match forces OWNER REVIEW REQUIRED and
|
|
23
27
|
# sets blast radius high on its own, whatever the diff's size. CODEOWNERS names who is asked
|
|
24
|
-
# when the repository has that file; it is never a prerequisite
|
|
25
|
-
# one must still be able to protect its auth and its infrastructure.
|
|
28
|
+
# when the repository has that file; it is never a prerequisite.
|
|
26
29
|
#
|
|
27
|
-
#
|
|
28
|
-
#
|
|
29
|
-
#
|
|
30
|
-
|
|
31
|
-
# this one catches exactly three and they are the three that deserved an owner (a database
|
|
32
|
-
# migration, a change to the platform role definitions, and a downstream token service).
|
|
33
|
-
OWNER_PATHS: '(^|/)([Aa]uth|[Aa]uthn|[Aa]uthz|[Aa]uthentication|[Aa]uthorization|[Ii]dentity|[Ss]ecurity|[Ss]ecrets?|[Mm]igrations|[Ii]nfra|terraform|helm|k8s|deploy)(/|[A-Z][A-Za-z]*\.[a-z]+$)'
|
|
30
|
+
# Secrets: a `secrets` directory or file, an environment file, a key or a certificate. Code
|
|
31
|
+
# that handles secrets (a SecretMasker.cs) is not a secret; the review pass reads it like any
|
|
32
|
+
# other change.
|
|
33
|
+
OWNER_PATHS: '(^|/)([Ss]ecrets?(/|\.[A-Za-z0-9]+$)|\.env(\.[A-Za-z0-9_-]+)?$|[^/]+\.(pem|pfx|p12|key)$)'
|
|
34
34
|
# Paths worth a second look that do not, alone, need a person. A match raises the floor to
|
|
35
35
|
# medium, and medium with acceptable recoverability still auto-merges. This is the line that
|
|
36
|
-
# separates "look here" from "stop here",
|
|
37
|
-
|
|
38
|
-
#
|
|
39
|
-
|
|
40
|
-
#
|
|
41
|
-
#
|
|
42
|
-
|
|
43
|
-
|
|
36
|
+
# separates "look here" from "stop here". Auth, identity, security, migrations and
|
|
37
|
+
# infrastructure used to stop a merge from here; they are the review pass's to look at now, and
|
|
38
|
+
# a migration that rewrites data still parks through a `low` recoverability the agent evidences.
|
|
39
|
+
SENSITIVE_PATHS: '(^|/)([Dd]omain|entities|[Cc]ontracts)/|(^|/)([Aa]uth|[Aa]uthn|[Aa]uthz|[Aa]uthentication|[Aa]uthorization|[Ii]dentity|[Ss]ecurity|[Mm]igrations|[Ii]nfra|terraform|helm|k8s|deploy)(/|[A-Z][A-Za-z]*\.[a-z]+$)'
|
|
40
|
+
# Diff shape. Lines decide high: a change over a thousand counted lines (tests, docs,
|
|
41
|
+
# translations and generated code excluded) is too big to merge unseen. A file count alone
|
|
42
|
+
# never does, so the high file threshold is set out of reach; spread still raises medium.
|
|
43
|
+
BLAST_HIGH_FILES: "100000"
|
|
44
|
+
BLAST_HIGH_LINES: "1000"
|
|
44
45
|
BLAST_MEDIUM_FILES: "5"
|
|
45
46
|
BLAST_MEDIUM_LINES: "200"
|
|
46
47
|
# Paths that change no runtime behaviour: tests, docs, specs, translations and generated
|
|
@@ -80,14 +81,18 @@ env:
|
|
|
80
81
|
PARK_AT_UNUSABLE_OUTPUT: "2"
|
|
81
82
|
ISSUE_CONTEXT_PATH: /tmp/gh-aw/agent/issue-context.json
|
|
82
83
|
GH_AW_ALLOWED_BOTS: "platform-devbox[bot],github-actions[bot]"
|
|
84
|
+
# The bots whose pull requests the gate takes, in every spelling GitHub uses for one account.
|
|
85
|
+
# Any other author needs write access to the repository, as they would to push the branch.
|
|
86
|
+
TRUSTED_BOTS: "github-actions[bot] app/github-actions platform-devbox[bot]"
|
|
83
87
|
GIT_AUTHOR_NAME: "github-actions[bot]"
|
|
84
88
|
GIT_AUTHOR_EMAIL: "github-actions[bot]@users.noreply.github.com"
|
|
85
89
|
GIT_COMMITTER_NAME: "github-actions[bot]"
|
|
86
90
|
GIT_COMMITTER_EMAIL: "github-actions[bot]@users.noreply.github.com"
|
|
87
91
|
description: |
|
|
88
|
-
Decides what happens to a
|
|
89
|
-
risk assessment is clean, hand to a human when it is
|
|
90
|
-
|
|
92
|
+
Decides what happens to a pull request once CI has reported, whether the bot or a person with
|
|
93
|
+
write access opened it: merge when the risk assessment is clean, hand to a human when it is
|
|
94
|
+
genuinely dangerous, fix CI or a conflict when there is one. Called by the Work Router, one
|
|
95
|
+
pull request at a time by its merge train; does not trigger on public events.
|
|
91
96
|
|
|
92
97
|
In a stack, a child pull request (its base is the feature branch) merges into that feature
|
|
93
98
|
branch and its child issue closes with it; the root pull request is held for a person. The
|
|
@@ -154,6 +159,10 @@ jobs:
|
|
|
154
159
|
found: ${{ steps.subject.outputs.found }}
|
|
155
160
|
pr: ${{ steps.subject.outputs.pr }}
|
|
156
161
|
issue: ${{ steps.subject.outputs.issue }}
|
|
162
|
+
# Where verdicts, attempts and labels go: the issue, or the pull request when it closes none.
|
|
163
|
+
record: ${{ steps.subject.outputs.record }}
|
|
164
|
+
head_ref: ${{ steps.subject.outputs.head-ref }}
|
|
165
|
+
closes: ${{ steps.subject.outputs.closes }}
|
|
157
166
|
conclusion: ${{ steps.subject.outputs.conclusion }}
|
|
158
167
|
run-id: ${{ steps.subject.outputs.run-id }}
|
|
159
168
|
review_blocked: ${{ steps.review.outputs.review_blocked }}
|
|
@@ -174,6 +183,7 @@ jobs:
|
|
|
174
183
|
ci-run-id: ${{ inputs.ci-run-id }}
|
|
175
184
|
linked-issue: ${{ inputs.linked-issue }}
|
|
176
185
|
require-label: ${{ env.IMPLEMENT_LABEL }}
|
|
186
|
+
trusted-bots: ${{ env.TRUSTED_BOTS }}
|
|
177
187
|
- name: Block a pull request with requested changes
|
|
178
188
|
id: review
|
|
179
189
|
env:
|
|
@@ -354,14 +364,14 @@ jobs:
|
|
|
354
364
|
uses: ./.github/actions/remove-issue-labels
|
|
355
365
|
with:
|
|
356
366
|
token: ${{ steps.app-token.outputs.token }}
|
|
357
|
-
issue-number: ${{ needs.subject.outputs.
|
|
367
|
+
issue-number: ${{ needs.subject.outputs.record }}
|
|
358
368
|
labels: ${{ env.WORKING_LABEL }}
|
|
359
369
|
- name: Flag owner review
|
|
360
370
|
if: needs.protected_changes.outputs.holds_review == 'true'
|
|
361
371
|
uses: ./.github/actions/add-issue-labels
|
|
362
372
|
with:
|
|
363
373
|
token: ${{ steps.app-token.outputs.token }}
|
|
364
|
-
issue-number: ${{ needs.subject.outputs.
|
|
374
|
+
issue-number: ${{ needs.subject.outputs.record }}
|
|
365
375
|
labels: |-
|
|
366
376
|
${{ env.REVIEW_LABEL }}
|
|
367
377
|
${{ env.OWNER_REVIEW_LABEL }}
|
|
@@ -370,7 +380,7 @@ jobs:
|
|
|
370
380
|
uses: ./.github/actions/create-issue-comment
|
|
371
381
|
with:
|
|
372
382
|
token: ${{ steps.app-token.outputs.token }}
|
|
373
|
-
issue-number: ${{ needs.subject.outputs.
|
|
383
|
+
issue-number: ${{ needs.subject.outputs.record }}
|
|
374
384
|
body: |
|
|
375
385
|
${{ env.GATE_MARKER }}
|
|
376
386
|
PR #${{ needs.subject.outputs.pr }} changes protected files and cannot be auto-merged.
|
|
@@ -439,7 +449,7 @@ jobs:
|
|
|
439
449
|
uses: ./.github/actions/create-issue-comment
|
|
440
450
|
with:
|
|
441
451
|
token: ${{ steps.app-token.outputs.token }}
|
|
442
|
-
issue-number: ${{ needs.subject.outputs.
|
|
452
|
+
issue-number: ${{ needs.subject.outputs.record }}
|
|
443
453
|
body: |
|
|
444
454
|
Problems found in PR #${{ needs.subject.outputs.pr }}. ${{ steps.conflicts.outputs.has_conflicts == 'true' && 'Merge conflicts detected.' || 'CI failed.' }}
|
|
445
455
|
Bot is working on fixing it.
|
|
@@ -455,6 +465,7 @@ jobs:
|
|
|
455
465
|
outputs:
|
|
456
466
|
valid: ${{ steps.validate.outputs.valid }}
|
|
457
467
|
outcome: ${{ steps.validate.outputs.outcome }}
|
|
468
|
+
pushed: ${{ steps.validate.outputs.pushed }}
|
|
458
469
|
steps:
|
|
459
470
|
- name: Checkout workflow actions
|
|
460
471
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
@@ -472,7 +483,7 @@ jobs:
|
|
|
472
483
|
uses: ./.github/actions/validate-merge-gate-output
|
|
473
484
|
with:
|
|
474
485
|
output-file: ${{ steps.output.outputs.output-file }}
|
|
475
|
-
issue-number: ${{ needs.subject.outputs.
|
|
486
|
+
issue-number: ${{ needs.subject.outputs.record }}
|
|
476
487
|
ci-conclusion: ${{ needs.subject.outputs.conclusion }}
|
|
477
488
|
blast-level: ${{ needs.protected_changes.outputs.level }}
|
|
478
489
|
protected-hit: ${{ needs.protected_changes.outputs.requires_review }}
|
|
@@ -510,18 +521,23 @@ jobs:
|
|
|
510
521
|
token: ${{ steps.app-token.outputs.token }}
|
|
511
522
|
fetch-depth: 0
|
|
512
523
|
- name: Verify pull request closes the source issue
|
|
524
|
+
if: needs.subject.outputs.issue != ''
|
|
513
525
|
continue-on-error: true
|
|
514
526
|
uses: ./.github/actions/link-pr-to-issue
|
|
515
527
|
with:
|
|
516
528
|
token: ${{ steps.app-token.outputs.token }}
|
|
517
529
|
pr-number: ${{ needs.subject.outputs.pr }}
|
|
518
530
|
issue-number: ${{ needs.subject.outputs.issue }}
|
|
531
|
+
# The push goes to this pull request's branch or nowhere. A `[bot] ` title prefix used to be
|
|
532
|
+
# the guard, which a person's pull request does not carry; the branch the subject job read
|
|
533
|
+
# is the exact one, whoever opened it.
|
|
519
534
|
- name: Apply agent output
|
|
520
535
|
uses: ./.github/actions/apply-agent-output
|
|
521
536
|
with:
|
|
522
537
|
artifact-name: ${{ needs.activation.outputs.artifact_prefix }}agent
|
|
523
538
|
token: ${{ steps.app-token.outputs.token }}
|
|
524
539
|
push-to-branch: 'true'
|
|
540
|
+
expected-branch: ${{ needs.subject.outputs.head_ref }}
|
|
525
541
|
apply-labels: 'false'
|
|
526
542
|
# GITHUB_TOKEN on purpose: an App-token comment on a pull request is an issue_comment
|
|
527
543
|
# event, and GITHUB_TOKEN raises none. The full assessment lives on the issue, where the
|
|
@@ -557,7 +573,7 @@ jobs:
|
|
|
557
573
|
${{ needs.protected_changes.outputs.signals }}
|
|
558
574
|
```
|
|
559
575
|
|
|
560
|
-
Findings and verification on the linked issue:
|
|
576
|
+
${{ needs.subject.outputs.issue != '' && format('Findings and verification on the linked issue: #{0}.', needs.subject.outputs.issue) || 'Findings and verification are in the review comment above.' }} [View this workflow run](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})
|
|
561
577
|
${{ env.EVIDENCE_BEFORE_REVIEW == 'true' && contains(fromJson('["human-review","owner-review"]'), needs.validate_output.outputs.outcome) && 'Screenshots of this head follow in their own comment if it carries a verification plan. Approving the pull request merges it.' || '' }}
|
|
562
578
|
- name: Merge approved pull request
|
|
563
579
|
if: needs.validate_output.outputs.outcome == 'auto-merge' && needs.subject.outputs.stack_root != 'true'
|
|
@@ -578,7 +594,7 @@ jobs:
|
|
|
578
594
|
uses: ./.github/actions/create-issue-comment
|
|
579
595
|
with:
|
|
580
596
|
token: ${{ steps.app-token.outputs.token }}
|
|
581
|
-
issue-number: ${{ needs.subject.outputs.
|
|
597
|
+
issue-number: ${{ needs.subject.outputs.record }}
|
|
582
598
|
body: |
|
|
583
599
|
**Stack root held.** This pull request is the root of a stack: its children merge
|
|
584
600
|
into the feature branch, and it merges into ${{ github.event.repository.default_branch }} only when a person
|
|
@@ -588,7 +604,7 @@ jobs:
|
|
|
588
604
|
uses: ./.github/actions/remove-issue-labels
|
|
589
605
|
with:
|
|
590
606
|
token: ${{ steps.app-token.outputs.token }}
|
|
591
|
-
issue-number: ${{ needs.subject.outputs.
|
|
607
|
+
issue-number: ${{ needs.subject.outputs.record }}
|
|
592
608
|
labels: ${{ env.WORKING_LABEL }}
|
|
593
609
|
# `review` goes on for all three parked dispositions, so every board query and every
|
|
594
610
|
# authorize-bot-work handoff that already reads it keeps working. The second label is what
|
|
@@ -598,7 +614,7 @@ jobs:
|
|
|
598
614
|
uses: ./.github/actions/add-issue-labels
|
|
599
615
|
with:
|
|
600
616
|
token: ${{ steps.app-token.outputs.token }}
|
|
601
|
-
issue-number: ${{ needs.subject.outputs.
|
|
617
|
+
issue-number: ${{ needs.subject.outputs.record }}
|
|
602
618
|
labels: |-
|
|
603
619
|
${{ env.REVIEW_LABEL }}
|
|
604
620
|
${{ needs.validate_output.outputs.outcome == 'owner-review' && env.OWNER_REVIEW_LABEL || '' }}
|
|
@@ -630,7 +646,7 @@ jobs:
|
|
|
630
646
|
uses: ./.github/actions/remove-issue-labels
|
|
631
647
|
with:
|
|
632
648
|
token: ${{ steps.app-token.outputs.token }}
|
|
633
|
-
issue-number: ${{ needs.subject.outputs.
|
|
649
|
+
issue-number: ${{ needs.subject.outputs.record }}
|
|
634
650
|
labels: ${{ env.WORKING_LABEL }}
|
|
635
651
|
# GitHub's closing keywords never fire when a PR merges into a branch other than the
|
|
636
652
|
# default, so a child PR landing on the feature branch leaves its issue open — and
|
|
@@ -640,7 +656,7 @@ jobs:
|
|
|
640
656
|
# and `gh issue close` on an already-closed issue is a harmless no-op, making the
|
|
641
657
|
# step safe to re-run.
|
|
642
658
|
- name: Close the child issue when the pull request landed on a feature branch
|
|
643
|
-
if: needs.validate_output.outputs.outcome == 'auto-merge' && needs.subject.outputs.pr_base != '' && needs.subject.outputs.pr_base != github.event.repository.default_branch
|
|
659
|
+
if: needs.validate_output.outputs.outcome == 'auto-merge' && needs.subject.outputs.issue != '' && needs.subject.outputs.pr_base != '' && needs.subject.outputs.pr_base != github.event.repository.default_branch
|
|
644
660
|
env:
|
|
645
661
|
GH_TOKEN: ${{ steps.app-token.outputs.token }}
|
|
646
662
|
REPO: ${{ github.repository }}
|
|
@@ -667,7 +683,7 @@ jobs:
|
|
|
667
683
|
uses: ./.github/actions/remove-issue-labels
|
|
668
684
|
with:
|
|
669
685
|
token: ${{ steps.app-token.outputs.token }}
|
|
670
|
-
issue-number: ${{ needs.subject.outputs.
|
|
686
|
+
issue-number: ${{ needs.subject.outputs.record }}
|
|
671
687
|
labels: |
|
|
672
688
|
${{ env.IMPLEMENT_LABEL }}
|
|
673
689
|
${{ env.WORKING_LABEL }}
|
|
@@ -744,18 +760,18 @@ jobs:
|
|
|
744
760
|
uses: ./.github/actions/create-issue-comment
|
|
745
761
|
with:
|
|
746
762
|
token: ${{ steps.app-token.outputs.token }}
|
|
747
|
-
issue-number: ${{ needs.subject.outputs.
|
|
763
|
+
issue-number: ${{ needs.subject.outputs.record }}
|
|
748
764
|
body: |
|
|
749
765
|
${{ env.ATTEMPT_MARKER }}
|
|
750
766
|
Attempt ${{ inputs.attempts_so_far || '0' }} of ${{ env.MAX_ATTEMPTS }} on PR #${{ needs.subject.outputs.pr }} ended without an outcome.
|
|
751
|
-
This failure parks at ${{ steps.budget.outputs.threshold }}. The
|
|
767
|
+
This failure parks at ${{ steps.budget.outputs.threshold }}. The merge train will retry.
|
|
752
768
|
[View this workflow run](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})
|
|
753
769
|
- name: Report the exhausted attempt budget
|
|
754
770
|
if: steps.budget.outputs.park == 'true' && steps.budget.outputs.kind == 'machine'
|
|
755
771
|
uses: ./.github/actions/create-issue-comment
|
|
756
772
|
with:
|
|
757
773
|
token: ${{ steps.app-token.outputs.token }}
|
|
758
|
-
issue-number: ${{ needs.subject.outputs.
|
|
774
|
+
issue-number: ${{ needs.subject.outputs.record }}
|
|
759
775
|
body: |
|
|
760
776
|
${{ env.ATTEMPT_MARKER }}
|
|
761
777
|
Attempt ${{ inputs.attempts_so_far || '0' }} of ${{ steps.budget.outputs.threshold }} on PR #${{ needs.subject.outputs.pr }} ended without an outcome.
|
|
@@ -773,7 +789,7 @@ jobs:
|
|
|
773
789
|
uses: ./.github/actions/create-issue-comment
|
|
774
790
|
with:
|
|
775
791
|
token: ${{ steps.app-token.outputs.token }}
|
|
776
|
-
issue-number: ${{ needs.subject.outputs.
|
|
792
|
+
issue-number: ${{ needs.subject.outputs.record }}
|
|
777
793
|
body: |
|
|
778
794
|
${{ env.GATE_MARKER }}
|
|
779
795
|
The agent finished on PR #${{ needs.subject.outputs.pr }} but its report could not be
|
|
@@ -783,6 +799,26 @@ jobs:
|
|
|
783
799
|
|
|
784
800
|
**Verdict:** human-review
|
|
785
801
|
[View this workflow run](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})
|
|
802
|
+
# The issue is where the belt reads verdicts, but the pull request is where people look. A
|
|
803
|
+
# parked pull request with nothing on it reads as abandoned, and a repair the agent pushed
|
|
804
|
+
# that the gate refused to apply sits in the run artifact where nobody finds it.
|
|
805
|
+
- name: Tell the pull request it needs a person
|
|
806
|
+
if: steps.budget.outputs.park == 'true'
|
|
807
|
+
uses: ./.github/actions/create-issue-comment
|
|
808
|
+
with:
|
|
809
|
+
token: ${{ steps.app-token.outputs.token }}
|
|
810
|
+
issue-number: ${{ needs.subject.outputs.pr }}
|
|
811
|
+
body: |
|
|
812
|
+
The merge gate stopped on this pull request and handed it to a person${{ needs.subject.outputs.issue != '' && format(' (#{0})', needs.subject.outputs.issue) || '' }}.
|
|
813
|
+
${{ needs.validate_output.outputs.pushed == 'true' && 'The agent pushed a repair that was not applied because its report could not be read. The patch and bundle are in the `agent` artifact of the run below.' || '' }}
|
|
814
|
+
[View this workflow run](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})
|
|
815
|
+
- name: Label the pull request for review
|
|
816
|
+
if: steps.budget.outputs.park == 'true'
|
|
817
|
+
uses: ./.github/actions/add-issue-labels
|
|
818
|
+
with:
|
|
819
|
+
token: ${{ steps.app-token.outputs.token }}
|
|
820
|
+
issue-number: ${{ needs.subject.outputs.pr }}
|
|
821
|
+
labels: ${{ env.REVIEW_LABEL }}
|
|
786
822
|
# `stalled` means a park the machine caused, and the janitor retries those. An unusable
|
|
787
823
|
# report is a park the machine caused and retrying reproduces it, so it gets `review`
|
|
788
824
|
# alone: the janitor's own rule is retry a failure, report a decision.
|
|
@@ -791,7 +827,7 @@ jobs:
|
|
|
791
827
|
uses: ./.github/actions/add-issue-labels
|
|
792
828
|
with:
|
|
793
829
|
token: ${{ steps.app-token.outputs.token }}
|
|
794
|
-
issue-number: ${{ needs.subject.outputs.
|
|
830
|
+
issue-number: ${{ needs.subject.outputs.record }}
|
|
795
831
|
labels: |-
|
|
796
832
|
${{ env.REVIEW_LABEL }}
|
|
797
833
|
${{ steps.budget.outputs.kind == 'machine' && env.STALLED_LABEL || '' }}
|
|
@@ -801,7 +837,7 @@ jobs:
|
|
|
801
837
|
uses: ./.github/actions/remove-issue-labels
|
|
802
838
|
with:
|
|
803
839
|
token: ${{ steps.app-token.outputs.token }}
|
|
804
|
-
issue-number: ${{ needs.subject.outputs.
|
|
840
|
+
issue-number: ${{ needs.subject.outputs.record }}
|
|
805
841
|
labels: ${{ env.WORKING_LABEL }}
|
|
806
842
|
|
|
807
843
|
agent:
|
|
@@ -871,7 +907,7 @@ steps:
|
|
|
871
907
|
uses: ./.github/actions/load-issue-context
|
|
872
908
|
with:
|
|
873
909
|
token: ${{ github.token }}
|
|
874
|
-
issue-number: ${{ needs.subject.outputs.
|
|
910
|
+
issue-number: ${{ needs.subject.outputs.record }}
|
|
875
911
|
output-path: ${{ env.ISSUE_CONTEXT_PATH }}
|
|
876
912
|
- name: Fetch the diff and any failing job logs
|
|
877
913
|
env:
|
|
@@ -913,9 +949,10 @@ safe-outputs:
|
|
|
913
949
|
# target "*" because these workers are dispatched, not triggered by the pull request:
|
|
914
950
|
# the default "triggering" target has no pull request in context and rejects the push
|
|
915
951
|
# with "requires pull request context", so the agent's fix is computed and discarded.
|
|
952
|
+
# No title prefix: the gate repairs pull requests people opened as well, and conclude pushes
|
|
953
|
+
# only to the branch of the pull request the subject job validated.
|
|
916
954
|
push-to-pull-request-branch:
|
|
917
955
|
target: "*"
|
|
918
|
-
required-title-prefix: "[bot] "
|
|
919
956
|
max-patch-size: 10240
|
|
920
957
|
# A failed bot PR may already contain protected files. Permit a verified repair push,
|
|
921
958
|
# but protected_changes still prevents the later green-CI cycle from auto-merging it.
|
|
@@ -934,13 +971,13 @@ safe-outputs:
|
|
|
934
971
|
timeout-minutes: 120
|
|
935
972
|
---
|
|
936
973
|
|
|
937
|
-
1. You are gating pull request **#${{ needs.subject.outputs.pr }}**, which closes
|
|
938
|
-
|
|
939
|
-
**${{ needs.subject.outputs.conclusion }}**.
|
|
974
|
+
1. You are gating pull request **#${{ needs.subject.outputs.pr }}**, which ${{ needs.subject.outputs.closes }}.
|
|
975
|
+
CI concluded **${{ needs.subject.outputs.conclusion }}**.
|
|
940
976
|
|
|
941
|
-
It has already been confirmed that this is an open pull request
|
|
942
|
-
|
|
943
|
-
|
|
977
|
+
It has already been confirmed that this is an open pull request from this repository, opened
|
|
978
|
+
by the bot or by someone with write access. Do not re-check any of that, and do not poll for
|
|
979
|
+
checks: the conclusion above is the answer. Who opened it changes nothing below: a person's
|
|
980
|
+
pull request is repaired, reviewed and merged by the same rules as the bot's.
|
|
944
981
|
|
|
945
982
|
You are on the pull request branch. Never rebase, reset, amend or otherwise rewrite
|
|
946
983
|
history: the workflow applies your commits as a bundle with a fast-forward-only push and
|
|
@@ -948,9 +985,11 @@ timeout-minutes: 120
|
|
|
948
985
|
`push_to_pull_request_branch` tool's own description recommends rebasing; in this
|
|
949
986
|
repository that advice is wrong. Merge, commit, and let the workflow push.
|
|
950
987
|
|
|
951
|
-
2. Read `${{ env.ISSUE_CONTEXT_PATH }}`. It contains the issue body and its discussion
|
|
988
|
+
2. Read `${{ env.ISSUE_CONTEXT_PATH }}`. It contains the issue body and its discussion, or, for
|
|
989
|
+
a pull request that closes no issue, the pull request's own description and discussion. The
|
|
952
990
|
acceptance criteria there define what this implementation had to satisfy, and step 5c asks
|
|
953
|
-
you to check the diff against them.
|
|
991
|
+
you to check the diff against them. A description with no stated criteria is checked against
|
|
992
|
+
what it says the change does.
|
|
954
993
|
|
|
955
994
|
3. Branch on the conclusion.
|
|
956
995
|
|
|
@@ -979,6 +1018,13 @@ timeout-minutes: 120
|
|
|
979
1018
|
until it exits 0, then verify, push and report `remediated` as in step 6. An `assessed`
|
|
980
1019
|
verdict while it fails blocks the pull request.
|
|
981
1020
|
|
|
1021
|
+
When CI failed as well, repair CI first and `check-diff` second, and verify again after the
|
|
1022
|
+
`check-diff` repair. The two pull in opposite directions: a complexity or coverage gate wants
|
|
1023
|
+
more code and tests, `check-diff` wants fewer lines. Trimming to fit `check-diff` is how a
|
|
1024
|
+
pull request that once passed broke the formatter, Semgrep and the complexity gate on its
|
|
1025
|
+
last commit (Pliny-Bot #633). Never delete a test that covers a branch the change added; if
|
|
1026
|
+
both cannot hold, keep CI green and say so in `reason`.
|
|
1027
|
+
|
|
982
1028
|
- **success** → step 4, then step 5 (review the change).
|
|
983
1029
|
- **failure** → step 4, then step 6 (CI remediation).
|
|
984
1030
|
- **action_required, cancelled, timed_out, or anything else** → CI did not produce a usable
|
|
@@ -1197,7 +1243,7 @@ timeout-minutes: 120
|
|
|
1197
1243
|
your report and from the facts it measured, and a word it does not recognise parks the pull
|
|
1198
1244
|
request. Never merge with administrator privileges and never bypass a required check.
|
|
1199
1245
|
|
|
1200
|
-
8. Emit exactly one `add_comment` targeting
|
|
1246
|
+
8. Emit exactly one `add_comment` targeting item `${{ needs.subject.outputs.record }}`,
|
|
1201
1247
|
containing, in this order:
|
|
1202
1248
|
|
|
1203
1249
|
1. `${{ env.GATE_MARKER }}`
|