@plainconceptsplatform/workflows 0.20.2 → 0.20.3

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.
Files changed (46) hide show
  1. package/dist/index.js +0 -0
  2. package/dist/stack-defaults.js +16 -16
  3. package/dist/workflow-catalog.d.ts +1 -1
  4. package/dist/workflow-catalog.js +2 -0
  5. package/loops/actions/add-issue-labels/action.yml +50 -50
  6. package/loops/actions/agent-output.cjs +17 -17
  7. package/loops/actions/apply-agent-bundle/action.yml +24 -24
  8. package/loops/actions/apply-agent-comments/action.yml +42 -42
  9. package/loops/actions/apply-agent-labels/action.yml +55 -55
  10. package/loops/actions/apply-agent-output/action.yml +108 -108
  11. package/loops/actions/classify-route/action.yml +100 -100
  12. package/loops/actions/cleanup-artifacts/action.yml +91 -91
  13. package/loops/actions/close-agent-issues/action.yml +43 -43
  14. package/loops/actions/collect-app-errors/action.yml +297 -0
  15. package/loops/actions/collect-app-errors/group-and-redact.mjs +252 -0
  16. package/loops/actions/collect-app-errors/query-app-errors.sh +104 -0
  17. package/loops/actions/create-agent-issues/action.yml +52 -52
  18. package/loops/actions/create-issue-comment/action.yml +29 -29
  19. package/loops/actions/download-agent-output/action.yml +53 -53
  20. package/loops/actions/link-pr-to-issue/action.yml +40 -40
  21. package/loops/actions/list-open-issues/action.yml +33 -33
  22. package/loops/actions/load-issue-context/action.yml +45 -45
  23. package/loops/actions/merge-agent-pr/action.yml +49 -49
  24. package/loops/actions/push-agent-branch/action.yml +45 -45
  25. package/loops/actions/remove-issue-labels/action.yml +37 -37
  26. package/loops/actions/update-agent-issues/action.yml +58 -58
  27. package/loops/actions/validate-review-output/action.yml +35 -35
  28. package/loops/actions/validate-triage-output/action.yml +36 -36
  29. package/loops/actions/verify-app-errors/action.yml +11 -0
  30. package/loops/actions/verify-app-errors/verify-app-errors.mjs +216 -0
  31. package/loops/actions/verify-composite-actions/action.yml +9 -9
  32. package/loops/actions/verify-refine-output/action.yml +9 -9
  33. package/loops/actions/verify-route-matrix/action.yml +9 -9
  34. package/loops/actions/verify-route-matrix/verify-route-matrix.sh +88 -0
  35. package/loops/scripts/compile-agent-workflows.mjs +331 -331
  36. package/loops/templates/agentics/agentics-app-errors.yml +168 -0
  37. package/loops/templates/agentics/agentics-maintenance.yml +121 -121
  38. package/loops/templates/ci/app-ci-dotnet-next.yml +330 -330
  39. package/loops/templates/ci/app-ci-node-monorepo.yml +260 -260
  40. package/loops/templates/issues/bug_report.yml +109 -109
  41. package/loops/templates/issues/feature_request.yml +75 -75
  42. package/loops/templates/release/github-release.yml +30 -30
  43. package/loops/workflows/authorize-bot-work.yml +105 -105
  44. package/loops/workflows/shared/opencode-ci.md +206 -206
  45. package/loops/workflows/shared/platform-defaults.md +19 -19
  46. package/package.json +9 -8
