@plainconceptsplatform/workflows 0.19.2 → 0.20.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.js +12 -1
- package/dist/stack-defaults.js +16 -16
- package/dist/worker-env.js +14 -0
- 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/apply-agent-output/action.yml +108 -108
- package/loops/actions/assess-blast-radius/action.yml +148 -0
- package/loops/actions/assess-blast-radius/assess-blast-radius.sh +138 -0
- package/loops/actions/classify-route/action.yml +100 -100
- package/loops/actions/cleanup-artifacts/action.yml +91 -91
- package/loops/actions/close-agent-issues/action.yml +43 -43
- package/loops/actions/create-agent-issues/action.yml +52 -52
- package/loops/actions/create-issue-comment/action.yml +29 -29
- package/loops/actions/download-agent-output/action.yml +53 -53
- package/loops/actions/housekeeping/action.yml +55 -2
- 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/push-agent-branch/action.yml +45 -45
- package/loops/actions/remove-issue-labels/action.yml +37 -37
- package/loops/actions/update-agent-issues/action.yml +58 -58
- package/loops/actions/validate-merge-gate-output/action.yml +62 -40
- package/loops/actions/validate-merge-gate-output/validate-merge-gate-output.sh +147 -31
- package/loops/actions/validate-refine-output/action.yml +48 -44
- package/loops/actions/validate-refine-output/validate-refine-output.sh +15 -4
- 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-refine-output/verify-refine-output.sh +6 -1
- package/loops/actions/verify-route-matrix/action.yml +9 -9
- package/loops/actions/verify-route-matrix/verify-gate-metrics.mjs +51 -0
- package/loops/actions/verify-route-matrix/verify-route-matrix.sh +329 -29
- package/loops/scripts/compile-agent-workflows.mjs +331 -331
- package/loops/templates/agentics/agentics-maintenance.yml +121 -121
- package/loops/templates/ci/app-ci-dotnet-next.yml +330 -330
- package/loops/templates/ci/app-ci-node-monorepo.yml +260 -260
- package/loops/templates/issues/bug_report.yml +109 -109
- package/loops/templates/issues/feature_request.yml +75 -75
- package/loops/templates/opencode/opencode.ci.json +55 -49
- package/loops/templates/opencode/opencode.ci.json.md +59 -49
- package/loops/templates/release/github-release.yml +30 -30
- package/loops/workflows/agent-merge-gate.md +367 -148
- package/loops/workflows/agent-refine.md +60 -16
- package/loops/workflows/authorize-bot-work.yml +105 -105
- package/loops/workflows/shared/opencode-ci.md +206 -206
- package/loops/workflows/shared/platform-defaults.md +19 -19
- package/package.json +1 -1
|
@@ -151,11 +151,17 @@ export async function installCatalog(repositoryPath, options = {}) {
|
|
|
151
151
|
// (the shared CI setup and the OpenCode config) get them on every run and stay stable. A worker
|
|
152
152
|
// gets its VERIFY_COMMANDS default once, when it is first installed: after that the value is the
|
|
153
153
|
// consumer's, and the env merge keeps it.
|
|
154
|
+
//
|
|
155
|
+
// Except when the consumer has no value. "First install only" meant a worker installed before
|
|
156
|
+
// this injection existed kept `VERIFY_COMMANDS: ""` for good, and mergeWorkerEnv then preserved
|
|
157
|
+
// the empty string as the consumer's deliberate choice. All four consuming repositories were in
|
|
158
|
+
// that state, so every merge-gate repair pushed a fix with the verification block interpolating
|
|
159
|
+
// to nothing. An empty value is the absence of a choice, so an update fills it.
|
|
154
160
|
function applyStackDefaults(files, inspection, existing) {
|
|
155
161
|
const defaults = generateStackDefaults(inspection);
|
|
156
162
|
const result = new Map(files);
|
|
157
163
|
for (const [target, content] of result) {
|
|
158
|
-
if (isWorker(target) && !existing.has(target)) {
|
|
164
|
+
if (isWorker(target) && (!existing.has(target) || hasEmptyVerifyCommands(existing.get(target)))) {
|
|
159
165
|
result.set(target, injectStackEnv(content, defaults));
|
|
160
166
|
}
|
|
161
167
|
else if (target.endsWith("opencode-ci.md")) {
|
|
@@ -167,6 +173,11 @@ function applyStackDefaults(files, inspection, existing) {
|
|
|
167
173
|
}
|
|
168
174
|
return result;
|
|
169
175
|
}
|
|
176
|
+
// A worker whose VERIFY_COMMANDS is present but empty. Anything else, including a value the
|
|
177
|
+
// consumer wrote, is left alone.
|
|
178
|
+
function hasEmptyVerifyCommands(current) {
|
|
179
|
+
return typeof current === "string" && /^ {2}VERIFY_COMMANDS: *(""|'')? *$/m.test(current);
|
|
180
|
+
}
|
|
170
181
|
// Directories that belong wholly to the package. A file here that carries our ownership header
|
|
171
182
|
// and is no longer in the package was deleted upstream, and without this it would sit in every
|
|
172
183
|
// consumer forever: that is how `stale-recovery` and `update-changelog` outlived the code that
|
package/dist/stack-defaults.js
CHANGED
|
@@ -31,31 +31,31 @@ export function generateOpencodeCi(baseContent, inspection) {
|
|
|
31
31
|
if (inspection.stackHints.solutionFiles.length > 0) {
|
|
32
32
|
const solutionPath = inspection.stackHints.solutionFiles[0].replaceAll("\\", "/");
|
|
33
33
|
if (!result.includes("name: Cache NuGet packages")) {
|
|
34
|
-
const nugetCache = ` - name: Cache NuGet packages
|
|
35
|
-
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
|
|
36
|
-
with:
|
|
37
|
-
path: ~/.nuget/packages
|
|
38
|
-
key: nuget-\${{ runner.os }}-\${{ hashFiles('**/*.slnx', '**/Directory.Packages.props') }}
|
|
39
|
-
restore-keys: nuget-\${{ runner.os }}-
|
|
40
|
-
|
|
34
|
+
const nugetCache = ` - name: Cache NuGet packages
|
|
35
|
+
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
|
|
36
|
+
with:
|
|
37
|
+
path: ~/.nuget/packages
|
|
38
|
+
key: nuget-\${{ runner.os }}-\${{ hashFiles('**/*.slnx', '**/Directory.Packages.props') }}
|
|
39
|
+
restore-keys: nuget-\${{ runner.os }}-
|
|
40
|
+
|
|
41
41
|
`;
|
|
42
42
|
result = insertBeforeMarker(result, nugetCache, " - name: Install workspace dependencies");
|
|
43
43
|
}
|
|
44
44
|
if (!result.includes("name: Restore .NET dependencies")) {
|
|
45
|
-
const restore = ` - name: Restore .NET dependencies
|
|
46
|
-
run: dotnet restore ${solutionPath}
|
|
47
|
-
|
|
45
|
+
const restore = ` - name: Restore .NET dependencies
|
|
46
|
+
run: dotnet restore ${solutionPath}
|
|
47
|
+
|
|
48
48
|
`;
|
|
49
49
|
result = insertBeforeMarker(result, restore, " - name: Install workspace dependencies");
|
|
50
50
|
}
|
|
51
51
|
}
|
|
52
52
|
if (inspection.stackHints.openSpec && !result.includes("name: Install OpenSpec CLI")) {
|
|
53
|
-
const openspecStep = ` - name: Install OpenSpec CLI
|
|
54
|
-
run: |
|
|
55
|
-
set -euo pipefail
|
|
56
|
-
npm install -g "@fission-ai/openspec@1.8.0"
|
|
57
|
-
openspec --version
|
|
58
|
-
|
|
53
|
+
const openspecStep = ` - name: Install OpenSpec CLI
|
|
54
|
+
run: |
|
|
55
|
+
set -euo pipefail
|
|
56
|
+
npm install -g "@fission-ai/openspec@1.8.0"
|
|
57
|
+
openspec --version
|
|
58
|
+
|
|
59
59
|
`;
|
|
60
60
|
result = insertBeforeMarker(result, openspecStep, " - name: Install workspace dependencies");
|
|
61
61
|
}
|
package/dist/worker-env.js
CHANGED
|
@@ -74,6 +74,10 @@ export function entryValue(entry) {
|
|
|
74
74
|
const first = entry.lines[0].replace(ENTRY, "$2").trim();
|
|
75
75
|
return [first, ...entry.lines.slice(1).map((line) => line.trim())].join("\n").trim();
|
|
76
76
|
}
|
|
77
|
+
// A value that is present but says nothing: empty, or empty quotes.
|
|
78
|
+
function isBlank(value) {
|
|
79
|
+
return value === "" || value === '""' || value === "''";
|
|
80
|
+
}
|
|
77
81
|
export function mergeWorkerEnv(packageContent, consumerContent, baselineContent, parse = parseWorkerEnv) {
|
|
78
82
|
const report = { keptEnv: [], updatedDefaults: [], consumerOnlyEnv: [], droppedEnv: [] };
|
|
79
83
|
const pkg = parse(packageContent);
|
|
@@ -91,6 +95,16 @@ export function mergeWorkerEnv(packageContent, consumerContent, baselineContent,
|
|
|
91
95
|
merged.push(entry);
|
|
92
96
|
continue;
|
|
93
97
|
}
|
|
98
|
+
// An empty value is the absence of a choice, not a choice of nothing. Treating it as the
|
|
99
|
+
// consumer's is how `VERIFY_COMMANDS: ""` survived in all four consuming repositories with
|
|
100
|
+
// no baseline to compare against, leaving the merge gate pushing repairs it had verified
|
|
101
|
+
// with an empty command block. If the package has something and the consumer has nothing,
|
|
102
|
+
// the package wins.
|
|
103
|
+
if (isBlank(entryValue(mine)) && !isBlank(entryValue(entry))) {
|
|
104
|
+
merged.push(entry);
|
|
105
|
+
report.updatedDefaults.push(entry.key);
|
|
106
|
+
continue;
|
|
107
|
+
}
|
|
94
108
|
const base = baselineByKey.get(entry.key);
|
|
95
109
|
if (base !== undefined && entryValue(base) === entryValue(mine)) {
|
|
96
110
|
// Still the previous default: the package changed it, the consumer never did.
|
|
@@ -1,50 +1,50 @@
|
|
|
1
|
-
# Managed by @plainconceptsplatform/workflows. Source: loops/actions/add-issue-labels/action.yml. Update with workflows update --force; consumer edits may be overwritten.
|
|
2
|
-
name: Add issue labels
|
|
3
|
-
description: Add one or more labels to 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
|
-
labels:
|
|
12
|
-
description: Labels to add, one per line. A comma-separated list is accepted as well.
|
|
13
|
-
required: true
|
|
14
|
-
runs:
|
|
15
|
-
using: composite
|
|
16
|
-
steps:
|
|
17
|
-
- name: Add labels
|
|
18
|
-
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
|
19
|
-
env:
|
|
20
|
-
ISSUE_NUMBER: ${{ inputs.issue-number }}
|
|
21
|
-
LABELS: ${{ inputs.labels }}
|
|
22
|
-
with:
|
|
23
|
-
github-token: ${{ inputs.token }}
|
|
24
|
-
script: |
|
|
25
|
-
const labels = process.env.LABELS.split(/\r?\n|,/).map((label) => label.trim()).filter(Boolean);
|
|
26
|
-
if (labels.length === 0) {
|
|
27
|
-
core.notice('No labels to add.');
|
|
28
|
-
return;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
// Create what does not exist yet, so shipping a new label in the package does not
|
|
32
|
-
// require a person to go and make it in every repository first. Its sibling
|
|
33
|
-
// remove-issue-labels has swallowed 404 for a long time; this one had no guard at all,
|
|
34
|
-
// so a label the package introduced would fail the step in every consumer until
|
|
35
|
-
// somebody created it by hand. 422 is "already exists", which is the happy path on
|
|
36
|
-
// every run after the first.
|
|
37
|
-
for (const name of labels) {
|
|
38
|
-
try {
|
|
39
|
-
await github.rest.issues.createLabel({ ...context.repo, name, color: 'ededed' });
|
|
40
|
-
core.notice(`Created the ${name} label.`);
|
|
41
|
-
} catch (error) {
|
|
42
|
-
if (error.status !== 422) throw error;
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
await github.rest.issues.addLabels({
|
|
47
|
-
...context.repo,
|
|
48
|
-
issue_number: Number(process.env.ISSUE_NUMBER),
|
|
49
|
-
labels,
|
|
50
|
-
});
|
|
1
|
+
# Managed by @plainconceptsplatform/workflows. Source: loops/actions/add-issue-labels/action.yml. Update with workflows update --force; consumer edits may be overwritten.
|
|
2
|
+
name: Add issue labels
|
|
3
|
+
description: Add one or more labels to 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
|
+
labels:
|
|
12
|
+
description: Labels to add, one per line. A comma-separated list is accepted as well.
|
|
13
|
+
required: true
|
|
14
|
+
runs:
|
|
15
|
+
using: composite
|
|
16
|
+
steps:
|
|
17
|
+
- name: Add labels
|
|
18
|
+
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
|
19
|
+
env:
|
|
20
|
+
ISSUE_NUMBER: ${{ inputs.issue-number }}
|
|
21
|
+
LABELS: ${{ inputs.labels }}
|
|
22
|
+
with:
|
|
23
|
+
github-token: ${{ inputs.token }}
|
|
24
|
+
script: |
|
|
25
|
+
const labels = process.env.LABELS.split(/\r?\n|,/).map((label) => label.trim()).filter(Boolean);
|
|
26
|
+
if (labels.length === 0) {
|
|
27
|
+
core.notice('No labels to add.');
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Create what does not exist yet, so shipping a new label in the package does not
|
|
32
|
+
// require a person to go and make it in every repository first. Its sibling
|
|
33
|
+
// remove-issue-labels has swallowed 404 for a long time; this one had no guard at all,
|
|
34
|
+
// so a label the package introduced would fail the step in every consumer until
|
|
35
|
+
// somebody created it by hand. 422 is "already exists", which is the happy path on
|
|
36
|
+
// every run after the first.
|
|
37
|
+
for (const name of labels) {
|
|
38
|
+
try {
|
|
39
|
+
await github.rest.issues.createLabel({ ...context.repo, name, color: 'ededed' });
|
|
40
|
+
core.notice(`Created the ${name} label.`);
|
|
41
|
+
} catch (error) {
|
|
42
|
+
if (error.status !== 422) throw error;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
await github.rest.issues.addLabels({
|
|
47
|
+
...context.repo,
|
|
48
|
+
issue_number: Number(process.env.ISSUE_NUMBER),
|
|
49
|
+
labels,
|
|
50
|
+
});
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
// Managed by @plainconceptsplatform/workflows. Source: loops/actions/agent-output.cjs. Update with `workflows update --force`; consumer edits may be overwritten.
|
|
2
|
-
const fs = require('node:fs');
|
|
3
|
-
|
|
4
|
-
// Every apply-agent-* action reads the same artifact the same way: a missing file means the
|
|
5
|
-
// agent produced nothing, which is a normal outcome rather than a failure.
|
|
6
|
-
function readAgentItems(outputFile, type) {
|
|
7
|
-
if (!outputFile || !fs.existsSync(outputFile)) {
|
|
8
|
-
return [];
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
const parsed = JSON.parse(fs.readFileSync(outputFile, 'utf8'));
|
|
12
|
-
const items = Array.isArray(parsed.items) ? parsed.items : [];
|
|
13
|
-
|
|
14
|
-
return type ? items.filter((item) => item.type === type) : items;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
module.exports = { readAgentItems };
|
|
1
|
+
// Managed by @plainconceptsplatform/workflows. Source: loops/actions/agent-output.cjs. Update with `workflows update --force`; consumer edits may be overwritten.
|
|
2
|
+
const fs = require('node:fs');
|
|
3
|
+
|
|
4
|
+
// Every apply-agent-* action reads the same artifact the same way: a missing file means the
|
|
5
|
+
// agent produced nothing, which is a normal outcome rather than a failure.
|
|
6
|
+
function readAgentItems(outputFile, type) {
|
|
7
|
+
if (!outputFile || !fs.existsSync(outputFile)) {
|
|
8
|
+
return [];
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const parsed = JSON.parse(fs.readFileSync(outputFile, 'utf8'));
|
|
12
|
+
const items = Array.isArray(parsed.items) ? parsed.items : [];
|
|
13
|
+
|
|
14
|
+
return type ? items.filter((item) => item.type === type) : items;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
module.exports = { readAgentItems };
|
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
# Managed by @plainconceptsplatform/workflows. Source: loops/actions/apply-agent-bundle/action.yml. Update with workflows update --force; consumer edits may be overwritten.
|
|
2
|
-
name: Apply agent bundle
|
|
3
|
-
description: Fast-forward an intended branch to the single commit exported by a verified git bundle.
|
|
4
|
-
inputs:
|
|
5
|
-
bundle-file:
|
|
6
|
-
description: Path to the git bundle from the agent artifact.
|
|
7
|
-
required: true
|
|
8
|
-
target-branch:
|
|
9
|
-
description: Branch that must fast-forward to the bundle commit.
|
|
10
|
-
required: true
|
|
11
|
-
base-branch:
|
|
12
|
-
description: Existing branch used only when target-branch does not exist.
|
|
13
|
-
required: false
|
|
14
|
-
default: ''
|
|
15
|
-
runs:
|
|
16
|
-
using: composite
|
|
17
|
-
steps:
|
|
18
|
-
- name: Fast-forward branch from bundle
|
|
19
|
-
shell: bash
|
|
20
|
-
env:
|
|
21
|
-
BUNDLE_FILE: ${{ inputs.bundle-file }}
|
|
22
|
-
TARGET_BRANCH: ${{ inputs.target-branch }}
|
|
23
|
-
BASE_BRANCH: ${{ inputs.base-branch }}
|
|
24
|
-
run: bash "$GITHUB_ACTION_PATH/apply-bundle.sh" "$BUNDLE_FILE" "$TARGET_BRANCH" "$BASE_BRANCH"
|
|
1
|
+
# Managed by @plainconceptsplatform/workflows. Source: loops/actions/apply-agent-bundle/action.yml. Update with workflows update --force; consumer edits may be overwritten.
|
|
2
|
+
name: Apply agent bundle
|
|
3
|
+
description: Fast-forward an intended branch to the single commit exported by a verified git bundle.
|
|
4
|
+
inputs:
|
|
5
|
+
bundle-file:
|
|
6
|
+
description: Path to the git bundle from the agent artifact.
|
|
7
|
+
required: true
|
|
8
|
+
target-branch:
|
|
9
|
+
description: Branch that must fast-forward to the bundle commit.
|
|
10
|
+
required: true
|
|
11
|
+
base-branch:
|
|
12
|
+
description: Existing branch used only when target-branch does not exist.
|
|
13
|
+
required: false
|
|
14
|
+
default: ''
|
|
15
|
+
runs:
|
|
16
|
+
using: composite
|
|
17
|
+
steps:
|
|
18
|
+
- name: Fast-forward branch from bundle
|
|
19
|
+
shell: bash
|
|
20
|
+
env:
|
|
21
|
+
BUNDLE_FILE: ${{ inputs.bundle-file }}
|
|
22
|
+
TARGET_BRANCH: ${{ inputs.target-branch }}
|
|
23
|
+
BASE_BRANCH: ${{ inputs.base-branch }}
|
|
24
|
+
run: bash "$GITHUB_ACTION_PATH/apply-bundle.sh" "$BUNDLE_FILE" "$TARGET_BRANCH" "$BASE_BRANCH"
|
|
@@ -1,42 +1,42 @@
|
|
|
1
|
-
# Managed by @plainconceptsplatform/workflows. Source: loops/actions/apply-agent-comments/action.yml. Update with workflows update --force; consumer edits may be overwritten.
|
|
2
|
-
name: Apply agent comments
|
|
3
|
-
description: Post every add_comment item from agent_output.json.
|
|
4
|
-
inputs:
|
|
5
|
-
output-file:
|
|
6
|
-
description: Path to agent_output.json.
|
|
7
|
-
required: true
|
|
8
|
-
token:
|
|
9
|
-
description: GitHub token with issues:write and pull-requests:write.
|
|
10
|
-
required: true
|
|
11
|
-
runs:
|
|
12
|
-
using: composite
|
|
13
|
-
steps:
|
|
14
|
-
- name: Post comments
|
|
15
|
-
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
|
16
|
-
env:
|
|
17
|
-
AGENT_OUTPUT_LIB: ${{ github.action_path }}/../agent-output.cjs
|
|
18
|
-
OUTPUT_FILE: ${{ inputs.output-file }}
|
|
19
|
-
with:
|
|
20
|
-
github-token: ${{ inputs.token }}
|
|
21
|
-
script: |
|
|
22
|
-
const { readAgentItems } = require(process.env.AGENT_OUTPUT_LIB);
|
|
23
|
-
const items = readAgentItems(process.env.OUTPUT_FILE, 'add_comment');
|
|
24
|
-
|
|
25
|
-
let posted = 0;
|
|
26
|
-
|
|
27
|
-
for (const item of items) {
|
|
28
|
-
if (!item.item_number) {
|
|
29
|
-
core.warning(`add_comment item has no item_number, skipping: ${JSON.stringify(item)}`);
|
|
30
|
-
continue;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
await github.rest.issues.createComment({
|
|
34
|
-
...context.repo,
|
|
35
|
-
issue_number: Number(item.item_number),
|
|
36
|
-
body: item.body,
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
posted += 1;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
core.info(`Posted ${posted} comment(s).`);
|
|
1
|
+
# Managed by @plainconceptsplatform/workflows. Source: loops/actions/apply-agent-comments/action.yml. Update with workflows update --force; consumer edits may be overwritten.
|
|
2
|
+
name: Apply agent comments
|
|
3
|
+
description: Post every add_comment item from agent_output.json.
|
|
4
|
+
inputs:
|
|
5
|
+
output-file:
|
|
6
|
+
description: Path to agent_output.json.
|
|
7
|
+
required: true
|
|
8
|
+
token:
|
|
9
|
+
description: GitHub token with issues:write and pull-requests:write.
|
|
10
|
+
required: true
|
|
11
|
+
runs:
|
|
12
|
+
using: composite
|
|
13
|
+
steps:
|
|
14
|
+
- name: Post comments
|
|
15
|
+
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
|
16
|
+
env:
|
|
17
|
+
AGENT_OUTPUT_LIB: ${{ github.action_path }}/../agent-output.cjs
|
|
18
|
+
OUTPUT_FILE: ${{ inputs.output-file }}
|
|
19
|
+
with:
|
|
20
|
+
github-token: ${{ inputs.token }}
|
|
21
|
+
script: |
|
|
22
|
+
const { readAgentItems } = require(process.env.AGENT_OUTPUT_LIB);
|
|
23
|
+
const items = readAgentItems(process.env.OUTPUT_FILE, 'add_comment');
|
|
24
|
+
|
|
25
|
+
let posted = 0;
|
|
26
|
+
|
|
27
|
+
for (const item of items) {
|
|
28
|
+
if (!item.item_number) {
|
|
29
|
+
core.warning(`add_comment item has no item_number, skipping: ${JSON.stringify(item)}`);
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
await github.rest.issues.createComment({
|
|
34
|
+
...context.repo,
|
|
35
|
+
issue_number: Number(item.item_number),
|
|
36
|
+
body: item.body,
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
posted += 1;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
core.info(`Posted ${posted} comment(s).`);
|
|
@@ -1,55 +1,55 @@
|
|
|
1
|
-
# Managed by @plainconceptsplatform/workflows. Source: loops/actions/apply-agent-labels/action.yml. Update with workflows update --force; consumer edits may be overwritten.
|
|
2
|
-
name: Apply agent labels
|
|
3
|
-
description: Apply every add_labels and remove_labels item from agent_output.json.
|
|
4
|
-
inputs:
|
|
5
|
-
output-file:
|
|
6
|
-
description: Path to agent_output.json.
|
|
7
|
-
required: true
|
|
8
|
-
token:
|
|
9
|
-
description: GitHub token with issues:write.
|
|
10
|
-
required: true
|
|
11
|
-
runs:
|
|
12
|
-
using: composite
|
|
13
|
-
steps:
|
|
14
|
-
- name: Apply label changes
|
|
15
|
-
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
|
16
|
-
env:
|
|
17
|
-
AGENT_OUTPUT_LIB: ${{ github.action_path }}/../agent-output.cjs
|
|
18
|
-
OUTPUT_FILE: ${{ inputs.output-file }}
|
|
19
|
-
with:
|
|
20
|
-
github-token: ${{ inputs.token }}
|
|
21
|
-
script: |
|
|
22
|
-
const { readAgentItems } = require(process.env.AGENT_OUTPUT_LIB);
|
|
23
|
-
const items = readAgentItems(process.env.OUTPUT_FILE)
|
|
24
|
-
.filter((item) => item.type === 'add_labels' || item.type === 'remove_labels');
|
|
25
|
-
|
|
26
|
-
let added = 0;
|
|
27
|
-
let removed = 0;
|
|
28
|
-
|
|
29
|
-
for (const item of items) {
|
|
30
|
-
const labels = (item.labels ?? []).map((label) => label.name).filter(Boolean);
|
|
31
|
-
|
|
32
|
-
if (!item.item_number || labels.length === 0) {
|
|
33
|
-
core.warning(`${item.type} item is not actionable, skipping: ${JSON.stringify(item)}`);
|
|
34
|
-
continue;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
const issue_number = Number(item.item_number);
|
|
38
|
-
|
|
39
|
-
if (item.type === 'add_labels') {
|
|
40
|
-
await github.rest.issues.addLabels({ ...context.repo, issue_number, labels });
|
|
41
|
-
added += labels.length;
|
|
42
|
-
continue;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
for (const name of labels) {
|
|
46
|
-
try {
|
|
47
|
-
await github.rest.issues.removeLabel({ ...context.repo, issue_number, name });
|
|
48
|
-
removed += 1;
|
|
49
|
-
} catch (error) {
|
|
50
|
-
if (error.status !== 404) throw error;
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
core.info(`Added ${added} label(s), removed ${removed}.`);
|
|
1
|
+
# Managed by @plainconceptsplatform/workflows. Source: loops/actions/apply-agent-labels/action.yml. Update with workflows update --force; consumer edits may be overwritten.
|
|
2
|
+
name: Apply agent labels
|
|
3
|
+
description: Apply every add_labels and remove_labels item from agent_output.json.
|
|
4
|
+
inputs:
|
|
5
|
+
output-file:
|
|
6
|
+
description: Path to agent_output.json.
|
|
7
|
+
required: true
|
|
8
|
+
token:
|
|
9
|
+
description: GitHub token with issues:write.
|
|
10
|
+
required: true
|
|
11
|
+
runs:
|
|
12
|
+
using: composite
|
|
13
|
+
steps:
|
|
14
|
+
- name: Apply label changes
|
|
15
|
+
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
|
16
|
+
env:
|
|
17
|
+
AGENT_OUTPUT_LIB: ${{ github.action_path }}/../agent-output.cjs
|
|
18
|
+
OUTPUT_FILE: ${{ inputs.output-file }}
|
|
19
|
+
with:
|
|
20
|
+
github-token: ${{ inputs.token }}
|
|
21
|
+
script: |
|
|
22
|
+
const { readAgentItems } = require(process.env.AGENT_OUTPUT_LIB);
|
|
23
|
+
const items = readAgentItems(process.env.OUTPUT_FILE)
|
|
24
|
+
.filter((item) => item.type === 'add_labels' || item.type === 'remove_labels');
|
|
25
|
+
|
|
26
|
+
let added = 0;
|
|
27
|
+
let removed = 0;
|
|
28
|
+
|
|
29
|
+
for (const item of items) {
|
|
30
|
+
const labels = (item.labels ?? []).map((label) => label.name).filter(Boolean);
|
|
31
|
+
|
|
32
|
+
if (!item.item_number || labels.length === 0) {
|
|
33
|
+
core.warning(`${item.type} item is not actionable, skipping: ${JSON.stringify(item)}`);
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const issue_number = Number(item.item_number);
|
|
38
|
+
|
|
39
|
+
if (item.type === 'add_labels') {
|
|
40
|
+
await github.rest.issues.addLabels({ ...context.repo, issue_number, labels });
|
|
41
|
+
added += labels.length;
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
for (const name of labels) {
|
|
46
|
+
try {
|
|
47
|
+
await github.rest.issues.removeLabel({ ...context.repo, issue_number, name });
|
|
48
|
+
removed += 1;
|
|
49
|
+
} catch (error) {
|
|
50
|
+
if (error.status !== 404) throw error;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
core.info(`Added ${added} label(s), removed ${removed}.`);
|