@plainconceptsplatform/workflows 1.13.0 → 1.14.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/loops/actions/add-issue-labels/action.yml +50 -50
- package/loops/actions/agent-output.cjs +17 -17
- package/loops/actions/apply-agent-bundle/action.yml +24 -24
- package/loops/actions/apply-agent-comments/action.yml +42 -42
- package/loops/actions/apply-agent-labels/action.yml +55 -55
- package/loops/actions/cleanup-artifacts/action.yml +91 -91
- package/loops/actions/close-agent-issues/action.yml +43 -43
- package/loops/actions/create-issue-comment/action.yml +29 -29
- package/loops/actions/download-agent-output/action.yml +53 -53
- package/loops/actions/link-pr-to-issue/action.yml +40 -40
- package/loops/actions/list-open-issues/action.yml +33 -33
- package/loops/actions/load-issue-context/action.yml +45 -45
- package/loops/actions/merge-agent-pr/action.yml +49 -49
- package/loops/actions/merge-dependabot/action.yml +10 -2
- package/loops/actions/merge-dependabot/merge-dependabot.mjs +47 -17
- package/loops/actions/remove-issue-labels/action.yml +37 -37
- package/loops/actions/update-agent-issues/action.yml +58 -58
- package/loops/actions/validate-review-output/action.yml +35 -35
- package/loops/actions/validate-triage-output/action.yml +36 -36
- package/loops/actions/verify-composite-actions/action.yml +9 -9
- package/loops/actions/verify-refine-output/action.yml +9 -9
- package/loops/actions/verify-route-matrix/action.yml +9 -9
- package/loops/actions/verify-route-matrix/verify-route-matrix.sh +7 -2
- package/loops/templates/agentics/agentics-maintenance.yml +121 -121
- package/loops/templates/dependabot-merge/.github/workflows/dependabot-merge.yml +3 -1
- package/loops/templates/issues/bug_report.yml +109 -109
- package/loops/templates/issues/feature_request.yml +75 -75
- package/loops/workflows/agent-implement.md +13 -12
- package/loops/workflows/shared/opencode-ci.md +17 -5
- package/loops/workflows/shared/platform-defaults.md +53 -53
- package/loops/workflows/work-router.yml +4 -0
- package/package.json +2 -2
|
@@ -1,29 +1,29 @@
|
|
|
1
|
-
# Managed by @plainconceptsplatform/workflows. Source: loops/actions/create-issue-comment/action.yml. Update with workflows update --force; consumer edits may be overwritten.
|
|
2
|
-
name: Create issue comment
|
|
3
|
-
description: Create a comment on an issue or pull request.
|
|
4
|
-
inputs:
|
|
5
|
-
token:
|
|
6
|
-
description: GitHub token used by github-script.
|
|
7
|
-
required: true
|
|
8
|
-
issue-number:
|
|
9
|
-
description: Issue or pull request number.
|
|
10
|
-
required: true
|
|
11
|
-
body:
|
|
12
|
-
description: Complete Markdown comment body.
|
|
13
|
-
required: true
|
|
14
|
-
runs:
|
|
15
|
-
using: composite
|
|
16
|
-
steps:
|
|
17
|
-
- name: Create comment
|
|
18
|
-
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
|
19
|
-
env:
|
|
20
|
-
ISSUE_NUMBER: ${{ inputs.issue-number }}
|
|
21
|
-
BODY: ${{ inputs.body }}
|
|
22
|
-
with:
|
|
23
|
-
github-token: ${{ inputs.token }}
|
|
24
|
-
script: |
|
|
25
|
-
await github.rest.issues.createComment({
|
|
26
|
-
...context.repo,
|
|
27
|
-
issue_number: Number(process.env.ISSUE_NUMBER),
|
|
28
|
-
body: process.env.BODY,
|
|
29
|
-
});
|
|
1
|
+
# Managed by @plainconceptsplatform/workflows. Source: loops/actions/create-issue-comment/action.yml. Update with workflows update --force; consumer edits may be overwritten.
|
|
2
|
+
name: Create issue comment
|
|
3
|
+
description: Create a comment on an issue or pull request.
|
|
4
|
+
inputs:
|
|
5
|
+
token:
|
|
6
|
+
description: GitHub token used by github-script.
|
|
7
|
+
required: true
|
|
8
|
+
issue-number:
|
|
9
|
+
description: Issue or pull request number.
|
|
10
|
+
required: true
|
|
11
|
+
body:
|
|
12
|
+
description: Complete Markdown comment body.
|
|
13
|
+
required: true
|
|
14
|
+
runs:
|
|
15
|
+
using: composite
|
|
16
|
+
steps:
|
|
17
|
+
- name: Create comment
|
|
18
|
+
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
|
19
|
+
env:
|
|
20
|
+
ISSUE_NUMBER: ${{ inputs.issue-number }}
|
|
21
|
+
BODY: ${{ inputs.body }}
|
|
22
|
+
with:
|
|
23
|
+
github-token: ${{ inputs.token }}
|
|
24
|
+
script: |
|
|
25
|
+
await github.rest.issues.createComment({
|
|
26
|
+
...context.repo,
|
|
27
|
+
issue_number: Number(process.env.ISSUE_NUMBER),
|
|
28
|
+
body: process.env.BODY,
|
|
29
|
+
});
|
|
@@ -1,53 +1,53 @@
|
|
|
1
|
-
# Managed by @plainconceptsplatform/workflows. Source: loops/actions/download-agent-output/action.yml. Update with workflows update --force; consumer edits may be overwritten.
|
|
2
|
-
name: Download agent output
|
|
3
|
-
description: Download the agent artifact and expose the output JSON and bundle paths.
|
|
4
|
-
inputs:
|
|
5
|
-
artifact-name:
|
|
6
|
-
description: >-
|
|
7
|
-
Artifact name to download. gh-aw prefixes it with the value it derives from the
|
|
8
|
-
workflow's inputs, so a workflow_call worker must pass the activation job's
|
|
9
|
-
artifact_prefix output followed by "agent", not the bare name.
|
|
10
|
-
required: true
|
|
11
|
-
outputs:
|
|
12
|
-
output-file:
|
|
13
|
-
description: Path to agent_output.json, or empty if not found.
|
|
14
|
-
value: ${{ steps.download.outputs.output-file }}
|
|
15
|
-
bundle-file:
|
|
16
|
-
description: Path to the git bundle, or empty if not found.
|
|
17
|
-
value: ${{ steps.download.outputs.bundle-file }}
|
|
18
|
-
item-count:
|
|
19
|
-
description: Number of items in the agent output.
|
|
20
|
-
value: ${{ steps.download.outputs.item-count }}
|
|
21
|
-
runs:
|
|
22
|
-
using: composite
|
|
23
|
-
steps:
|
|
24
|
-
- name: Download agent artifact
|
|
25
|
-
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
|
26
|
-
with:
|
|
27
|
-
name: ${{ inputs.artifact-name }}
|
|
28
|
-
path: agent-artifact
|
|
29
|
-
- name: Locate output and bundle
|
|
30
|
-
id: download
|
|
31
|
-
shell: bash
|
|
32
|
-
env:
|
|
33
|
-
ARTIFACT_NAME: ${{ inputs.artifact-name }}
|
|
34
|
-
run: |
|
|
35
|
-
set -euo pipefail
|
|
36
|
-
OUTPUT_FILE=""
|
|
37
|
-
BUNDLE_FILE=""
|
|
38
|
-
ITEM_COUNT="0"
|
|
39
|
-
|
|
40
|
-
if [ -f "agent-artifact/agent_output.json" ]; then
|
|
41
|
-
OUTPUT_FILE="agent-artifact/agent_output.json"
|
|
42
|
-
ITEM_COUNT=$(jq '.items | length' "$OUTPUT_FILE")
|
|
43
|
-
BUNDLE_FILE=$(ls agent-artifact/aw-*.bundle 2>/dev/null | head -1 || true)
|
|
44
|
-
else
|
|
45
|
-
echo "::error::Artifact '$ARTIFACT_NAME' contained no agent_output.json. Nothing the agent proposed will be applied."
|
|
46
|
-
exit 1
|
|
47
|
-
fi
|
|
48
|
-
|
|
49
|
-
echo "Artifact '$ARTIFACT_NAME' carries $ITEM_COUNT item(s)."
|
|
50
|
-
|
|
51
|
-
echo "output-file=$OUTPUT_FILE" >> "$GITHUB_OUTPUT"
|
|
52
|
-
echo "bundle-file=$BUNDLE_FILE" >> "$GITHUB_OUTPUT"
|
|
53
|
-
echo "item-count=$ITEM_COUNT" >> "$GITHUB_OUTPUT"
|
|
1
|
+
# Managed by @plainconceptsplatform/workflows. Source: loops/actions/download-agent-output/action.yml. Update with workflows update --force; consumer edits may be overwritten.
|
|
2
|
+
name: Download agent output
|
|
3
|
+
description: Download the agent artifact and expose the output JSON and bundle paths.
|
|
4
|
+
inputs:
|
|
5
|
+
artifact-name:
|
|
6
|
+
description: >-
|
|
7
|
+
Artifact name to download. gh-aw prefixes it with the value it derives from the
|
|
8
|
+
workflow's inputs, so a workflow_call worker must pass the activation job's
|
|
9
|
+
artifact_prefix output followed by "agent", not the bare name.
|
|
10
|
+
required: true
|
|
11
|
+
outputs:
|
|
12
|
+
output-file:
|
|
13
|
+
description: Path to agent_output.json, or empty if not found.
|
|
14
|
+
value: ${{ steps.download.outputs.output-file }}
|
|
15
|
+
bundle-file:
|
|
16
|
+
description: Path to the git bundle, or empty if not found.
|
|
17
|
+
value: ${{ steps.download.outputs.bundle-file }}
|
|
18
|
+
item-count:
|
|
19
|
+
description: Number of items in the agent output.
|
|
20
|
+
value: ${{ steps.download.outputs.item-count }}
|
|
21
|
+
runs:
|
|
22
|
+
using: composite
|
|
23
|
+
steps:
|
|
24
|
+
- name: Download agent artifact
|
|
25
|
+
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
|
26
|
+
with:
|
|
27
|
+
name: ${{ inputs.artifact-name }}
|
|
28
|
+
path: agent-artifact
|
|
29
|
+
- name: Locate output and bundle
|
|
30
|
+
id: download
|
|
31
|
+
shell: bash
|
|
32
|
+
env:
|
|
33
|
+
ARTIFACT_NAME: ${{ inputs.artifact-name }}
|
|
34
|
+
run: |
|
|
35
|
+
set -euo pipefail
|
|
36
|
+
OUTPUT_FILE=""
|
|
37
|
+
BUNDLE_FILE=""
|
|
38
|
+
ITEM_COUNT="0"
|
|
39
|
+
|
|
40
|
+
if [ -f "agent-artifact/agent_output.json" ]; then
|
|
41
|
+
OUTPUT_FILE="agent-artifact/agent_output.json"
|
|
42
|
+
ITEM_COUNT=$(jq '.items | length' "$OUTPUT_FILE")
|
|
43
|
+
BUNDLE_FILE=$(ls agent-artifact/aw-*.bundle 2>/dev/null | head -1 || true)
|
|
44
|
+
else
|
|
45
|
+
echo "::error::Artifact '$ARTIFACT_NAME' contained no agent_output.json. Nothing the agent proposed will be applied."
|
|
46
|
+
exit 1
|
|
47
|
+
fi
|
|
48
|
+
|
|
49
|
+
echo "Artifact '$ARTIFACT_NAME' carries $ITEM_COUNT item(s)."
|
|
50
|
+
|
|
51
|
+
echo "output-file=$OUTPUT_FILE" >> "$GITHUB_OUTPUT"
|
|
52
|
+
echo "bundle-file=$BUNDLE_FILE" >> "$GITHUB_OUTPUT"
|
|
53
|
+
echo "item-count=$ITEM_COUNT" >> "$GITHUB_OUTPUT"
|
|
@@ -1,40 +1,40 @@
|
|
|
1
|
-
# Managed by @plainconceptsplatform/workflows. Source: loops/actions/link-pr-to-issue/action.yml. Update with workflows update --force; consumer edits may be overwritten.
|
|
2
|
-
name: Link pull request to issue
|
|
3
|
-
description: Ensure the pull request body carries a closing reference to its source issue.
|
|
4
|
-
inputs:
|
|
5
|
-
token:
|
|
6
|
-
description: GitHub token with pull-requests write access.
|
|
7
|
-
required: true
|
|
8
|
-
pr-number:
|
|
9
|
-
description: Pull request number.
|
|
10
|
-
required: true
|
|
11
|
-
issue-number:
|
|
12
|
-
description: Issue number the pull request should close.
|
|
13
|
-
required: true
|
|
14
|
-
runs:
|
|
15
|
-
using: composite
|
|
16
|
-
steps:
|
|
17
|
-
- name: Ensure a closing reference
|
|
18
|
-
shell: bash
|
|
19
|
-
env:
|
|
20
|
-
GH_TOKEN: ${{ inputs.token }}
|
|
21
|
-
REPO: ${{ github.repository }}
|
|
22
|
-
PR_NUMBER: ${{ inputs.pr-number }}
|
|
23
|
-
ISSUE_NUMBER: ${{ inputs.issue-number }}
|
|
24
|
-
run: |
|
|
25
|
-
set -euo pipefail
|
|
26
|
-
|
|
27
|
-
pr="$(gh pr view "$PR_NUMBER" --repo "$REPO" --json closingIssuesReferences,body)"
|
|
28
|
-
|
|
29
|
-
if [ "$(jq '.closingIssuesReferences | length' <<<"$pr")" -gt 0 ]; then
|
|
30
|
-
echo "PR #$PR_NUMBER already closes an issue."
|
|
31
|
-
exit 0
|
|
32
|
-
fi
|
|
33
|
-
|
|
34
|
-
# A closing reference can only be created from the pull request body; there is no
|
|
35
|
-
# REST or GraphQL mutation for it.
|
|
36
|
-
body="$(jq -r '.body // ""' <<<"$pr")"
|
|
37
|
-
printf '%s\n\nCloses #%s\n' "$body" "$ISSUE_NUMBER" > /tmp/pr-body.md
|
|
38
|
-
|
|
39
|
-
gh pr edit "$PR_NUMBER" --repo "$REPO" --body-file /tmp/pr-body.md
|
|
40
|
-
echo "Added 'Closes #$ISSUE_NUMBER' to PR #$PR_NUMBER."
|
|
1
|
+
# Managed by @plainconceptsplatform/workflows. Source: loops/actions/link-pr-to-issue/action.yml. Update with workflows update --force; consumer edits may be overwritten.
|
|
2
|
+
name: Link pull request to issue
|
|
3
|
+
description: Ensure the pull request body carries a closing reference to its source issue.
|
|
4
|
+
inputs:
|
|
5
|
+
token:
|
|
6
|
+
description: GitHub token with pull-requests write access.
|
|
7
|
+
required: true
|
|
8
|
+
pr-number:
|
|
9
|
+
description: Pull request number.
|
|
10
|
+
required: true
|
|
11
|
+
issue-number:
|
|
12
|
+
description: Issue number the pull request should close.
|
|
13
|
+
required: true
|
|
14
|
+
runs:
|
|
15
|
+
using: composite
|
|
16
|
+
steps:
|
|
17
|
+
- name: Ensure a closing reference
|
|
18
|
+
shell: bash
|
|
19
|
+
env:
|
|
20
|
+
GH_TOKEN: ${{ inputs.token }}
|
|
21
|
+
REPO: ${{ github.repository }}
|
|
22
|
+
PR_NUMBER: ${{ inputs.pr-number }}
|
|
23
|
+
ISSUE_NUMBER: ${{ inputs.issue-number }}
|
|
24
|
+
run: |
|
|
25
|
+
set -euo pipefail
|
|
26
|
+
|
|
27
|
+
pr="$(gh pr view "$PR_NUMBER" --repo "$REPO" --json closingIssuesReferences,body)"
|
|
28
|
+
|
|
29
|
+
if [ "$(jq '.closingIssuesReferences | length' <<<"$pr")" -gt 0 ]; then
|
|
30
|
+
echo "PR #$PR_NUMBER already closes an issue."
|
|
31
|
+
exit 0
|
|
32
|
+
fi
|
|
33
|
+
|
|
34
|
+
# A closing reference can only be created from the pull request body; there is no
|
|
35
|
+
# REST or GraphQL mutation for it.
|
|
36
|
+
body="$(jq -r '.body // ""' <<<"$pr")"
|
|
37
|
+
printf '%s\n\nCloses #%s\n' "$body" "$ISSUE_NUMBER" > /tmp/pr-body.md
|
|
38
|
+
|
|
39
|
+
gh pr edit "$PR_NUMBER" --repo "$REPO" --body-file /tmp/pr-body.md
|
|
40
|
+
echo "Added 'Closes #$ISSUE_NUMBER' to PR #$PR_NUMBER."
|
|
@@ -1,33 +1,33 @@
|
|
|
1
|
-
# Managed by @plainconceptsplatform/workflows. Source: loops/actions/list-open-issues/action.yml. Update with workflows update --force; consumer edits may be overwritten.
|
|
2
|
-
name: List open issues
|
|
3
|
-
description: |
|
|
4
|
-
Writes all open issues (number, title, labels) to `/tmp/gh-aw/agent/open-issues.json`
|
|
5
|
-
so the agent can check for semantic duplicates without spending turns discovering them.
|
|
6
|
-
inputs:
|
|
7
|
-
token:
|
|
8
|
-
description: GitHub token with issues:read permission.
|
|
9
|
-
required: true
|
|
10
|
-
repo:
|
|
11
|
-
description: Repository in `owner/name` format.
|
|
12
|
-
required: true
|
|
13
|
-
output-path:
|
|
14
|
-
description: Path to write the JSON output.
|
|
15
|
-
required: false
|
|
16
|
-
default: /tmp/gh-aw/agent/open-issues.json
|
|
17
|
-
runs:
|
|
18
|
-
using: composite
|
|
19
|
-
steps:
|
|
20
|
-
- name: List open issues
|
|
21
|
-
shell: bash
|
|
22
|
-
env:
|
|
23
|
-
GH_TOKEN: ${{ inputs.token }}
|
|
24
|
-
REPO: ${{ inputs.repo }}
|
|
25
|
-
OUTPUT_PATH: ${{ inputs.output-path }}
|
|
26
|
-
run: |
|
|
27
|
-
set -euo pipefail
|
|
28
|
-
mkdir -p "$(dirname "$OUTPUT_PATH")"
|
|
29
|
-
gh issue list --repo "$REPO" --state open --limit 500 \
|
|
30
|
-
--json number,title,labels \
|
|
31
|
-
--jq '[.[] | {number, title, labels: [.labels[].name]}]' \
|
|
32
|
-
> "$OUTPUT_PATH"
|
|
33
|
-
echo "Wrote $(jq 'length' "$OUTPUT_PATH") open issues to $OUTPUT_PATH"
|
|
1
|
+
# Managed by @plainconceptsplatform/workflows. Source: loops/actions/list-open-issues/action.yml. Update with workflows update --force; consumer edits may be overwritten.
|
|
2
|
+
name: List open issues
|
|
3
|
+
description: |
|
|
4
|
+
Writes all open issues (number, title, labels) to `/tmp/gh-aw/agent/open-issues.json`
|
|
5
|
+
so the agent can check for semantic duplicates without spending turns discovering them.
|
|
6
|
+
inputs:
|
|
7
|
+
token:
|
|
8
|
+
description: GitHub token with issues:read permission.
|
|
9
|
+
required: true
|
|
10
|
+
repo:
|
|
11
|
+
description: Repository in `owner/name` format.
|
|
12
|
+
required: true
|
|
13
|
+
output-path:
|
|
14
|
+
description: Path to write the JSON output.
|
|
15
|
+
required: false
|
|
16
|
+
default: /tmp/gh-aw/agent/open-issues.json
|
|
17
|
+
runs:
|
|
18
|
+
using: composite
|
|
19
|
+
steps:
|
|
20
|
+
- name: List open issues
|
|
21
|
+
shell: bash
|
|
22
|
+
env:
|
|
23
|
+
GH_TOKEN: ${{ inputs.token }}
|
|
24
|
+
REPO: ${{ inputs.repo }}
|
|
25
|
+
OUTPUT_PATH: ${{ inputs.output-path }}
|
|
26
|
+
run: |
|
|
27
|
+
set -euo pipefail
|
|
28
|
+
mkdir -p "$(dirname "$OUTPUT_PATH")"
|
|
29
|
+
gh issue list --repo "$REPO" --state open --limit 500 \
|
|
30
|
+
--json number,title,labels \
|
|
31
|
+
--jq '[.[] | {number, title, labels: [.labels[].name]}]' \
|
|
32
|
+
> "$OUTPUT_PATH"
|
|
33
|
+
echo "Wrote $(jq 'length' "$OUTPUT_PATH") open issues to $OUTPUT_PATH"
|
|
@@ -1,45 +1,45 @@
|
|
|
1
|
-
# Managed by @plainconceptsplatform/workflows. Source: loops/actions/load-issue-context/action.yml. Update with workflows update --force; consumer edits may be overwritten.
|
|
2
|
-
name: Load issue context
|
|
3
|
-
description: Write issue metadata and comment context to a JSON file.
|
|
4
|
-
inputs:
|
|
5
|
-
token:
|
|
6
|
-
description: GitHub token used by github-script.
|
|
7
|
-
required: true
|
|
8
|
-
issue-number:
|
|
9
|
-
description: Issue number to load.
|
|
10
|
-
required: true
|
|
11
|
-
output-path:
|
|
12
|
-
description: Absolute path where context JSON is written.
|
|
13
|
-
required: true
|
|
14
|
-
runs:
|
|
15
|
-
using: composite
|
|
16
|
-
steps:
|
|
17
|
-
- name: Load issue and comments
|
|
18
|
-
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
|
19
|
-
env:
|
|
20
|
-
ISSUE_NUMBER: ${{ inputs.issue-number }}
|
|
21
|
-
OUTPUT_PATH: ${{ inputs.output-path }}
|
|
22
|
-
with:
|
|
23
|
-
github-token: ${{ inputs.token }}
|
|
24
|
-
script: |
|
|
25
|
-
const fs = require('fs');
|
|
26
|
-
const issueNumber = Number(process.env.ISSUE_NUMBER);
|
|
27
|
-
const issue = await github.rest.issues.get({ ...context.repo, issue_number: issueNumber });
|
|
28
|
-
const comments = await github.paginate(github.rest.issues.listComments, {
|
|
29
|
-
...context.repo, issue_number: issueNumber, per_page: 100,
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
fs.mkdirSync(require('path').dirname(process.env.OUTPUT_PATH), { recursive: true });
|
|
33
|
-
fs.writeFileSync(process.env.OUTPUT_PATH, JSON.stringify({
|
|
34
|
-
number: issue.data.number,
|
|
35
|
-
title: issue.data.title,
|
|
36
|
-
body: issue.data.body,
|
|
37
|
-
author: issue.data.user.login,
|
|
38
|
-
authorAssociation: issue.data.author_association,
|
|
39
|
-
labels: issue.data.labels.map(({ name }) => name),
|
|
40
|
-
comments: comments.map(({ user, author_association, body }) => ({
|
|
41
|
-
author: user.login,
|
|
42
|
-
association: author_association,
|
|
43
|
-
body,
|
|
44
|
-
})),
|
|
45
|
-
}, null, 2));
|
|
1
|
+
# Managed by @plainconceptsplatform/workflows. Source: loops/actions/load-issue-context/action.yml. Update with workflows update --force; consumer edits may be overwritten.
|
|
2
|
+
name: Load issue context
|
|
3
|
+
description: Write issue metadata and comment context to a JSON file.
|
|
4
|
+
inputs:
|
|
5
|
+
token:
|
|
6
|
+
description: GitHub token used by github-script.
|
|
7
|
+
required: true
|
|
8
|
+
issue-number:
|
|
9
|
+
description: Issue number to load.
|
|
10
|
+
required: true
|
|
11
|
+
output-path:
|
|
12
|
+
description: Absolute path where context JSON is written.
|
|
13
|
+
required: true
|
|
14
|
+
runs:
|
|
15
|
+
using: composite
|
|
16
|
+
steps:
|
|
17
|
+
- name: Load issue and comments
|
|
18
|
+
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
|
19
|
+
env:
|
|
20
|
+
ISSUE_NUMBER: ${{ inputs.issue-number }}
|
|
21
|
+
OUTPUT_PATH: ${{ inputs.output-path }}
|
|
22
|
+
with:
|
|
23
|
+
github-token: ${{ inputs.token }}
|
|
24
|
+
script: |
|
|
25
|
+
const fs = require('fs');
|
|
26
|
+
const issueNumber = Number(process.env.ISSUE_NUMBER);
|
|
27
|
+
const issue = await github.rest.issues.get({ ...context.repo, issue_number: issueNumber });
|
|
28
|
+
const comments = await github.paginate(github.rest.issues.listComments, {
|
|
29
|
+
...context.repo, issue_number: issueNumber, per_page: 100,
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
fs.mkdirSync(require('path').dirname(process.env.OUTPUT_PATH), { recursive: true });
|
|
33
|
+
fs.writeFileSync(process.env.OUTPUT_PATH, JSON.stringify({
|
|
34
|
+
number: issue.data.number,
|
|
35
|
+
title: issue.data.title,
|
|
36
|
+
body: issue.data.body,
|
|
37
|
+
author: issue.data.user.login,
|
|
38
|
+
authorAssociation: issue.data.author_association,
|
|
39
|
+
labels: issue.data.labels.map(({ name }) => name),
|
|
40
|
+
comments: comments.map(({ user, author_association, body }) => ({
|
|
41
|
+
author: user.login,
|
|
42
|
+
association: author_association,
|
|
43
|
+
body,
|
|
44
|
+
})),
|
|
45
|
+
}, null, 2));
|
|
@@ -1,49 +1,49 @@
|
|
|
1
|
-
# Managed by @plainconceptsplatform/workflows. Source: loops/actions/merge-agent-pr/action.yml. Update with workflows update --force; consumer edits may be overwritten.
|
|
2
|
-
name: Merge agent pull request
|
|
3
|
-
description: Read merge_pull_request from agent_output.json and merge the PR via gh.
|
|
4
|
-
inputs:
|
|
5
|
-
output-file:
|
|
6
|
-
description: Path to agent_output.json.
|
|
7
|
-
required: true
|
|
8
|
-
token:
|
|
9
|
-
description: GitHub token with pull-requests:write and contents:write.
|
|
10
|
-
required: true
|
|
11
|
-
repo:
|
|
12
|
-
description: Target repository in owner/name format.
|
|
13
|
-
required: false
|
|
14
|
-
default: ${{ github.repository }}
|
|
15
|
-
runs:
|
|
16
|
-
using: composite
|
|
17
|
-
steps:
|
|
18
|
-
- name: Merge pull request
|
|
19
|
-
shell: bash
|
|
20
|
-
env:
|
|
21
|
-
GH_TOKEN: ${{ inputs.token }}
|
|
22
|
-
OUTPUT_FILE: ${{ inputs.output-file }}
|
|
23
|
-
REPO: ${{ inputs.repo }}
|
|
24
|
-
run: |
|
|
25
|
-
set -euo pipefail
|
|
26
|
-
[ -f "$OUTPUT_FILE" ] || exit 0
|
|
27
|
-
|
|
28
|
-
jq -c '.items[] | select(.type == "merge_pull_request")' "$OUTPUT_FILE" | while read -r item; do
|
|
29
|
-
PR_NUM=$(echo "$item" | jq -er '.pr_number // .item_number // empty')
|
|
30
|
-
[[ "$PR_NUM" =~ ^[1-9][0-9]*$ ]] || { echo "::error::Invalid pull request number: $PR_NUM"; exit 1; }
|
|
31
|
-
|
|
32
|
-
HEAD_SHA=$(gh pr view "$PR_NUM" --repo "$REPO" --json headRefOid --jq '.headRefOid')
|
|
33
|
-
[[ "$HEAD_SHA" =~ ^[0-9a-fA-F]{40}$ ]] || { echo "::error::Invalid pull request head SHA for #$PR_NUM"; exit 1; }
|
|
34
|
-
|
|
35
|
-
HEAD_REF=$(gh pr view "$PR_NUM" --repo "$REPO" --json headRefName --jq '.headRefName')
|
|
36
|
-
|
|
37
|
-
gh pr merge "$PR_NUM" --repo "$REPO" --squash --match-head-commit "$HEAD_SHA"
|
|
38
|
-
|
|
39
|
-
# Delete the branch, because nothing else ever has: four repositories had accumulated
|
|
40
|
-
# 47 non-main branches, every one the head of a pull request merged or closed months
|
|
41
|
-
# ago. Done after the merge and with its failure swallowed rather than through
|
|
42
|
-
# `gh pr merge --delete-branch`, which also tries to delete the local branch and can
|
|
43
|
-
# turn a completed merge into a red step. `delete_branch_on_merge` on the repository
|
|
44
|
-
# does the same job, but only where someone remembered to switch it on.
|
|
45
|
-
if [ -n "$HEAD_REF" ] && [ "$HEAD_REF" != "null" ]; then
|
|
46
|
-
gh api -X DELETE "repos/$REPO/git/refs/heads/$HEAD_REF" >/dev/null 2>&1 ||
|
|
47
|
-
echo "::notice::branch $HEAD_REF was already gone or is protected"
|
|
48
|
-
fi
|
|
49
|
-
done
|
|
1
|
+
# Managed by @plainconceptsplatform/workflows. Source: loops/actions/merge-agent-pr/action.yml. Update with workflows update --force; consumer edits may be overwritten.
|
|
2
|
+
name: Merge agent pull request
|
|
3
|
+
description: Read merge_pull_request from agent_output.json and merge the PR via gh.
|
|
4
|
+
inputs:
|
|
5
|
+
output-file:
|
|
6
|
+
description: Path to agent_output.json.
|
|
7
|
+
required: true
|
|
8
|
+
token:
|
|
9
|
+
description: GitHub token with pull-requests:write and contents:write.
|
|
10
|
+
required: true
|
|
11
|
+
repo:
|
|
12
|
+
description: Target repository in owner/name format.
|
|
13
|
+
required: false
|
|
14
|
+
default: ${{ github.repository }}
|
|
15
|
+
runs:
|
|
16
|
+
using: composite
|
|
17
|
+
steps:
|
|
18
|
+
- name: Merge pull request
|
|
19
|
+
shell: bash
|
|
20
|
+
env:
|
|
21
|
+
GH_TOKEN: ${{ inputs.token }}
|
|
22
|
+
OUTPUT_FILE: ${{ inputs.output-file }}
|
|
23
|
+
REPO: ${{ inputs.repo }}
|
|
24
|
+
run: |
|
|
25
|
+
set -euo pipefail
|
|
26
|
+
[ -f "$OUTPUT_FILE" ] || exit 0
|
|
27
|
+
|
|
28
|
+
jq -c '.items[] | select(.type == "merge_pull_request")' "$OUTPUT_FILE" | while read -r item; do
|
|
29
|
+
PR_NUM=$(echo "$item" | jq -er '.pr_number // .item_number // empty')
|
|
30
|
+
[[ "$PR_NUM" =~ ^[1-9][0-9]*$ ]] || { echo "::error::Invalid pull request number: $PR_NUM"; exit 1; }
|
|
31
|
+
|
|
32
|
+
HEAD_SHA=$(gh pr view "$PR_NUM" --repo "$REPO" --json headRefOid --jq '.headRefOid')
|
|
33
|
+
[[ "$HEAD_SHA" =~ ^[0-9a-fA-F]{40}$ ]] || { echo "::error::Invalid pull request head SHA for #$PR_NUM"; exit 1; }
|
|
34
|
+
|
|
35
|
+
HEAD_REF=$(gh pr view "$PR_NUM" --repo "$REPO" --json headRefName --jq '.headRefName')
|
|
36
|
+
|
|
37
|
+
gh pr merge "$PR_NUM" --repo "$REPO" --squash --match-head-commit "$HEAD_SHA"
|
|
38
|
+
|
|
39
|
+
# Delete the branch, because nothing else ever has: four repositories had accumulated
|
|
40
|
+
# 47 non-main branches, every one the head of a pull request merged or closed months
|
|
41
|
+
# ago. Done after the merge and with its failure swallowed rather than through
|
|
42
|
+
# `gh pr merge --delete-branch`, which also tries to delete the local branch and can
|
|
43
|
+
# turn a completed merge into a red step. `delete_branch_on_merge` on the repository
|
|
44
|
+
# does the same job, but only where someone remembered to switch it on.
|
|
45
|
+
if [ -n "$HEAD_REF" ] && [ "$HEAD_REF" != "null" ]; then
|
|
46
|
+
gh api -X DELETE "repos/$REPO/git/refs/heads/$HEAD_REF" >/dev/null 2>&1 ||
|
|
47
|
+
echo "::notice::branch $HEAD_REF was already gone or is protected"
|
|
48
|
+
fi
|
|
49
|
+
done
|
|
@@ -9,9 +9,16 @@ description: >-
|
|
|
9
9
|
inputs:
|
|
10
10
|
token:
|
|
11
11
|
description: >-
|
|
12
|
-
Token
|
|
13
|
-
workflows on the default branch; a merge made with
|
|
12
|
+
Token for the writes: approve, merge, comment. Contents and pull-requests write. The App
|
|
13
|
+
token makes the merge start the push workflows on the default branch; a merge made with
|
|
14
|
+
GITHUB_TOKEN starts none.
|
|
14
15
|
required: true
|
|
16
|
+
read-token:
|
|
17
|
+
description: >-
|
|
18
|
+
Token for the reads: pull requests, check runs, commit statuses. Needs checks and statuses
|
|
19
|
+
read, which the App may not hold. A read it is refused skips that pull request with a warning.
|
|
20
|
+
required: false
|
|
21
|
+
default: ${{ github.token }}
|
|
15
22
|
scope:
|
|
16
23
|
description: "Which updates merge: all, minor (minor and patch), patch, or off."
|
|
17
24
|
required: false
|
|
@@ -44,6 +51,7 @@ runs:
|
|
|
44
51
|
shell: bash
|
|
45
52
|
env:
|
|
46
53
|
GH_TOKEN: ${{ inputs.token }}
|
|
54
|
+
READ_TOKEN: ${{ inputs.read-token }}
|
|
47
55
|
REPO: ${{ github.repository }}
|
|
48
56
|
SCOPE: ${{ inputs.scope }}
|
|
49
57
|
MERGE_WITHOUT_CHECKS: ${{ inputs.merge-without-checks }}
|