@plainconceptsplatform/workflows 1.3.1 → 1.5.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/stack-defaults.d.ts +1 -0
- package/dist/stack-defaults.js +13 -1
- package/dist/worker-env.js +2 -3
- 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 +5 -0
- 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 +64 -3
- 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 +95 -1
- 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 +5 -0
- package/loops/actions/validate-merge-gate-output/validate-merge-gate-output.sh +8 -2
- package/loops/actions/validate-refine-output/validate-refine-output.sh +30 -1
- 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 +17 -0
- package/loops/actions/verify-route-matrix/action.yml +9 -9
- package/loops/actions/verify-route-matrix/verify-route-matrix.sh +221 -7
- package/loops/docs/diagrams.md +90 -12
- package/loops/scripts/compile-agent-workflows.mjs +76 -2
- package/loops/templates/agentics/agentics-maintenance.yml +121 -121
- package/loops/templates/issues/bug_report.yml +109 -109
- package/loops/templates/issues/feature_request.yml +75 -75
- package/loops/templates/release/github-release.yml +30 -30
- package/loops/workflows/agent-implement.md +43 -8
- package/loops/workflows/agent-merge-gate.md +102 -6
- package/loops/workflows/agent-refine.md +152 -5
- package/loops/workflows/authorize-bot-work.yml +105 -105
- package/loops/workflows/shared/platform-defaults.md +23 -23
- package/loops/workflows/work-router.yml +345 -2
- package/package.json +1 -1
|
@@ -30,6 +30,8 @@ export interface CatalogInstallResult {
|
|
|
30
30
|
readonly baselines: readonly BaselineStatus[];
|
|
31
31
|
readonly upToDate: boolean;
|
|
32
32
|
readonly dryRun: boolean;
|
|
33
|
+
/** Problems the update cannot fix on its own, for a person to act on. */
|
|
34
|
+
readonly warnings: readonly string[];
|
|
33
35
|
}
|
|
34
36
|
export interface CatalogInstallOptions {
|
|
35
37
|
/** Also overwrite files whose ownership header was removed, and changed templates. */
|
|
@@ -7,7 +7,7 @@ import { promisify } from "node:util";
|
|
|
7
7
|
import { parse as parseYaml } from "yaml";
|
|
8
8
|
import { catalogTemplates, mandatoryFiles, retiredWorkflowFiles, routeNames, templateNames, workflowRoutes } from "./workflow-catalog.js";
|
|
9
9
|
import { processRoutes, excludedWorkerFiles } from "./route-processing.js";
|
|
10
|
-
import { generateOpencodeCi, generateOpencodeConfig, generateStackDefaults, injectStackEnv } from "./stack-defaults.js";
|
|
10
|
+
import { generateOpencodeCi, generateOpencodeConfig, generateStackDefaults, injectStackEnv, shippedVerifyDefaults } from "./stack-defaults.js";
|
|
11
11
|
import { mergeRouter, mergeWorker } from "./worker-env.js";
|
|
12
12
|
import { fetchBaseline, hasOwnershipHeader, installedVersion, packageVersion, stampVersion } from "./package-baseline.js";
|
|
13
13
|
const execFileAsync = promisify(execFile);
|
|
@@ -133,6 +133,7 @@ export async function installCatalog(repositoryPath, options = {}) {
|
|
|
133
133
|
baselines,
|
|
134
134
|
upToDate: updates.length === 0 && removals.length === 0,
|
|
135
135
|
dryRun: options.dryRun ?? false,
|
|
136
|
+
warnings: await verifyScriptWarnings(repositoryPath, updates, existing),
|
|
136
137
|
};
|
|
137
138
|
if (options.dryRun)
|
|
138
139
|
return result;
|
|
@@ -158,12 +159,22 @@ export async function installCatalog(repositoryPath, options = {}) {
|
|
|
158
159
|
// the empty string as the consumer's deliberate choice. All four consuming repositories were in
|
|
159
160
|
// that state, so every merge-gate repair pushed a fix with the verification block interpolating
|
|
160
161
|
// to nothing. An empty value is the absence of a choice, so an update fills it.
|
|
162
|
+
//
|
|
163
|
+
// So is a value the package wrote itself. The implement worker shipped a dotnet-only line, and
|
|
164
|
+
// every full-stack consumer kept it as if someone had chosen it, so the bot never built the web
|
|
165
|
+
// app before opening a pull request. A consumer holding a shipped default gets the current one:
|
|
166
|
+
// its own value is blanked here, which the env merge then reads as no choice.
|
|
161
167
|
function applyStackDefaults(files, inspection, existing) {
|
|
162
168
|
const defaults = generateStackDefaults(inspection);
|
|
163
169
|
const result = new Map(files);
|
|
164
170
|
for (const [target, content] of result) {
|
|
165
|
-
|
|
171
|
+
const current = existing.get(target);
|
|
172
|
+
if (isWorker(target) && (current === undefined || hasEmptyVerifyCommands(current))) {
|
|
173
|
+
result.set(target, injectStackEnv(content, defaults));
|
|
174
|
+
}
|
|
175
|
+
else if (isWorker(target) && hasShippedVerifyCommands(current, defaults.verifyCommands)) {
|
|
166
176
|
result.set(target, injectStackEnv(content, defaults));
|
|
177
|
+
existing.set(target, current.replace(VERIFY_LINE, ' VERIFY_COMMANDS: ""'));
|
|
167
178
|
}
|
|
168
179
|
else if (target.endsWith("opencode-ci.md")) {
|
|
169
180
|
result.set(target, generateOpencodeCi(content, inspection));
|
|
@@ -174,11 +185,42 @@ function applyStackDefaults(files, inspection, existing) {
|
|
|
174
185
|
}
|
|
175
186
|
return result;
|
|
176
187
|
}
|
|
188
|
+
const VERIFY_LINE = /^ {2}VERIFY_COMMANDS: *(.*?) *$/m;
|
|
177
189
|
// A worker whose VERIFY_COMMANDS is present but empty. Anything else, including a value the
|
|
178
190
|
// consumer wrote, is left alone.
|
|
179
191
|
function hasEmptyVerifyCommands(current) {
|
|
180
192
|
return typeof current === "string" && /^ {2}VERIFY_COMMANDS: *(""|'')? *$/m.test(current);
|
|
181
193
|
}
|
|
194
|
+
function verifyCommandsOf(content) {
|
|
195
|
+
const raw = VERIFY_LINE.exec(content)?.[1];
|
|
196
|
+
return raw?.replace(/^(["'])(.*)\1$/, "$2");
|
|
197
|
+
}
|
|
198
|
+
function hasShippedVerifyCommands(current, replacement) {
|
|
199
|
+
if (current === undefined)
|
|
200
|
+
return false;
|
|
201
|
+
const value = verifyCommandsOf(current);
|
|
202
|
+
return value !== undefined && value !== replacement && shippedVerifyDefaults.has(value);
|
|
203
|
+
}
|
|
204
|
+
// `pnpm verify` is only a command if the repository defines it. The update still writes it, since
|
|
205
|
+
// it is the right default, and says what is missing instead of leaving the bot to find out.
|
|
206
|
+
async function verifyScriptWarnings(repositoryPath, updates, existing) {
|
|
207
|
+
const written = new Map(existing);
|
|
208
|
+
for (const update of updates)
|
|
209
|
+
written.set(update.target, update.content);
|
|
210
|
+
const workers = [...written].filter(([target, content]) => isWorker(target) && /\bpnpm verify\b/.test(verifyCommandsOf(content) ?? ""));
|
|
211
|
+
if (workers.length === 0)
|
|
212
|
+
return [];
|
|
213
|
+
let scripts = {};
|
|
214
|
+
try {
|
|
215
|
+
scripts = JSON.parse(await readFile(join(repositoryPath, "package.json"), "utf8")).scripts ?? {};
|
|
216
|
+
}
|
|
217
|
+
catch {
|
|
218
|
+
scripts = {};
|
|
219
|
+
}
|
|
220
|
+
if (typeof scripts.verify === "string")
|
|
221
|
+
return [];
|
|
222
|
+
return [`VERIFY_COMMANDS runs \`pnpm verify\` in ${workers.map(([target]) => target).sort().join(", ")}, but package.json has no "verify" script. Add one that runs what CI blocks on.`];
|
|
223
|
+
}
|
|
182
224
|
// Directories that belong wholly to the package. A file here that carries our ownership header
|
|
183
225
|
// and is no longer in the package was deleted upstream, and without this it would sit in every
|
|
184
226
|
// consumer forever: that is how `stale-recovery` and `update-changelog` outlived the code that
|
package/dist/index.js
CHANGED
|
@@ -139,6 +139,8 @@ export async function run(arguments_, repositoryPath = process.cwd()) {
|
|
|
139
139
|
console.error(`Template conflicts found. Re-run with --force to overwrite consumer-owned copies:\n${allConflicts.join("\n")}`);
|
|
140
140
|
return 1;
|
|
141
141
|
}
|
|
142
|
+
for (const warning of catalog?.warnings ?? [])
|
|
143
|
+
console.error(`warning: ${warning}`);
|
|
142
144
|
console.log(JSON.stringify({
|
|
143
145
|
command,
|
|
144
146
|
dryRun,
|
|
@@ -177,6 +179,7 @@ function summarize(result) {
|
|
|
177
179
|
baselines: result.baselines,
|
|
178
180
|
changes: result.changes.filter((change) => change.status !== "unchanged"),
|
|
179
181
|
unchanged: result.changes.filter((change) => change.status === "unchanged").length,
|
|
182
|
+
...(result.warnings.length > 0 ? { warnings: result.warnings } : {}),
|
|
180
183
|
};
|
|
181
184
|
}
|
|
182
185
|
// A fixed baseline for every recorded version, instead of asking npm. Rolling out a version that
|
package/dist/stack-defaults.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ export interface StackDefaults {
|
|
|
6
6
|
readonly hasNodeOnly: boolean;
|
|
7
7
|
}
|
|
8
8
|
export declare function generateStackDefaults(inspection: RepositoryInspection): StackDefaults;
|
|
9
|
+
export declare const shippedVerifyDefaults: ReadonlySet<string>;
|
|
9
10
|
export declare function injectStackEnv(content: string, defaults: StackDefaults): string;
|
|
10
11
|
export declare function generateOpencodeCi(baseContent: string, inspection: RepositoryInspection): string;
|
|
11
12
|
export declare function generateOpencodeConfig(baseContent: string, inspection: RepositoryInspection): string;
|
package/dist/stack-defaults.js
CHANGED
|
@@ -4,8 +4,12 @@ export function generateStackDefaults(inspection) {
|
|
|
4
4
|
const hasNodeOnly = hasNode && !hasDotnet;
|
|
5
5
|
let verifyCommands;
|
|
6
6
|
let repoRulesBase;
|
|
7
|
+
// A full-stack repository verifies with its own `pnpm verify`, which runs what its CI blocks on.
|
|
8
|
+
// The command this replaced was prose the agent had to interpret, and the implement worker never
|
|
9
|
+
// got it at all: it kept the package's dotnet-only line, so bot pull requests shipped with the
|
|
10
|
+
// web build broken (Pliny-Bot #639).
|
|
7
11
|
if (hasDotnet && hasNode) {
|
|
8
|
-
verifyCommands = "
|
|
12
|
+
verifyCommands = "pnpm verify";
|
|
9
13
|
repoRulesBase = "Full-stack .NET + React/Next.js repository. Follow Clean Architecture layering: API → Application → Domain. Infrastructure implements Application ports. Do not reference EF Core or ASP.NET from Application. Frontend communicates exclusively via HTTP endpoints. Run both .NET and frontend verification.";
|
|
10
14
|
}
|
|
11
15
|
else if (hasDotnet) {
|
|
@@ -18,6 +22,14 @@ export function generateStackDefaults(inspection) {
|
|
|
18
22
|
}
|
|
19
23
|
return { verifyCommands, repoRulesBase, hasDotnet, hasNodeOnly };
|
|
20
24
|
}
|
|
25
|
+
// Every VERIFY_COMMANDS value the package itself has ever written. A consumer holding one of these
|
|
26
|
+
// never chose it, so an update may replace it with the current default for the stack.
|
|
27
|
+
export const shippedVerifyDefaults = new Set([
|
|
28
|
+
".NET: dotnet restore && dotnet build -c Release && dotnet test | Web: pnpm lint && pnpm test && pnpm build",
|
|
29
|
+
"dotnet restore && dotnet build -c Release --no-restore && dotnet test",
|
|
30
|
+
"dotnet restore && dotnet build -c Release --no-restore && dotnet test -c Release --no-build",
|
|
31
|
+
"pnpm verify",
|
|
32
|
+
]);
|
|
21
33
|
// Only a worker that prints a verification block declares VERIFY_COMMANDS. Adding the key to
|
|
22
34
|
// the others made byte-identical workers read as changed on every update, so a worker without
|
|
23
35
|
// the key is left without it.
|
package/dist/worker-env.js
CHANGED
|
@@ -139,9 +139,8 @@ function engineEndpoint(content) {
|
|
|
139
139
|
// triage, refine, implement, apply-review and audit on RunnerLandingZone while its merge-gate
|
|
140
140
|
// and release stayed on agents-arc -- the pool was applied to the workers installed at the time
|
|
141
141
|
// and never to the ones added later, and nothing reported the split. The pool is package-owned
|
|
142
|
-
// now:
|
|
143
|
-
//
|
|
144
|
-
// cannot drift back without a red run. Per the standing rule for this package, anything a
|
|
142
|
+
// now: every job, router and release included, belongs on the Azure fleet (agents-arc, runner
|
|
143
|
+
// group `agentic`). The route matrix asserts it, so a repo cannot drift back without a red run. Per the standing rule for this package, anything a
|
|
145
144
|
// consumer really must vary belongs in `env:` at the top of the file, not in `runs-on`.
|
|
146
145
|
// GitHub evaluates no expression in a `workflow_run.workflows:` list or in a `cron:`, so the two
|
|
147
146
|
// router values that are also needed there cannot be read from `env:` at those two lines. The
|
|
@@ -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}.`);
|
|
@@ -39,6 +39,10 @@ inputs:
|
|
|
39
39
|
description: Issue an update_issue item targets when it names none.
|
|
40
40
|
required: false
|
|
41
41
|
default: ''
|
|
42
|
+
parent-issue:
|
|
43
|
+
description: The split parent; see create-agent-issues. Empty for anything but a split.
|
|
44
|
+
required: false
|
|
45
|
+
default: ''
|
|
42
46
|
outputs:
|
|
43
47
|
item-count:
|
|
44
48
|
description: Number of items the agent produced.
|
|
@@ -92,6 +96,7 @@ runs:
|
|
|
92
96
|
with:
|
|
93
97
|
output-file: ${{ steps.output.outputs.output-file }}
|
|
94
98
|
token: ${{ inputs.token }}
|
|
99
|
+
parent-issue: ${{ inputs.parent-issue }}
|
|
95
100
|
|
|
96
101
|
- name: Post agent comments
|
|
97
102
|
if: steps.output.outputs.item-count != '0'
|