@@ -0,0 +1,104 @@
1
+ #!/usr/bin/env bash
2
+ # Managed by @plainconceptsplatform/workflows. Source: loops/actions/collect-app-errors/query-app-errors.sh. Update with `workflows update --force`; consumer edits may be overwritten.
3
+ #
4
+ # Ask the Log Analytics workspace what the application threw, and write the rows to a file.
5
+ #
6
+ # Two tables, both named, and never any others. `AppServiceConsoleLogs` and
7
+ # `ContainerAppConsoleLogs` sit in this same workspace and carry raw engine stdout, which is
8
+ # not governed by the no-content rule the application's own telemetry follows. A `union *`
9
+ # here would be a privacy incident rather than a wider query.
10
+ #
11
+ # `AppExceptions` alone was not enough, and the first dry run against a real workspace is what
12
+ # said so: nought exceptions in a day, on a service that had been failing all morning. Nothing
13
+ # in these applications calls RecordException or marks an activity failed. Every failure they
14
+ # actually care about is caught in code and reported through ILogger, so it lands in
15
+ # `AppTraces` at severity Error and never reaches `AppExceptions` at all. Querying only the
16
+ # exception table would have meant a report that ran green every morning and never once saw
17
+ # the thing it was built for.
18
+ #
19
+ # Workspace table names, not the classic ones. These resources are workspace-based
20
+ # (`IngestionMode: LogAnalytics`), so the table is `AppExceptions` and its columns are
21
+ # capitalised: `ProblemId`, not `problemId`. A query written against the classic schema
22
+ # returns an error, or worse, nothing.
23
+
24
+ set -euo pipefail
25
+
26
+ WORKSPACE_ID="${1:?workspace id}"
27
+ LOOKBACK_HOURS="${2:?lookback hours}"
28
+ MIN_OCCURRENCES="${3:?minimum occurrences}"
29
+ MAX_ROWS="${4:?maximum rows}"
30
+ OUTPUT="${5:?output file}"
31
+
32
+ # `sum(ItemCount)`, never `count()`.
33
+ #
34
+ # Telemetry is sampled -- 0.3 in a pre environment -- and every row carries the number of real
35
+ # events it stands for. Counting rows under-reports by roughly the inverse of the ratio, which
36
+ # is how a problem that happened two hundred times reads as sixty and falls under a floor set
37
+ # to catch it.
38
+ # Grouped on the message TEMPLATE, not the message.
39
+ #
40
+ # "Run {RunId} failed" is one problem however many runs hit it; the rendered messages are all
41
+ # different and would group into one finding each. The template is what ILogger was given and
42
+ # what Azure Monitor keeps in OriginalFormat, so it is the closest thing traces have to the
43
+ # exception table's ProblemId. Falling back to the rendered message where it is missing costs
44
+ # some grouping and loses nothing.
45
+ read -r -d '' QUERY <<KQL || true
46
+ let window = ago(${LOOKBACK_HOURS}h);
47
+ let thrown =
48
+ AppExceptions
49
+ | where TimeGenerated > window
50
+ | extend Problem = ProblemId, Kind = ExceptionType, Stack = Details;
51
+ let logged =
52
+ AppTraces
53
+ | where TimeGenerated > window
54
+ | where SeverityLevel >= 3
55
+ | extend Problem = tostring(coalesce(Properties["OriginalFormat"], Message)),
56
+ Kind = tostring(coalesce(Properties["ExceptionType"], "LoggedError")),
57
+ Stack = dynamic([]);
58
+ union thrown, logged
59
+ | summarize Occurrences = sum(ItemCount),
60
+ Operations = dcount(OperationName),
61
+ FirstSeen = min(TimeGenerated),
62
+ LastSeen = max(TimeGenerated),
63
+ AnyDetails = any(Stack)
64
+ by ProblemId = Problem, ExceptionType = Kind, OperationName, AppRoleName
65
+ | where Occurrences >= ${MIN_OCCURRENCES}
66
+ | order by Occurrences desc
67
+ | take ${MAX_ROWS}
68
+ KQL
69
+
70
+ # An empty file rather than a missing one, so the step after this always has something to
71
+ # read and says "nothing to report" rather than failing on a path that is not there.
72
+ echo '[]' > "$OUTPUT"
73
+
74
+ # A query that will not run is a warning, not a failure.
75
+ #
76
+ # The commonest reason by far is the one grant this needs: the deploy identity can create the
77
+ # workspace and cannot read it, because creating is a control-plane right and querying is a
78
+ # data-plane one. That grant arrives with an infra apply, which is a deliberate act somebody
79
+ # does later, so between installing this and applying that the job would be red every single
80
+ # morning -- and a job that is red every morning is a job somebody switches off, taking the
81
+ # working version with it.
82
+ #
83
+ # Nothing is lost by being quiet here. There is no report to withhold and no half-written
84
+ # issue: there are no rows. The reason is on the run, in the log and in the job summary.
85
+ if ! az monitor log-analytics query \
86
+ --workspace "$WORKSPACE_ID" \
87
+ --analytics-query "$QUERY" \
88
+ --output json > "${OUTPUT}.tmp" 2> "${OUTPUT}.err"; then
89
+
90
+ # The reason, without the token the CLI sometimes prints beside it.
91
+ reason="$(sed -E 's/(Bearer|access_token|client_secret)[^ ]*/\1 [redacted]/gi' "${OUTPUT}.err" | tail -3 | tr '\n' ' ')"
92
+ rm -f "${OUTPUT}.tmp" "${OUTPUT}.err"
93
+
94
+ echo "::warning::The workspace could not be read, so nothing was collected. The identity needs Monitoring Reader on this workspace. ${reason}"
95
+ exit 0
96
+ fi
97
+
98
+ mv "${OUTPUT}.tmp" "$OUTPUT"
99
+ rm -f "${OUTPUT}.err"
100
+
101
+ # Counted here rather than in the step after, so a query that returns nothing is visible in
102
+ # the log at the point it happened instead of looking like a parsing problem later.
103
+ rows="$(python3 -c 'import json,sys; print(len(json.load(open(sys.argv[1]))))' "$OUTPUT" 2>/dev/null || echo 0)"
104
+ echo "The workspace returned ${rows} grouped exception(s) over the last ${LOOKBACK_HOURS}h."
@@ -1,52 +1,52 @@
1
- # Managed by @plainconceptsplatform/workflows. Source: loops/actions/create-agent-issues/action.yml. Update with workflows update --force; consumer edits may be overwritten.
2
- name: Create agent issues
3
- description: Create every create_issue 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
- outputs:
12
- created-count:
13
- description: Number of issues created.
14
- value: ${{ steps.create.outputs.created-count }}
15
- first-issue-number:
16
- description: Issue number of the first issue created, or empty.
17
- value: ${{ steps.create.outputs.first-issue-number }}
18
- runs:
19
- using: composite
20
- steps:
21
- - name: Create issues
22
- id: create
23
- uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
24
- env:
25
- AGENT_OUTPUT_LIB: ${{ github.action_path }}/../agent-output.cjs
26
- OUTPUT_FILE: ${{ inputs.output-file }}
27
- with:
28
- github-token: ${{ inputs.token }}
29
- script: |
30
- const { readAgentItems } = require(process.env.AGENT_OUTPUT_LIB);
31
- const items = readAgentItems(process.env.OUTPUT_FILE, 'create_issue');
32
-
33
- const created = [];
34
-
35
- for (const item of items) {
36
- if (!item.title) {
37
- core.warning(`create_issue item has no title, skipping: ${JSON.stringify(item)}`);
38
- continue;
39
- }
40
-
41
- const { data } = await github.rest.issues.create({
42
- ...context.repo,
43
- title: item.title,
44
- body: item.body ?? '',
45
- });
46
-
47
- created.push(data.number);
48
- core.info(`Created #${data.number}: ${item.title}`);
49
- }
50
-
51
- core.setOutput('created-count', String(created.length));
52
- core.setOutput('first-issue-number', created.length > 0 ? String(created[0]) : '');
1
+ # Managed by @plainconceptsplatform/workflows. Source: loops/actions/create-agent-issues/action.yml. Update with workflows update --force; consumer edits may be overwritten.
2
+ name: Create agent issues
3
+ description: Create every create_issue 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
+ outputs:
12
+ created-count:
13
+ description: Number of issues created.
14
+ value: ${{ steps.create.outputs.created-count }}
15
+ first-issue-number:
16
+ description: Issue number of the first issue created, or empty.
17
+ value: ${{ steps.create.outputs.first-issue-number }}
18
+ runs:
19
+ using: composite
20
+ steps:
21
+ - name: Create issues
22
+ id: create
23
+ uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
24
+ env:
25
+ AGENT_OUTPUT_LIB: ${{ github.action_path }}/../agent-output.cjs
26
+ OUTPUT_FILE: ${{ inputs.output-file }}
27
+ with:
28
+ github-token: ${{ inputs.token }}
29
+ script: |
30
+ const { readAgentItems } = require(process.env.AGENT_OUTPUT_LIB);
31
+ const items = readAgentItems(process.env.OUTPUT_FILE, 'create_issue');
32
+
33
+ const created = [];
34
+
35
+ for (const item of items) {
36
+ if (!item.title) {
37
+ core.warning(`create_issue item has no title, skipping: ${JSON.stringify(item)}`);
38
+ continue;
39
+ }
40
+
41
+ const { data } = await github.rest.issues.create({
42
+ ...context.repo,
43
+ title: item.title,
44
+ body: item.body ?? '',
45
+ });
46
+
47
+ created.push(data.number);
48
+ core.info(`Created #${data.number}: ${item.title}`);
49
+ }
50
+
51
+ core.setOutput('created-count', String(created.length));
52
+ core.setOutput('first-issue-number', created.length > 0 ? String(created[0]) : '');
@@ -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));