From c18c4803c5f898e9b579a48e494db001803a1a07 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sun, 19 Apr 2026 19:01:23 +0000
Subject: [PATCH 01/14] feat: add maintenance activity report operation
Agent-Logs-Url: https://github.com/github/gh-aw/sessions/267bf5c1-a299-43c5-be20-17cdb0ab2a0c
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
---
.github/workflows/agentics-maintenance.yml | 54 +++++++-
actions/setup/js/run_activity_report.cjs | 129 ++++++++++++++++++
actions/setup/js/run_activity_report.test.cjs | 115 ++++++++++++++++
pkg/workflow/maintenance_workflow_test.go | 40 ++++--
pkg/workflow/maintenance_workflow_yaml.go | 53 ++++++-
pkg/workflow/side_repo_maintenance.go | 50 ++++++-
.../side_repo_maintenance_integration_test.go | 4 +
7 files changed, 431 insertions(+), 14 deletions(-)
create mode 100644 actions/setup/js/run_activity_report.cjs
create mode 100644 actions/setup/js/run_activity_report.test.cjs
diff --git a/.github/workflows/agentics-maintenance.yml b/.github/workflows/agentics-maintenance.yml
index 59d99c41a74..1d63f82e62b 100644
--- a/.github/workflows/agentics-maintenance.yml
+++ b/.github/workflows/agentics-maintenance.yml
@@ -50,6 +50,7 @@ on:
- 'upgrade'
- 'safe_outputs'
- 'create_labels'
+ - 'activity_report'
- 'close_agentic_workflows_issues'
- 'clean_cache_memories'
- 'validate'
@@ -61,7 +62,7 @@ on:
workflow_call:
inputs:
operation:
- description: 'Optional maintenance operation to run (disable, enable, update, upgrade, safe_outputs, create_labels, close_agentic_workflows_issues, clean_cache_memories, validate)'
+ description: 'Optional maintenance operation to run (disable, enable, update, upgrade, safe_outputs, create_labels, activity_report, close_agentic_workflows_issues, clean_cache_memories, validate)'
required: false
type: string
default: ''
@@ -156,7 +157,7 @@ jobs:
await main();
run_operation:
- if: ${{ (github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call') && inputs.operation != '' && inputs.operation != 'safe_outputs' && inputs.operation != 'create_labels' && inputs.operation != 'close_agentic_workflows_issues' && inputs.operation != 'clean_cache_memories' && inputs.operation != 'validate' && (!(github.event.repository.fork)) }}
+ if: ${{ (github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call') && inputs.operation != '' && inputs.operation != 'safe_outputs' && inputs.operation != 'create_labels' && inputs.operation != 'activity_report' && inputs.operation != 'close_agentic_workflows_issues' && inputs.operation != 'clean_cache_memories' && inputs.operation != 'validate' && (!(github.event.repository.fork)) }}
runs-on: ubuntu-slim
permissions:
actions: write
@@ -311,6 +312,55 @@ jobs:
const { main } = require('${{ runner.temp }}/gh-aw/actions/create_labels.cjs');
await main();
+ activity_report:
+ if: ${{ (github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call') && inputs.operation == 'activity_report' && (!(github.event.repository.fork)) }}
+ runs-on: ubuntu-slim
+ permissions:
+ actions: read
+ issues: write
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
+ with:
+ persist-credentials: false
+
+ - name: Setup Scripts
+ uses: ./actions/setup
+ with:
+ destination: ${{ runner.temp }}/gh-aw/actions
+
+ - name: Check admin/maintainer permissions
+ uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9
+ with:
+ github-token: ${{ secrets.GITHUB_TOKEN }}
+ script: |
+ const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
+ setupGlobals(core, github, context, exec, io, getOctokit);
+ const { main } = require('${{ runner.temp }}/gh-aw/actions/check_team_member.cjs');
+ await main();
+
+ - name: Setup Go
+ uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
+ with:
+ go-version-file: go.mod
+ cache: true
+
+ - name: Build gh-aw
+ run: make build
+
+ - name: Generate agentic workflow activity report
+ uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9
+ env:
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ GH_AW_CMD_PREFIX: ./gh-aw
+ with:
+ github-token: ${{ secrets.GITHUB_TOKEN }}
+ script: |
+ const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
+ setupGlobals(core, github, context, exec, io, getOctokit);
+ const { main } = require('${{ runner.temp }}/gh-aw/actions/run_activity_report.cjs');
+ await main();
+
close_agentic_workflows_issues:
if: ${{ (github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call') && inputs.operation == 'close_agentic_workflows_issues' && (!(github.event.repository.fork)) }}
runs-on: ubuntu-slim
diff --git a/actions/setup/js/run_activity_report.cjs b/actions/setup/js/run_activity_report.cjs
new file mode 100644
index 00000000000..85c4ea15639
--- /dev/null
+++ b/actions/setup/js/run_activity_report.cjs
@@ -0,0 +1,129 @@
+// @ts-check
+///
+
+const { getErrorMessage, isRateLimitError } = require("./error_helpers.cjs");
+const { resolveExecutionOwnerRepo } = require("./repo_helpers.cjs");
+const { sanitizeContent } = require("./sanitize_content.cjs");
+
+const ISSUE_TITLE = "[AW activity report]";
+
+/** @typedef {{ key: string, heading: string, startDate: string, optionalOnRateLimit: boolean }} ActivityRange */
+
+/** @type {ActivityRange[]} */
+const REPORT_RANGES = [
+ { key: "24h", heading: "Last 24 hours", startDate: "-1d", optionalOnRateLimit: false },
+ { key: "7d", heading: "Last 7 days", startDate: "-1w", optionalOnRateLimit: false },
+ { key: "30d", heading: "Last 30 days", startDate: "-1mo", optionalOnRateLimit: true },
+];
+
+/**
+ * @param {string} text
+ * @returns {boolean}
+ */
+function hasRateLimitText(text) {
+ return /\bapi rate limit\b|\brate limit exceeded\b|\bsecondary rate limit\b|\b429\b/i.test(text);
+}
+
+/**
+ * Run the logs command for a configured report range.
+ *
+ * @param {string} bin
+ * @param {string[]} prefixArgs
+ * @param {string} repoSlug
+ * @param {ActivityRange} range
+ * @returns {Promise<{ heading: string, body: string }>}
+ */
+async function runRangeReport(bin, prefixArgs, repoSlug, range) {
+ const args = [...prefixArgs, "logs", "--repo", repoSlug, "--start-date", range.startDate, "--format", "markdown"];
+ core.info(`Running: ${bin} ${args.join(" ")}`);
+
+ try {
+ const result = await exec.getExecOutput(bin, args, { ignoreReturnCode: true });
+ const output = `${result.stdout || ""}\n${result.stderr || ""}`.trim();
+ const rateLimited = hasRateLimitText(output);
+
+ if (result.exitCode === 0 && result.stdout.trim()) {
+ return {
+ heading: range.heading,
+ body: sanitizeContent(result.stdout.trim()),
+ };
+ }
+
+ if (rateLimited && range.optionalOnRateLimit) {
+ core.warning(`Skipping ${range.heading} report due to GitHub API rate limiting`);
+ return {
+ heading: range.heading,
+ body: "_Skipped due to GitHub API rate limiting._",
+ };
+ }
+
+ if (rateLimited) {
+ return {
+ heading: range.heading,
+ body: "_Could not generate this section due to GitHub API rate limiting._",
+ };
+ }
+
+ return {
+ heading: range.heading,
+ body: `_Report command failed (exit code ${result.exitCode})._\n\n\`\`\`\n${sanitizeContent(output || "No command output was captured.")}\n\`\`\``,
+ };
+ } catch (error) {
+ const errorMessage = getErrorMessage(error);
+ const rateLimited = isRateLimitError(error) || hasRateLimitText(errorMessage);
+
+ if (rateLimited && range.optionalOnRateLimit) {
+ core.warning(`Skipping ${range.heading} report due to GitHub API rate limiting`);
+ return {
+ heading: range.heading,
+ body: "_Skipped due to GitHub API rate limiting._",
+ };
+ }
+
+ if (rateLimited) {
+ return {
+ heading: range.heading,
+ body: "_Could not generate this section due to GitHub API rate limiting._",
+ };
+ }
+
+ return {
+ heading: range.heading,
+ body: `_Report command failed: ${sanitizeContent(errorMessage)}_`,
+ };
+ }
+}
+
+/**
+ * Generate an agentic workflow activity report issue.
+ * @returns {Promise}
+ */
+async function main() {
+ const cmdPrefixStr = process.env.GH_AW_CMD_PREFIX || "gh aw";
+ const [bin, ...prefixArgs] = cmdPrefixStr.split(" ").filter(Boolean);
+ const { owner, repo } = resolveExecutionOwnerRepo();
+ const repoSlug = `${owner}/${repo}`;
+
+ core.info(`Generating agentic workflow activity report for ${repoSlug}`);
+
+ const sections = [];
+ for (const range of REPORT_RANGES) {
+ sections.push(await runRangeReport(bin, prefixArgs, repoSlug, range));
+ }
+
+ const body = ["## Agentic workflow activity report", "", `Repository: \`${repoSlug}\``, `Generated at: ${new Date().toISOString()}`, "", ...sections.flatMap(section => ["---", "", `## ${section.heading}`, "", section.body, ""])].join(
+ "\n"
+ );
+
+ const createdIssue = await github.rest.issues.create({
+ owner,
+ repo,
+ title: ISSUE_TITLE,
+ body,
+ labels: ["agentic-workflows"],
+ });
+
+ core.info(`Created issue #${createdIssue.data.number}: ${createdIssue.data.html_url}`);
+}
+
+module.exports = { main, hasRateLimitText, runRangeReport };
diff --git a/actions/setup/js/run_activity_report.test.cjs b/actions/setup/js/run_activity_report.test.cjs
new file mode 100644
index 00000000000..2514e40161e
--- /dev/null
+++ b/actions/setup/js/run_activity_report.test.cjs
@@ -0,0 +1,115 @@
+// @ts-check
+import { describe, it, expect, beforeEach, afterEach, vi } from "vitest";
+
+describe("run_activity_report", () => {
+ let originalGlobals;
+ let originalEnv;
+ let mockCore;
+ let mockGithub;
+ let mockContext;
+ let mockExec;
+
+ beforeEach(() => {
+ originalEnv = { ...process.env };
+ process.env.GH_AW_CMD_PREFIX = "gh aw";
+
+ originalGlobals = {
+ core: global.core,
+ github: global.github,
+ context: global.context,
+ exec: global.exec,
+ };
+
+ mockCore = {
+ info: vi.fn(),
+ warning: vi.fn(),
+ };
+ mockGithub = {
+ rest: {
+ issues: {
+ create: vi.fn().mockResolvedValue({
+ data: { number: 42, html_url: "https://github.com/testowner/testrepo/issues/42" },
+ }),
+ },
+ },
+ };
+ mockContext = {
+ repo: {
+ owner: "testowner",
+ repo: "testrepo",
+ },
+ };
+ mockExec = {
+ getExecOutput: vi.fn(),
+ };
+
+ global.core = mockCore;
+ global.github = mockGithub;
+ global.context = mockContext;
+ global.exec = mockExec;
+ });
+
+ afterEach(() => {
+ process.env = originalEnv;
+ global.core = originalGlobals.core;
+ global.github = originalGlobals.github;
+ global.context = originalGlobals.context;
+ global.exec = originalGlobals.exec;
+ vi.clearAllMocks();
+ });
+
+ it("creates an activity report issue with all three time ranges", async () => {
+ mockExec.getExecOutput
+ .mockResolvedValueOnce({ stdout: "## 24h report\nok", stderr: "", exitCode: 0 })
+ .mockResolvedValueOnce({ stdout: "## 7d report\nok", stderr: "", exitCode: 0 })
+ .mockResolvedValueOnce({ stdout: "## 30d report\nok", stderr: "", exitCode: 0 });
+
+ const { main } = await import("./run_activity_report.cjs");
+ await main();
+
+ expect(mockExec.getExecOutput).toHaveBeenCalledTimes(3);
+ expect(mockExec.getExecOutput).toHaveBeenNthCalledWith(1, "gh", expect.arrayContaining(["aw", "logs", "--repo", "testowner/testrepo", "--start-date", "-1d", "--format", "markdown"]), expect.objectContaining({ ignoreReturnCode: true }));
+ expect(mockExec.getExecOutput).toHaveBeenNthCalledWith(2, "gh", expect.arrayContaining(["aw", "logs", "--repo", "testowner/testrepo", "--start-date", "-1w", "--format", "markdown"]), expect.objectContaining({ ignoreReturnCode: true }));
+ expect(mockExec.getExecOutput).toHaveBeenNthCalledWith(
+ 3,
+ "gh",
+ expect.arrayContaining(["aw", "logs", "--repo", "testowner/testrepo", "--start-date", "-1mo", "--format", "markdown"]),
+ expect.objectContaining({ ignoreReturnCode: true })
+ );
+
+ expect(mockGithub.rest.issues.create).toHaveBeenCalledWith(
+ expect.objectContaining({
+ owner: "testowner",
+ repo: "testrepo",
+ title: "[AW activity report]",
+ labels: ["agentic-workflows"],
+ })
+ );
+
+ const issueBody = mockGithub.rest.issues.create.mock.calls[0][0].body;
+ expect(issueBody).toContain("## Last 24 hours");
+ expect(issueBody).toContain("## Last 7 days");
+ expect(issueBody).toContain("## Last 30 days");
+ });
+
+ it("skips the 30-day query when rate limited", async () => {
+ mockExec.getExecOutput
+ .mockResolvedValueOnce({ stdout: "24h", stderr: "", exitCode: 0 })
+ .mockResolvedValueOnce({ stdout: "7d", stderr: "", exitCode: 0 })
+ .mockResolvedValueOnce({ stdout: "", stderr: "API rate limit exceeded", exitCode: 1 });
+
+ const { main } = await import("./run_activity_report.cjs");
+ await main();
+
+ expect(mockCore.warning).toHaveBeenCalledWith(expect.stringContaining("Skipping Last 30 days report"));
+ const issueBody = mockGithub.rest.issues.create.mock.calls[0][0].body;
+ expect(issueBody).toContain("Skipped due to GitHub API rate limiting.");
+ });
+
+ it("detects rate limit text helper", async () => {
+ const { hasRateLimitText } = await import("./run_activity_report.cjs");
+ expect(hasRateLimitText("API rate limit exceeded")).toBe(true);
+ expect(hasRateLimitText("secondary rate limit")).toBe(true);
+ expect(hasRateLimitText("normal output")).toBe(false);
+ });
+});
diff --git a/pkg/workflow/maintenance_workflow_test.go b/pkg/workflow/maintenance_workflow_test.go
index 985d9b5a813..fcdcb1a60d5 100644
--- a/pkg/workflow/maintenance_workflow_test.go
+++ b/pkg/workflow/maintenance_workflow_test.go
@@ -282,9 +282,10 @@ func TestGenerateMaintenanceWorkflow_OperationJobConditions(t *testing.T) {
yaml := string(content)
operationSkipCondition := `github.event_name != 'workflow_dispatch' && github.event_name != 'workflow_call' || inputs.operation == ''`
- operationRunCondition := `(github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call') && inputs.operation != '' && inputs.operation != 'safe_outputs' && inputs.operation != 'create_labels' && inputs.operation != 'close_agentic_workflows_issues' && inputs.operation != 'clean_cache_memories' && inputs.operation != 'validate'`
+ operationRunCondition := `(github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call') && inputs.operation != '' && inputs.operation != 'safe_outputs' && inputs.operation != 'create_labels' && inputs.operation != 'activity_report' && inputs.operation != 'close_agentic_workflows_issues' && inputs.operation != 'clean_cache_memories' && inputs.operation != 'validate'`
applySafeOutputsCondition := `(github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call') && inputs.operation == 'safe_outputs'`
createLabelsCondition := `(github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call') && inputs.operation == 'create_labels'`
+ activityReportCondition := `(github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call') && inputs.operation == 'activity_report'`
closeAgenticWorkflowIssuesCondition := `(github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call') && inputs.operation == 'close_agentic_workflows_issues'`
cleanCacheMemoriesCondition := `github.event_name != 'workflow_dispatch' && github.event_name != 'workflow_call' || inputs.operation == '' || inputs.operation == 'clean_cache_memories'`
@@ -367,6 +368,17 @@ func TestGenerateMaintenanceWorkflow_OperationJobConditions(t *testing.T) {
}
}
+ // activity_report job should be triggered when operation == 'activity_report'
+ activityReportIdx := strings.Index(yaml, "\n activity_report:")
+ if activityReportIdx == -1 {
+ t.Errorf("Job activity_report not found in generated workflow")
+ } else {
+ activityReportSection := yaml[activityReportIdx : activityReportIdx+runOpSectionSearchRange]
+ if !strings.Contains(activityReportSection, activityReportCondition) {
+ t.Errorf("Job activity_report should have the activation condition %q in:\n%s", activityReportCondition, activityReportSection)
+ }
+ }
+
// close_agentic_workflows_issues job should be triggered when operation == 'close_agentic_workflows_issues'
closeAgenticWorkflowIssuesIdx := strings.Index(yaml, "\n close_agentic_workflows_issues:")
if closeAgenticWorkflowIssuesIdx == -1 {
@@ -398,6 +410,11 @@ func TestGenerateMaintenanceWorkflow_OperationJobConditions(t *testing.T) {
t.Error("workflow_dispatch operation choices should include 'validate'")
}
+ // Verify activity_report is an option in the operation choices
+ if !strings.Contains(yaml, "- 'activity_report'") {
+ t.Error("workflow_dispatch operation choices should include 'activity_report'")
+ }
+
// Verify close_agentic_workflows_issues is an option in the operation choices
if !strings.Contains(yaml, "- 'close_agentic_workflows_issues'") {
t.Error("workflow_dispatch operation choices should include 'close_agentic_workflows_issues'")
@@ -430,9 +447,10 @@ func TestGenerateMaintenanceWorkflow_OperationJobConditions(t *testing.T) {
// Verify run_operation job exposes outputs
runOpIdx2 := strings.Index(yaml, "\n run_operation:")
if runOpIdx2 != -1 {
- runOpSection2 := yaml[runOpIdx2 : runOpIdx2+600]
+ runOpEnd := min(runOpIdx2+1200, len(yaml))
+ runOpSection2 := yaml[runOpIdx2:runOpEnd]
if !strings.Contains(runOpSection2, "outputs:\n operation: ${{ steps.record.outputs.operation }}") {
- t.Errorf("run_operation job should declare operation output, got:\n%s", runOpSection2[:300])
+ t.Errorf("run_operation job should declare operation output, got:\n%s", runOpSection2[:min(300, len(runOpSection2))])
}
}
@@ -678,12 +696,12 @@ func TestGenerateMaintenanceWorkflow_RunOperationCLICodegen(t *testing.T) {
t.Fatalf("Expected maintenance workflow to be generated: %v", err)
}
yaml := string(content)
- // run_operation, create_labels, validate_workflows, and compile_workflows should use the same setup-go version
- // (all use getActionPin, not hardcoded pins). Exactly 4 occurrences expected.
+ // run_operation, create_labels, activity_report, validate_workflows, and compile_workflows should use the same setup-go version
+ // (all use getActionPin, not hardcoded pins). Exactly 5 occurrences expected.
setupGoPin := getActionPin("actions/setup-go")
occurrences := strings.Count(yaml, setupGoPin)
- if occurrences != 4 {
- t.Errorf("Expected exactly 4 occurrences of pinned setup-go ref %q (run_operation + create_labels + validate_workflows + compile_workflows), got %d in:\n%s",
+ if occurrences != 5 {
+ t.Errorf("Expected exactly 5 occurrences of pinned setup-go ref %q (run_operation + create_labels + activity_report + validate_workflows + compile_workflows), got %d in:\n%s",
setupGoPin, occurrences, yaml)
}
})
@@ -1143,6 +1161,9 @@ func TestGenerateSideRepoMaintenanceWorkflow(t *testing.T) {
if !strings.Contains(contentStr, "create_labels") {
t.Errorf("Side-repo maintenance should include create_labels job, got content length %d", len(contentStr))
}
+ if !strings.Contains(contentStr, "activity_report") {
+ t.Errorf("Side-repo maintenance should include activity_report job, got content length %d", len(contentStr))
+ }
})
t.Run("no side-repo file generated when no current checkout", func(t *testing.T) {
@@ -1172,7 +1193,7 @@ func TestGenerateSideRepoMaintenanceWorkflow(t *testing.T) {
}
})
- t.Run("side-repo generated without expires uses safe_outputs and create_labels only", func(t *testing.T) {
+ t.Run("side-repo generated without expires uses safe_outputs, create_labels, and activity_report", func(t *testing.T) {
tmpDir := t.TempDir()
workflowDataList := []*WorkflowData{
{
@@ -1213,6 +1234,9 @@ func TestGenerateSideRepoMaintenanceWorkflow(t *testing.T) {
if strings.Contains(contentStr, "close-expired-entities") {
t.Errorf("Side-repo maintenance should NOT include close-expired-entities when no expires, got content length %d", len(contentStr))
}
+ if !strings.Contains(contentStr, "activity_report") {
+ t.Errorf("Side-repo maintenance should include activity_report when no expires, got content length %d", len(contentStr))
+ }
})
t.Run("expression-based repository does not generate side-repo maintenance", func(t *testing.T) {
diff --git a/pkg/workflow/maintenance_workflow_yaml.go b/pkg/workflow/maintenance_workflow_yaml.go
index 0415c3de54f..d80023fb915 100644
--- a/pkg/workflow/maintenance_workflow_yaml.go
+++ b/pkg/workflow/maintenance_workflow_yaml.go
@@ -59,6 +59,7 @@ on:
- 'upgrade'
- 'safe_outputs'
- 'create_labels'
+ - 'activity_report'
- 'close_agentic_workflows_issues'
- 'clean_cache_memories'
- 'validate'
@@ -70,7 +71,7 @@ on:
workflow_call:
inputs:
operation:
- description: 'Optional maintenance operation to run (disable, enable, update, upgrade, safe_outputs, create_labels, close_agentic_workflows_issues, clean_cache_memories, validate)'
+ description: 'Optional maintenance operation to run (disable, enable, update, upgrade, safe_outputs, create_labels, activity_report, close_agentic_workflows_issues, clean_cache_memories, validate)'
required: false
type: string
default: ''
@@ -195,8 +196,8 @@ jobs:
`)
// Add unified run_operation job for all dispatch operations except those with dedicated jobs
- // (safe_outputs, create_labels, close_agentic_workflows_issues, clean_cache_memories, validate)
- runOperationCondition := buildRunOperationCondition("safe_outputs", "create_labels", "close_agentic_workflows_issues", "clean_cache_memories", "validate")
+ // (safe_outputs, create_labels, activity_report, close_agentic_workflows_issues, clean_cache_memories, validate)
+ runOperationCondition := buildRunOperationCondition("safe_outputs", "create_labels", "activity_report", "close_agentic_workflows_issues", "clean_cache_memories", "validate")
yaml.WriteString(`
run_operation:
if: ${{ ` + RenderCondition(runOperationCondition) + ` }}
@@ -349,6 +350,52 @@ jobs:
await main();
`)
+ // Add activity_report job for workflow_dispatch with operation == 'activity_report'
+ yaml.WriteString(`
+ activity_report:
+ if: ${{ ` + RenderCondition(buildDispatchOperationCondition("activity_report")) + ` }}
+ runs-on: ` + runsOnValue + `
+ permissions:
+ actions: read
+ issues: write
+ steps:
+ - name: Checkout repository
+ uses: ` + getActionPin("actions/checkout") + `
+ with:
+ persist-credentials: false
+
+ - name: Setup Scripts
+ uses: ` + setupActionRef + `
+ with:
+ destination: ${{ runner.temp }}/gh-aw/actions
+
+ - name: Check admin/maintainer permissions
+ uses: ` + getCachedActionPinFromResolver("actions/github-script", resolver) + `
+ with:
+ github-token: ${{ secrets.GITHUB_TOKEN }}
+ script: |
+ const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
+ setupGlobals(core, github, context, exec, io, getOctokit);
+ const { main } = require('${{ runner.temp }}/gh-aw/actions/check_team_member.cjs');
+ await main();
+
+`)
+
+ yaml.WriteString(generateInstallCLISteps(actionMode, version, actionTag, resolver))
+ yaml.WriteString(` - name: Generate agentic workflow activity report
+ uses: ` + getCachedActionPinFromResolver("actions/github-script", resolver) + `
+ env:
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ GH_AW_CMD_PREFIX: ` + getCLICmdPrefix(actionMode) + `
+ with:
+ github-token: ${{ secrets.GITHUB_TOKEN }}
+ script: |
+ const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
+ setupGlobals(core, github, context, exec, io, getOctokit);
+ const { main } = require('${{ runner.temp }}/gh-aw/actions/run_activity_report.cjs');
+ await main();
+`)
+
// Add close_agentic_workflows_issues job for workflow_dispatch with operation == 'close_agentic_workflows_issues'
yaml.WriteString(`
close_agentic_workflows_issues:
diff --git a/pkg/workflow/side_repo_maintenance.go b/pkg/workflow/side_repo_maintenance.go
index 4e8aa64082a..36a81474ceb 100644
--- a/pkg/workflow/side_repo_maintenance.go
+++ b/pkg/workflow/side_repo_maintenance.go
@@ -216,6 +216,7 @@ on:
- ''
- 'safe_outputs'
- 'create_labels'
+ - 'activity_report'
- 'validate'
run_url:
description: 'Run URL or run ID to replay safe outputs from (e.g. https://github.com/owner/repo/actions/runs/12345 or 12345). Required when operation is safe_outputs.'
@@ -225,7 +226,7 @@ on:
workflow_call:
inputs:
operation:
- description: 'Optional maintenance operation to run (safe_outputs, create_labels, validate)'
+ description: 'Optional maintenance operation to run (safe_outputs, create_labels, activity_report, validate)'
required: false
type: string
default: ''
@@ -424,6 +425,53 @@ jobs:
await main();
`)
+ // Add activity_report job for workflow_dispatch/workflow_call with operation == 'activity_report'
+ yaml.WriteString(`
+ activity_report:
+ if: ${{ ` + RenderCondition(buildDispatchOperationCondition("activity_report")) + ` }}
+ runs-on: ` + runsOnValue + `
+ permissions:
+ actions: read
+ issues: write
+ steps:
+ - name: Checkout repository
+ uses: ` + getActionPin("actions/checkout") + `
+ with:
+ persist-credentials: false
+
+ - name: Setup Scripts
+ uses: ` + setupActionRef + `
+ with:
+ destination: ${{ runner.temp }}/gh-aw/actions
+
+ - name: Check admin/maintainer permissions
+ uses: ` + getCachedActionPinFromResolver("actions/github-script", resolver) + `
+ with:
+ github-token: ${{ secrets.GITHUB_TOKEN }}
+ script: |
+ const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
+ setupGlobals(core, github, context, exec, io, getOctokit);
+ const { main } = require('${{ runner.temp }}/gh-aw/actions/check_team_member.cjs');
+ await main();
+
+`)
+
+ yaml.WriteString(generateInstallCLISteps(actionMode, version, actionTag, resolver))
+ yaml.WriteString(` - name: Generate agentic workflow activity report in target repository
+ uses: ` + getCachedActionPinFromResolver("actions/github-script", resolver) + `
+ env:
+ GH_TOKEN: ` + token + `
+ GH_AW_CMD_PREFIX: ` + getCLICmdPrefix(actionMode) + `
+ GH_AW_TARGET_REPO_SLUG: "` + repoSlug + `"
+ with:
+ github-token: ` + token + `
+ script: |
+ const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
+ setupGlobals(core, github, context, exec, io, getOctokit);
+ const { main } = require('${{ runner.temp }}/gh-aw/actions/run_activity_report.cjs');
+ await main();
+`)
+
// Add validate_workflows job for workflow_dispatch/workflow_call with operation == 'validate'
validateRunsOnValue := FormatRunsOn(nil, "ubuntu-latest")
yaml.WriteString(`
diff --git a/pkg/workflow/side_repo_maintenance_integration_test.go b/pkg/workflow/side_repo_maintenance_integration_test.go
index dda9d21e4ef..64c4fc94952 100644
--- a/pkg/workflow/side_repo_maintenance_integration_test.go
+++ b/pkg/workflow/side_repo_maintenance_integration_test.go
@@ -87,6 +87,10 @@ This workflow operates on a separate repository.
assert.Contains(t, contentStr, "create_labels:",
"generated workflow should include create_labels job")
+ // Must have activity_report job.
+ assert.Contains(t, contentStr, "activity_report:",
+ "generated workflow should include activity_report job")
+
// GH_AW_TARGET_REPO_SLUG must be wired with the correct slug.
assert.Contains(t, contentStr, `GH_AW_TARGET_REPO_SLUG: "my-org/target-repo"`,
"GH_AW_TARGET_REPO_SLUG should be set to the target repo slug")
From 833a7c59209f8502d39afcb1f8725db5eab998c9 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sun, 19 Apr 2026 19:06:51 +0000
Subject: [PATCH 02/14] refactor: simplify activity report markdown assembly
Agent-Logs-Url: https://github.com/github/gh-aw/sessions/267bf5c1-a299-43c5-be20-17cdb0ab2a0c
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
---
actions/setup/js/run_activity_report.cjs | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/actions/setup/js/run_activity_report.cjs b/actions/setup/js/run_activity_report.cjs
index 85c4ea15639..2fd1eccde36 100644
--- a/actions/setup/js/run_activity_report.cjs
+++ b/actions/setup/js/run_activity_report.cjs
@@ -111,9 +111,9 @@ async function main() {
sections.push(await runRangeReport(bin, prefixArgs, repoSlug, range));
}
- const body = ["## Agentic workflow activity report", "", `Repository: \`${repoSlug}\``, `Generated at: ${new Date().toISOString()}`, "", ...sections.flatMap(section => ["---", "", `## ${section.heading}`, "", section.body, ""])].join(
- "\n"
- );
+ const headerLines = ["## Agentic workflow activity report", "", `Repository: \`${repoSlug}\``, `Generated at: ${new Date().toISOString()}`, ""];
+ const sectionLines = sections.flatMap(section => ["---", "", `## ${section.heading}`, "", section.body, ""]);
+ const body = [...headerLines, ...sectionLines].join("\n");
const createdIssue = await github.rest.issues.create({
owner,
From f18edc42d3b2f7a0f7ad33afe75aeaf3f58ae3f4 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sun, 19 Apr 2026 19:24:50 +0000
Subject: [PATCH 03/14] fix: use dashed activity-report operation and new
status issue title
Agent-Logs-Url: https://github.com/github/gh-aw/sessions/37d80ed2-4179-4462-ac6e-bbe23dc36ad5
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
---
.github/workflows/agentics-maintenance.yml | 8 ++++----
actions/setup/js/run_activity_report.cjs | 2 +-
actions/setup/js/run_activity_report.test.cjs | 2 +-
pkg/workflow/maintenance_workflow_test.go | 12 ++++++------
pkg/workflow/maintenance_workflow_yaml.go | 12 ++++++------
pkg/workflow/side_repo_maintenance.go | 8 ++++----
6 files changed, 22 insertions(+), 22 deletions(-)
diff --git a/.github/workflows/agentics-maintenance.yml b/.github/workflows/agentics-maintenance.yml
index 1d63f82e62b..fc2007d174d 100644
--- a/.github/workflows/agentics-maintenance.yml
+++ b/.github/workflows/agentics-maintenance.yml
@@ -50,7 +50,7 @@ on:
- 'upgrade'
- 'safe_outputs'
- 'create_labels'
- - 'activity_report'
+ - 'activity-report'
- 'close_agentic_workflows_issues'
- 'clean_cache_memories'
- 'validate'
@@ -62,7 +62,7 @@ on:
workflow_call:
inputs:
operation:
- description: 'Optional maintenance operation to run (disable, enable, update, upgrade, safe_outputs, create_labels, activity_report, close_agentic_workflows_issues, clean_cache_memories, validate)'
+ description: 'Optional maintenance operation to run (disable, enable, update, upgrade, safe_outputs, create_labels, activity-report, close_agentic_workflows_issues, clean_cache_memories, validate)'
required: false
type: string
default: ''
@@ -157,7 +157,7 @@ jobs:
await main();
run_operation:
- if: ${{ (github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call') && inputs.operation != '' && inputs.operation != 'safe_outputs' && inputs.operation != 'create_labels' && inputs.operation != 'activity_report' && inputs.operation != 'close_agentic_workflows_issues' && inputs.operation != 'clean_cache_memories' && inputs.operation != 'validate' && (!(github.event.repository.fork)) }}
+ if: ${{ (github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call') && inputs.operation != '' && inputs.operation != 'safe_outputs' && inputs.operation != 'create_labels' && inputs.operation != 'activity-report' && inputs.operation != 'close_agentic_workflows_issues' && inputs.operation != 'clean_cache_memories' && inputs.operation != 'validate' && (!(github.event.repository.fork)) }}
runs-on: ubuntu-slim
permissions:
actions: write
@@ -313,7 +313,7 @@ jobs:
await main();
activity_report:
- if: ${{ (github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call') && inputs.operation == 'activity_report' && (!(github.event.repository.fork)) }}
+ if: ${{ (github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call') && inputs.operation == 'activity-report' && (!(github.event.repository.fork)) }}
runs-on: ubuntu-slim
permissions:
actions: read
diff --git a/actions/setup/js/run_activity_report.cjs b/actions/setup/js/run_activity_report.cjs
index 2fd1eccde36..09a5766fc49 100644
--- a/actions/setup/js/run_activity_report.cjs
+++ b/actions/setup/js/run_activity_report.cjs
@@ -5,7 +5,7 @@ const { getErrorMessage, isRateLimitError } = require("./error_helpers.cjs");
const { resolveExecutionOwnerRepo } = require("./repo_helpers.cjs");
const { sanitizeContent } = require("./sanitize_content.cjs");
-const ISSUE_TITLE = "[AW activity report]";
+const ISSUE_TITLE = "[aw] agentic status report";
/** @typedef {{ key: string, heading: string, startDate: string, optionalOnRateLimit: boolean }} ActivityRange */
diff --git a/actions/setup/js/run_activity_report.test.cjs b/actions/setup/js/run_activity_report.test.cjs
index 2514e40161e..857357f9380 100644
--- a/actions/setup/js/run_activity_report.test.cjs
+++ b/actions/setup/js/run_activity_report.test.cjs
@@ -81,7 +81,7 @@ describe("run_activity_report", () => {
expect.objectContaining({
owner: "testowner",
repo: "testrepo",
- title: "[AW activity report]",
+ title: "[aw] agentic status report",
labels: ["agentic-workflows"],
})
);
diff --git a/pkg/workflow/maintenance_workflow_test.go b/pkg/workflow/maintenance_workflow_test.go
index fcdcb1a60d5..b1b33b02a34 100644
--- a/pkg/workflow/maintenance_workflow_test.go
+++ b/pkg/workflow/maintenance_workflow_test.go
@@ -282,10 +282,10 @@ func TestGenerateMaintenanceWorkflow_OperationJobConditions(t *testing.T) {
yaml := string(content)
operationSkipCondition := `github.event_name != 'workflow_dispatch' && github.event_name != 'workflow_call' || inputs.operation == ''`
- operationRunCondition := `(github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call') && inputs.operation != '' && inputs.operation != 'safe_outputs' && inputs.operation != 'create_labels' && inputs.operation != 'activity_report' && inputs.operation != 'close_agentic_workflows_issues' && inputs.operation != 'clean_cache_memories' && inputs.operation != 'validate'`
+ operationRunCondition := `(github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call') && inputs.operation != '' && inputs.operation != 'safe_outputs' && inputs.operation != 'create_labels' && inputs.operation != 'activity-report' && inputs.operation != 'close_agentic_workflows_issues' && inputs.operation != 'clean_cache_memories' && inputs.operation != 'validate'`
applySafeOutputsCondition := `(github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call') && inputs.operation == 'safe_outputs'`
createLabelsCondition := `(github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call') && inputs.operation == 'create_labels'`
- activityReportCondition := `(github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call') && inputs.operation == 'activity_report'`
+ activityReportCondition := `(github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call') && inputs.operation == 'activity-report'`
closeAgenticWorkflowIssuesCondition := `(github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call') && inputs.operation == 'close_agentic_workflows_issues'`
cleanCacheMemoriesCondition := `github.event_name != 'workflow_dispatch' && github.event_name != 'workflow_call' || inputs.operation == '' || inputs.operation == 'clean_cache_memories'`
@@ -368,7 +368,7 @@ func TestGenerateMaintenanceWorkflow_OperationJobConditions(t *testing.T) {
}
}
- // activity_report job should be triggered when operation == 'activity_report'
+ // activity_report job should be triggered when operation == 'activity-report'
activityReportIdx := strings.Index(yaml, "\n activity_report:")
if activityReportIdx == -1 {
t.Errorf("Job activity_report not found in generated workflow")
@@ -410,9 +410,9 @@ func TestGenerateMaintenanceWorkflow_OperationJobConditions(t *testing.T) {
t.Error("workflow_dispatch operation choices should include 'validate'")
}
- // Verify activity_report is an option in the operation choices
- if !strings.Contains(yaml, "- 'activity_report'") {
- t.Error("workflow_dispatch operation choices should include 'activity_report'")
+ // Verify activity-report is an option in the operation choices
+ if !strings.Contains(yaml, "- 'activity-report'") {
+ t.Error("workflow_dispatch operation choices should include 'activity-report'")
}
// Verify close_agentic_workflows_issues is an option in the operation choices
diff --git a/pkg/workflow/maintenance_workflow_yaml.go b/pkg/workflow/maintenance_workflow_yaml.go
index d80023fb915..ae529a96275 100644
--- a/pkg/workflow/maintenance_workflow_yaml.go
+++ b/pkg/workflow/maintenance_workflow_yaml.go
@@ -59,7 +59,7 @@ on:
- 'upgrade'
- 'safe_outputs'
- 'create_labels'
- - 'activity_report'
+ - 'activity-report'
- 'close_agentic_workflows_issues'
- 'clean_cache_memories'
- 'validate'
@@ -71,7 +71,7 @@ on:
workflow_call:
inputs:
operation:
- description: 'Optional maintenance operation to run (disable, enable, update, upgrade, safe_outputs, create_labels, activity_report, close_agentic_workflows_issues, clean_cache_memories, validate)'
+ description: 'Optional maintenance operation to run (disable, enable, update, upgrade, safe_outputs, create_labels, activity-report, close_agentic_workflows_issues, clean_cache_memories, validate)'
required: false
type: string
default: ''
@@ -196,8 +196,8 @@ jobs:
`)
// Add unified run_operation job for all dispatch operations except those with dedicated jobs
- // (safe_outputs, create_labels, activity_report, close_agentic_workflows_issues, clean_cache_memories, validate)
- runOperationCondition := buildRunOperationCondition("safe_outputs", "create_labels", "activity_report", "close_agentic_workflows_issues", "clean_cache_memories", "validate")
+ // (safe_outputs, create_labels, activity-report, close_agentic_workflows_issues, clean_cache_memories, validate)
+ runOperationCondition := buildRunOperationCondition("safe_outputs", "create_labels", "activity-report", "close_agentic_workflows_issues", "clean_cache_memories", "validate")
yaml.WriteString(`
run_operation:
if: ${{ ` + RenderCondition(runOperationCondition) + ` }}
@@ -350,10 +350,10 @@ jobs:
await main();
`)
- // Add activity_report job for workflow_dispatch with operation == 'activity_report'
+ // Add activity_report job for workflow_dispatch with operation == 'activity-report'
yaml.WriteString(`
activity_report:
- if: ${{ ` + RenderCondition(buildDispatchOperationCondition("activity_report")) + ` }}
+ if: ${{ ` + RenderCondition(buildDispatchOperationCondition("activity-report")) + ` }}
runs-on: ` + runsOnValue + `
permissions:
actions: read
diff --git a/pkg/workflow/side_repo_maintenance.go b/pkg/workflow/side_repo_maintenance.go
index 36a81474ceb..06007252ebc 100644
--- a/pkg/workflow/side_repo_maintenance.go
+++ b/pkg/workflow/side_repo_maintenance.go
@@ -216,7 +216,7 @@ on:
- ''
- 'safe_outputs'
- 'create_labels'
- - 'activity_report'
+ - 'activity-report'
- 'validate'
run_url:
description: 'Run URL or run ID to replay safe outputs from (e.g. https://github.com/owner/repo/actions/runs/12345 or 12345). Required when operation is safe_outputs.'
@@ -226,7 +226,7 @@ on:
workflow_call:
inputs:
operation:
- description: 'Optional maintenance operation to run (safe_outputs, create_labels, activity_report, validate)'
+ description: 'Optional maintenance operation to run (safe_outputs, create_labels, activity-report, validate)'
required: false
type: string
default: ''
@@ -425,10 +425,10 @@ jobs:
await main();
`)
- // Add activity_report job for workflow_dispatch/workflow_call with operation == 'activity_report'
+ // Add activity_report job for workflow_dispatch/workflow_call with operation == 'activity-report'
yaml.WriteString(`
activity_report:
- if: ${{ ` + RenderCondition(buildDispatchOperationCondition("activity_report")) + ` }}
+ if: ${{ ` + RenderCondition(buildDispatchOperationCondition("activity-report")) + ` }}
runs-on: ` + runsOnValue + `
permissions:
actions: read
From bb16c881f6a1d9c4dc873424570fb0e1a2baa9e6 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sun, 19 Apr 2026 19:36:02 +0000
Subject: [PATCH 04/14] fix: use activity_report operation naming for
consistency
Agent-Logs-Url: https://github.com/github/gh-aw/sessions/f36a3c23-cf51-4452-8735-342ff7556fa0
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
---
.github/workflows/agentics-maintenance.yml | 8 ++++----
pkg/workflow/maintenance_workflow_test.go | 12 ++++++------
pkg/workflow/maintenance_workflow_yaml.go | 12 ++++++------
pkg/workflow/side_repo_maintenance.go | 8 ++++----
4 files changed, 20 insertions(+), 20 deletions(-)
diff --git a/.github/workflows/agentics-maintenance.yml b/.github/workflows/agentics-maintenance.yml
index fc2007d174d..1d63f82e62b 100644
--- a/.github/workflows/agentics-maintenance.yml
+++ b/.github/workflows/agentics-maintenance.yml
@@ -50,7 +50,7 @@ on:
- 'upgrade'
- 'safe_outputs'
- 'create_labels'
- - 'activity-report'
+ - 'activity_report'
- 'close_agentic_workflows_issues'
- 'clean_cache_memories'
- 'validate'
@@ -62,7 +62,7 @@ on:
workflow_call:
inputs:
operation:
- description: 'Optional maintenance operation to run (disable, enable, update, upgrade, safe_outputs, create_labels, activity-report, close_agentic_workflows_issues, clean_cache_memories, validate)'
+ description: 'Optional maintenance operation to run (disable, enable, update, upgrade, safe_outputs, create_labels, activity_report, close_agentic_workflows_issues, clean_cache_memories, validate)'
required: false
type: string
default: ''
@@ -157,7 +157,7 @@ jobs:
await main();
run_operation:
- if: ${{ (github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call') && inputs.operation != '' && inputs.operation != 'safe_outputs' && inputs.operation != 'create_labels' && inputs.operation != 'activity-report' && inputs.operation != 'close_agentic_workflows_issues' && inputs.operation != 'clean_cache_memories' && inputs.operation != 'validate' && (!(github.event.repository.fork)) }}
+ if: ${{ (github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call') && inputs.operation != '' && inputs.operation != 'safe_outputs' && inputs.operation != 'create_labels' && inputs.operation != 'activity_report' && inputs.operation != 'close_agentic_workflows_issues' && inputs.operation != 'clean_cache_memories' && inputs.operation != 'validate' && (!(github.event.repository.fork)) }}
runs-on: ubuntu-slim
permissions:
actions: write
@@ -313,7 +313,7 @@ jobs:
await main();
activity_report:
- if: ${{ (github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call') && inputs.operation == 'activity-report' && (!(github.event.repository.fork)) }}
+ if: ${{ (github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call') && inputs.operation == 'activity_report' && (!(github.event.repository.fork)) }}
runs-on: ubuntu-slim
permissions:
actions: read
diff --git a/pkg/workflow/maintenance_workflow_test.go b/pkg/workflow/maintenance_workflow_test.go
index b1b33b02a34..fcdcb1a60d5 100644
--- a/pkg/workflow/maintenance_workflow_test.go
+++ b/pkg/workflow/maintenance_workflow_test.go
@@ -282,10 +282,10 @@ func TestGenerateMaintenanceWorkflow_OperationJobConditions(t *testing.T) {
yaml := string(content)
operationSkipCondition := `github.event_name != 'workflow_dispatch' && github.event_name != 'workflow_call' || inputs.operation == ''`
- operationRunCondition := `(github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call') && inputs.operation != '' && inputs.operation != 'safe_outputs' && inputs.operation != 'create_labels' && inputs.operation != 'activity-report' && inputs.operation != 'close_agentic_workflows_issues' && inputs.operation != 'clean_cache_memories' && inputs.operation != 'validate'`
+ operationRunCondition := `(github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call') && inputs.operation != '' && inputs.operation != 'safe_outputs' && inputs.operation != 'create_labels' && inputs.operation != 'activity_report' && inputs.operation != 'close_agentic_workflows_issues' && inputs.operation != 'clean_cache_memories' && inputs.operation != 'validate'`
applySafeOutputsCondition := `(github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call') && inputs.operation == 'safe_outputs'`
createLabelsCondition := `(github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call') && inputs.operation == 'create_labels'`
- activityReportCondition := `(github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call') && inputs.operation == 'activity-report'`
+ activityReportCondition := `(github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call') && inputs.operation == 'activity_report'`
closeAgenticWorkflowIssuesCondition := `(github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call') && inputs.operation == 'close_agentic_workflows_issues'`
cleanCacheMemoriesCondition := `github.event_name != 'workflow_dispatch' && github.event_name != 'workflow_call' || inputs.operation == '' || inputs.operation == 'clean_cache_memories'`
@@ -368,7 +368,7 @@ func TestGenerateMaintenanceWorkflow_OperationJobConditions(t *testing.T) {
}
}
- // activity_report job should be triggered when operation == 'activity-report'
+ // activity_report job should be triggered when operation == 'activity_report'
activityReportIdx := strings.Index(yaml, "\n activity_report:")
if activityReportIdx == -1 {
t.Errorf("Job activity_report not found in generated workflow")
@@ -410,9 +410,9 @@ func TestGenerateMaintenanceWorkflow_OperationJobConditions(t *testing.T) {
t.Error("workflow_dispatch operation choices should include 'validate'")
}
- // Verify activity-report is an option in the operation choices
- if !strings.Contains(yaml, "- 'activity-report'") {
- t.Error("workflow_dispatch operation choices should include 'activity-report'")
+ // Verify activity_report is an option in the operation choices
+ if !strings.Contains(yaml, "- 'activity_report'") {
+ t.Error("workflow_dispatch operation choices should include 'activity_report'")
}
// Verify close_agentic_workflows_issues is an option in the operation choices
diff --git a/pkg/workflow/maintenance_workflow_yaml.go b/pkg/workflow/maintenance_workflow_yaml.go
index ae529a96275..d80023fb915 100644
--- a/pkg/workflow/maintenance_workflow_yaml.go
+++ b/pkg/workflow/maintenance_workflow_yaml.go
@@ -59,7 +59,7 @@ on:
- 'upgrade'
- 'safe_outputs'
- 'create_labels'
- - 'activity-report'
+ - 'activity_report'
- 'close_agentic_workflows_issues'
- 'clean_cache_memories'
- 'validate'
@@ -71,7 +71,7 @@ on:
workflow_call:
inputs:
operation:
- description: 'Optional maintenance operation to run (disable, enable, update, upgrade, safe_outputs, create_labels, activity-report, close_agentic_workflows_issues, clean_cache_memories, validate)'
+ description: 'Optional maintenance operation to run (disable, enable, update, upgrade, safe_outputs, create_labels, activity_report, close_agentic_workflows_issues, clean_cache_memories, validate)'
required: false
type: string
default: ''
@@ -196,8 +196,8 @@ jobs:
`)
// Add unified run_operation job for all dispatch operations except those with dedicated jobs
- // (safe_outputs, create_labels, activity-report, close_agentic_workflows_issues, clean_cache_memories, validate)
- runOperationCondition := buildRunOperationCondition("safe_outputs", "create_labels", "activity-report", "close_agentic_workflows_issues", "clean_cache_memories", "validate")
+ // (safe_outputs, create_labels, activity_report, close_agentic_workflows_issues, clean_cache_memories, validate)
+ runOperationCondition := buildRunOperationCondition("safe_outputs", "create_labels", "activity_report", "close_agentic_workflows_issues", "clean_cache_memories", "validate")
yaml.WriteString(`
run_operation:
if: ${{ ` + RenderCondition(runOperationCondition) + ` }}
@@ -350,10 +350,10 @@ jobs:
await main();
`)
- // Add activity_report job for workflow_dispatch with operation == 'activity-report'
+ // Add activity_report job for workflow_dispatch with operation == 'activity_report'
yaml.WriteString(`
activity_report:
- if: ${{ ` + RenderCondition(buildDispatchOperationCondition("activity-report")) + ` }}
+ if: ${{ ` + RenderCondition(buildDispatchOperationCondition("activity_report")) + ` }}
runs-on: ` + runsOnValue + `
permissions:
actions: read
diff --git a/pkg/workflow/side_repo_maintenance.go b/pkg/workflow/side_repo_maintenance.go
index 06007252ebc..36a81474ceb 100644
--- a/pkg/workflow/side_repo_maintenance.go
+++ b/pkg/workflow/side_repo_maintenance.go
@@ -216,7 +216,7 @@ on:
- ''
- 'safe_outputs'
- 'create_labels'
- - 'activity-report'
+ - 'activity_report'
- 'validate'
run_url:
description: 'Run URL or run ID to replay safe outputs from (e.g. https://github.com/owner/repo/actions/runs/12345 or 12345). Required when operation is safe_outputs.'
@@ -226,7 +226,7 @@ on:
workflow_call:
inputs:
operation:
- description: 'Optional maintenance operation to run (safe_outputs, create_labels, activity-report, validate)'
+ description: 'Optional maintenance operation to run (safe_outputs, create_labels, activity_report, validate)'
required: false
type: string
default: ''
@@ -425,10 +425,10 @@ jobs:
await main();
`)
- // Add activity_report job for workflow_dispatch/workflow_call with operation == 'activity-report'
+ // Add activity_report job for workflow_dispatch/workflow_call with operation == 'activity_report'
yaml.WriteString(`
activity_report:
- if: ${{ ` + RenderCondition(buildDispatchOperationCondition("activity-report")) + ` }}
+ if: ${{ ` + RenderCondition(buildDispatchOperationCondition("activity_report")) + ` }}
runs-on: ` + runsOnValue + `
permissions:
actions: read
From 4dacf4b6d3cb626c269a4718289f8a4b2f682c8b Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sun, 19 Apr 2026 19:58:32 +0000
Subject: [PATCH 05/14] fix: improve activity report markdown structure and
query depth
Agent-Logs-Url: https://github.com/github/gh-aw/sessions/14261d82-e94d-44ea-a9cb-7ce48cf40810
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
---
actions/setup/js/run_activity_report.cjs | 20 ++++++++++++---
actions/setup/js/run_activity_report.test.cjs | 25 ++++++++++++++-----
2 files changed, 35 insertions(+), 10 deletions(-)
diff --git a/actions/setup/js/run_activity_report.cjs b/actions/setup/js/run_activity_report.cjs
index 09a5766fc49..91132d836d7 100644
--- a/actions/setup/js/run_activity_report.cjs
+++ b/actions/setup/js/run_activity_report.cjs
@@ -6,6 +6,7 @@ const { resolveExecutionOwnerRepo } = require("./repo_helpers.cjs");
const { sanitizeContent } = require("./sanitize_content.cjs");
const ISSUE_TITLE = "[aw] agentic status report";
+const REPORT_COUNT = 100;
/** @typedef {{ key: string, heading: string, startDate: string, optionalOnRateLimit: boolean }} ActivityRange */
@@ -34,7 +35,7 @@ function hasRateLimitText(text) {
* @returns {Promise<{ heading: string, body: string }>}
*/
async function runRangeReport(bin, prefixArgs, repoSlug, range) {
- const args = [...prefixArgs, "logs", "--repo", repoSlug, "--start-date", range.startDate, "--format", "markdown"];
+ const args = [...prefixArgs, "logs", "--repo", repoSlug, "--start-date", range.startDate, "--count", String(REPORT_COUNT), "--format", "markdown"];
core.info(`Running: ${bin} ${args.join(" ")}`);
try {
@@ -45,7 +46,7 @@ async function runRangeReport(bin, prefixArgs, repoSlug, range) {
if (result.exitCode === 0 && result.stdout.trim()) {
return {
heading: range.heading,
- body: sanitizeContent(result.stdout.trim()),
+ body: normalizeReportMarkdown(sanitizeContent(result.stdout.trim())),
};
}
@@ -94,6 +95,17 @@ async function runRangeReport(bin, prefixArgs, repoSlug, range) {
}
}
+/**
+ * Normalize report markdown for issue rendering.
+ * Demotes headings so top-level report headings start at H3.
+ *
+ * @param {string} markdown
+ * @returns {string}
+ */
+function normalizeReportMarkdown(markdown) {
+ return markdown.replace(/^(#{1,6})\s+/gm, (_, hashes) => `${"#".repeat(Math.min(6, hashes.length + 2))} `);
+}
+
/**
* Generate an agentic workflow activity report issue.
* @returns {Promise}
@@ -111,8 +123,8 @@ async function main() {
sections.push(await runRangeReport(bin, prefixArgs, repoSlug, range));
}
- const headerLines = ["## Agentic workflow activity report", "", `Repository: \`${repoSlug}\``, `Generated at: ${new Date().toISOString()}`, ""];
- const sectionLines = sections.flatMap(section => ["---", "", `## ${section.heading}`, "", section.body, ""]);
+ const headerLines = ["### Agentic workflow activity report", "", `Repository: \`${repoSlug}\``, `Generated at: ${new Date().toISOString()}`, ""];
+ const sectionLines = sections.flatMap(section => ["", `${section.heading}
`, "", section.body, "", " ", ""]);
const body = [...headerLines, ...sectionLines].join("\n");
const createdIssue = await github.rest.issues.create({
diff --git a/actions/setup/js/run_activity_report.test.cjs b/actions/setup/js/run_activity_report.test.cjs
index 857357f9380..a68b29aab45 100644
--- a/actions/setup/js/run_activity_report.test.cjs
+++ b/actions/setup/js/run_activity_report.test.cjs
@@ -68,12 +68,22 @@ describe("run_activity_report", () => {
await main();
expect(mockExec.getExecOutput).toHaveBeenCalledTimes(3);
- expect(mockExec.getExecOutput).toHaveBeenNthCalledWith(1, "gh", expect.arrayContaining(["aw", "logs", "--repo", "testowner/testrepo", "--start-date", "-1d", "--format", "markdown"]), expect.objectContaining({ ignoreReturnCode: true }));
- expect(mockExec.getExecOutput).toHaveBeenNthCalledWith(2, "gh", expect.arrayContaining(["aw", "logs", "--repo", "testowner/testrepo", "--start-date", "-1w", "--format", "markdown"]), expect.objectContaining({ ignoreReturnCode: true }));
+ expect(mockExec.getExecOutput).toHaveBeenNthCalledWith(
+ 1,
+ "gh",
+ expect.arrayContaining(["aw", "logs", "--repo", "testowner/testrepo", "--start-date", "-1d", "--count", "100", "--format", "markdown"]),
+ expect.objectContaining({ ignoreReturnCode: true })
+ );
+ expect(mockExec.getExecOutput).toHaveBeenNthCalledWith(
+ 2,
+ "gh",
+ expect.arrayContaining(["aw", "logs", "--repo", "testowner/testrepo", "--start-date", "-1w", "--count", "100", "--format", "markdown"]),
+ expect.objectContaining({ ignoreReturnCode: true })
+ );
expect(mockExec.getExecOutput).toHaveBeenNthCalledWith(
3,
"gh",
- expect.arrayContaining(["aw", "logs", "--repo", "testowner/testrepo", "--start-date", "-1mo", "--format", "markdown"]),
+ expect.arrayContaining(["aw", "logs", "--repo", "testowner/testrepo", "--start-date", "-1mo", "--count", "100", "--format", "markdown"]),
expect.objectContaining({ ignoreReturnCode: true })
);
@@ -87,9 +97,12 @@ describe("run_activity_report", () => {
);
const issueBody = mockGithub.rest.issues.create.mock.calls[0][0].body;
- expect(issueBody).toContain("## Last 24 hours");
- expect(issueBody).toContain("## Last 7 days");
- expect(issueBody).toContain("## Last 30 days");
+ expect(issueBody).toContain("### Agentic workflow activity report");
+ expect(issueBody).toContain("");
+ expect(issueBody).toContain("Last 24 hours
");
+ expect(issueBody).toContain("Last 7 days
");
+ expect(issueBody).toContain("Last 30 days
");
+ expect(issueBody).toContain("#### 24h report");
});
it("skips the 30-day query when rate limited", async () => {
From a039b6790d5156742fe56989fd0b557c83df89d3 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sun, 19 Apr 2026 20:03:25 +0000
Subject: [PATCH 06/14] test: strengthen heading normalization coverage for
activity report
Agent-Logs-Url: https://github.com/github/gh-aw/sessions/14261d82-e94d-44ea-a9cb-7ce48cf40810
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
---
actions/setup/js/run_activity_report.cjs | 9 +++++++--
actions/setup/js/run_activity_report.test.cjs | 8 ++++++++
2 files changed, 15 insertions(+), 2 deletions(-)
diff --git a/actions/setup/js/run_activity_report.cjs b/actions/setup/js/run_activity_report.cjs
index 91132d836d7..1843466adb0 100644
--- a/actions/setup/js/run_activity_report.cjs
+++ b/actions/setup/js/run_activity_report.cjs
@@ -7,6 +7,7 @@ const { sanitizeContent } = require("./sanitize_content.cjs");
const ISSUE_TITLE = "[aw] agentic status report";
const REPORT_COUNT = 100;
+const HEADING_DEMOTION_LEVELS = 2;
/** @typedef {{ key: string, heading: string, startDate: string, optionalOnRateLimit: boolean }} ActivityRange */
@@ -103,7 +104,11 @@ async function runRangeReport(bin, prefixArgs, repoSlug, range) {
* @returns {string}
*/
function normalizeReportMarkdown(markdown) {
- return markdown.replace(/^(#{1,6})\s+/gm, (_, hashes) => `${"#".repeat(Math.min(6, hashes.length + 2))} `);
+ return markdown.replace(/^(#{1,6})\s+/gm, (_, hashes) => {
+ const headingLevel = hashes.length;
+ const demotedHeadingLevel = Math.min(6, headingLevel + HEADING_DEMOTION_LEVELS);
+ return `${"#".repeat(demotedHeadingLevel)} `;
+ });
}
/**
@@ -138,4 +143,4 @@ async function main() {
core.info(`Created issue #${createdIssue.data.number}: ${createdIssue.data.html_url}`);
}
-module.exports = { main, hasRateLimitText, runRangeReport };
+module.exports = { main, hasRateLimitText, runRangeReport, normalizeReportMarkdown };
diff --git a/actions/setup/js/run_activity_report.test.cjs b/actions/setup/js/run_activity_report.test.cjs
index a68b29aab45..72ab99bab8a 100644
--- a/actions/setup/js/run_activity_report.test.cjs
+++ b/actions/setup/js/run_activity_report.test.cjs
@@ -125,4 +125,12 @@ describe("run_activity_report", () => {
expect(hasRateLimitText("secondary rate limit")).toBe(true);
expect(hasRateLimitText("normal output")).toBe(false);
});
+
+ it("demotes report headings by two levels", async () => {
+ const { normalizeReportMarkdown } = await import("./run_activity_report.cjs");
+ const transformed = normalizeReportMarkdown("# H1\n## H2\n### H3");
+ expect(transformed).toContain("### H1");
+ expect(transformed).toContain("#### H2");
+ expect(transformed).toContain("##### H3");
+ });
});
From ba187934422ca3edae3291e060b4624af56ff9e4 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sun, 19 Apr 2026 20:16:07 +0000
Subject: [PATCH 07/14] feat: increase activity report depth and cache
downloaded logs
Agent-Logs-Url: https://github.com/github/gh-aw/sessions/907ed0e7-a686-4cc8-b8b5-9985215319bf
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
---
.github/workflows/agentics-maintenance.yml | 11 +++++++++++
actions/setup/js/run_activity_report.cjs | 11 +++++++----
actions/setup/js/run_activity_report.test.cjs | 6 +++---
pkg/workflow/maintenance_workflow_test.go | 9 +++++++++
pkg/workflow/maintenance_workflow_yaml.go | 11 +++++++++++
pkg/workflow/side_repo_maintenance.go | 11 +++++++++++
.../side_repo_maintenance_integration_test.go | 6 ++++++
7 files changed, 58 insertions(+), 7 deletions(-)
diff --git a/.github/workflows/agentics-maintenance.yml b/.github/workflows/agentics-maintenance.yml
index 1d63f82e62b..21f18014915 100644
--- a/.github/workflows/agentics-maintenance.yml
+++ b/.github/workflows/agentics-maintenance.yml
@@ -317,6 +317,7 @@ jobs:
runs-on: ubuntu-slim
permissions:
actions: read
+ contents: read
issues: write
steps:
- name: Checkout repository
@@ -348,11 +349,21 @@ jobs:
- name: Build gh-aw
run: make build
+ - name: Cache activity report logs
+ uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v5.0.5
+ with:
+ path: ./.cache/gh-aw/activity-report-logs
+ key: ${{ runner.os }}-activity-report-logs-${{ github.repository }}-${{ github.ref_name }}
+ restore-keys: |
+ ${{ runner.os }}-activity-report-logs-${{ github.repository }}-
+ ${{ runner.os }}-activity-report-logs-
+
- name: Generate agentic workflow activity report
uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GH_AW_CMD_PREFIX: ./gh-aw
+ GH_AW_ACTIVITY_REPORT_OUTPUT_DIR: ./.cache/gh-aw/activity-report-logs
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
diff --git a/actions/setup/js/run_activity_report.cjs b/actions/setup/js/run_activity_report.cjs
index 1843466adb0..d2944beebc3 100644
--- a/actions/setup/js/run_activity_report.cjs
+++ b/actions/setup/js/run_activity_report.cjs
@@ -6,8 +6,9 @@ const { resolveExecutionOwnerRepo } = require("./repo_helpers.cjs");
const { sanitizeContent } = require("./sanitize_content.cjs");
const ISSUE_TITLE = "[aw] agentic status report";
-const REPORT_COUNT = 100;
+const REPORT_COUNT = 1000;
const HEADING_DEMOTION_LEVELS = 2;
+const DEFAULT_REPORT_OUTPUT_DIR = "./.cache/gh-aw/activity-report-logs";
/** @typedef {{ key: string, heading: string, startDate: string, optionalOnRateLimit: boolean }} ActivityRange */
@@ -33,10 +34,11 @@ function hasRateLimitText(text) {
* @param {string[]} prefixArgs
* @param {string} repoSlug
* @param {ActivityRange} range
+ * @param {string} outputDir
* @returns {Promise<{ heading: string, body: string }>}
*/
-async function runRangeReport(bin, prefixArgs, repoSlug, range) {
- const args = [...prefixArgs, "logs", "--repo", repoSlug, "--start-date", range.startDate, "--count", String(REPORT_COUNT), "--format", "markdown"];
+async function runRangeReport(bin, prefixArgs, repoSlug, range, outputDir) {
+ const args = [...prefixArgs, "logs", "--repo", repoSlug, "--start-date", range.startDate, "--count", String(REPORT_COUNT), "--output", outputDir, "--format", "markdown"];
core.info(`Running: ${bin} ${args.join(" ")}`);
try {
@@ -117,6 +119,7 @@ function normalizeReportMarkdown(markdown) {
*/
async function main() {
const cmdPrefixStr = process.env.GH_AW_CMD_PREFIX || "gh aw";
+ const reportOutputDir = process.env.GH_AW_ACTIVITY_REPORT_OUTPUT_DIR || DEFAULT_REPORT_OUTPUT_DIR;
const [bin, ...prefixArgs] = cmdPrefixStr.split(" ").filter(Boolean);
const { owner, repo } = resolveExecutionOwnerRepo();
const repoSlug = `${owner}/${repo}`;
@@ -125,7 +128,7 @@ async function main() {
const sections = [];
for (const range of REPORT_RANGES) {
- sections.push(await runRangeReport(bin, prefixArgs, repoSlug, range));
+ sections.push(await runRangeReport(bin, prefixArgs, repoSlug, range, reportOutputDir));
}
const headerLines = ["### Agentic workflow activity report", "", `Repository: \`${repoSlug}\``, `Generated at: ${new Date().toISOString()}`, ""];
diff --git a/actions/setup/js/run_activity_report.test.cjs b/actions/setup/js/run_activity_report.test.cjs
index 72ab99bab8a..549d9caff83 100644
--- a/actions/setup/js/run_activity_report.test.cjs
+++ b/actions/setup/js/run_activity_report.test.cjs
@@ -71,19 +71,19 @@ describe("run_activity_report", () => {
expect(mockExec.getExecOutput).toHaveBeenNthCalledWith(
1,
"gh",
- expect.arrayContaining(["aw", "logs", "--repo", "testowner/testrepo", "--start-date", "-1d", "--count", "100", "--format", "markdown"]),
+ expect.arrayContaining(["aw", "logs", "--repo", "testowner/testrepo", "--start-date", "-1d", "--count", "1000", "--output", "./.cache/gh-aw/activity-report-logs", "--format", "markdown"]),
expect.objectContaining({ ignoreReturnCode: true })
);
expect(mockExec.getExecOutput).toHaveBeenNthCalledWith(
2,
"gh",
- expect.arrayContaining(["aw", "logs", "--repo", "testowner/testrepo", "--start-date", "-1w", "--count", "100", "--format", "markdown"]),
+ expect.arrayContaining(["aw", "logs", "--repo", "testowner/testrepo", "--start-date", "-1w", "--count", "1000", "--output", "./.cache/gh-aw/activity-report-logs", "--format", "markdown"]),
expect.objectContaining({ ignoreReturnCode: true })
);
expect(mockExec.getExecOutput).toHaveBeenNthCalledWith(
3,
"gh",
- expect.arrayContaining(["aw", "logs", "--repo", "testowner/testrepo", "--start-date", "-1mo", "--count", "100", "--format", "markdown"]),
+ expect.arrayContaining(["aw", "logs", "--repo", "testowner/testrepo", "--start-date", "-1mo", "--count", "1000", "--output", "./.cache/gh-aw/activity-report-logs", "--format", "markdown"]),
expect.objectContaining({ ignoreReturnCode: true })
);
diff --git a/pkg/workflow/maintenance_workflow_test.go b/pkg/workflow/maintenance_workflow_test.go
index fcdcb1a60d5..00356b5a48b 100644
--- a/pkg/workflow/maintenance_workflow_test.go
+++ b/pkg/workflow/maintenance_workflow_test.go
@@ -377,6 +377,15 @@ func TestGenerateMaintenanceWorkflow_OperationJobConditions(t *testing.T) {
if !strings.Contains(activityReportSection, activityReportCondition) {
t.Errorf("Job activity_report should have the activation condition %q in:\n%s", activityReportCondition, activityReportSection)
}
+ if !strings.Contains(activityReportSection, "contents: read") {
+ t.Errorf("Job activity_report should include contents: read permission in:\n%s", activityReportSection)
+ }
+ }
+ if !strings.Contains(yaml, "Cache activity report logs") {
+ t.Errorf("Job activity_report should include a cache step in:\n%s", yaml)
+ }
+ if !strings.Contains(yaml, "GH_AW_ACTIVITY_REPORT_OUTPUT_DIR: ./.cache/gh-aw/activity-report-logs") {
+ t.Errorf("Job activity_report should set GH_AW_ACTIVITY_REPORT_OUTPUT_DIR in:\n%s", yaml)
}
// close_agentic_workflows_issues job should be triggered when operation == 'close_agentic_workflows_issues'
diff --git a/pkg/workflow/maintenance_workflow_yaml.go b/pkg/workflow/maintenance_workflow_yaml.go
index d80023fb915..60ef60c5c25 100644
--- a/pkg/workflow/maintenance_workflow_yaml.go
+++ b/pkg/workflow/maintenance_workflow_yaml.go
@@ -357,6 +357,7 @@ jobs:
runs-on: ` + runsOnValue + `
permissions:
actions: read
+ contents: read
issues: write
steps:
- name: Checkout repository
@@ -382,11 +383,21 @@ jobs:
`)
yaml.WriteString(generateInstallCLISteps(actionMode, version, actionTag, resolver))
+ yaml.WriteString(` - name: Cache activity report logs
+ uses: ` + getActionPin("actions/cache") + `
+ with:
+ path: ./.cache/gh-aw/activity-report-logs
+ key: ${{ runner.os }}-activity-report-logs-${{ github.repository }}-${{ github.ref_name }}
+ restore-keys: |
+ ${{ runner.os }}-activity-report-logs-${{ github.repository }}-
+ ${{ runner.os }}-activity-report-logs-
+`)
yaml.WriteString(` - name: Generate agentic workflow activity report
uses: ` + getCachedActionPinFromResolver("actions/github-script", resolver) + `
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GH_AW_CMD_PREFIX: ` + getCLICmdPrefix(actionMode) + `
+ GH_AW_ACTIVITY_REPORT_OUTPUT_DIR: ./.cache/gh-aw/activity-report-logs
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
diff --git a/pkg/workflow/side_repo_maintenance.go b/pkg/workflow/side_repo_maintenance.go
index 36a81474ceb..53122edd5b1 100644
--- a/pkg/workflow/side_repo_maintenance.go
+++ b/pkg/workflow/side_repo_maintenance.go
@@ -432,6 +432,7 @@ jobs:
runs-on: ` + runsOnValue + `
permissions:
actions: read
+ contents: read
issues: write
steps:
- name: Checkout repository
@@ -457,12 +458,22 @@ jobs:
`)
yaml.WriteString(generateInstallCLISteps(actionMode, version, actionTag, resolver))
+ yaml.WriteString(` - name: Cache activity report logs
+ uses: ` + getActionPin("actions/cache") + `
+ with:
+ path: ./.cache/gh-aw/activity-report-logs
+ key: ${{ runner.os }}-activity-report-logs-` + repoSlug + `-${{ github.ref_name }}
+ restore-keys: |
+ ${{ runner.os }}-activity-report-logs-` + repoSlug + `-
+ ${{ runner.os }}-activity-report-logs-
+`)
yaml.WriteString(` - name: Generate agentic workflow activity report in target repository
uses: ` + getCachedActionPinFromResolver("actions/github-script", resolver) + `
env:
GH_TOKEN: ` + token + `
GH_AW_CMD_PREFIX: ` + getCLICmdPrefix(actionMode) + `
GH_AW_TARGET_REPO_SLUG: "` + repoSlug + `"
+ GH_AW_ACTIVITY_REPORT_OUTPUT_DIR: ./.cache/gh-aw/activity-report-logs
with:
github-token: ` + token + `
script: |
diff --git a/pkg/workflow/side_repo_maintenance_integration_test.go b/pkg/workflow/side_repo_maintenance_integration_test.go
index 64c4fc94952..6d54679e621 100644
--- a/pkg/workflow/side_repo_maintenance_integration_test.go
+++ b/pkg/workflow/side_repo_maintenance_integration_test.go
@@ -90,6 +90,12 @@ This workflow operates on a separate repository.
// Must have activity_report job.
assert.Contains(t, contentStr, "activity_report:",
"generated workflow should include activity_report job")
+ assert.Contains(t, contentStr, "Cache activity report logs",
+ "generated workflow should include cache step for activity_report logs")
+ assert.Contains(t, contentStr, "GH_AW_ACTIVITY_REPORT_OUTPUT_DIR: ./.cache/gh-aw/activity-report-logs",
+ "generated workflow should set GH_AW_ACTIVITY_REPORT_OUTPUT_DIR for activity_report logs")
+ assert.Contains(t, contentStr, "actions: read\n contents: read\n issues: write",
+ "activity_report job should include contents: read with explicit permissions")
// GH_AW_TARGET_REPO_SLUG must be wired with the correct slug.
assert.Contains(t, contentStr, `GH_AW_TARGET_REPO_SLUG: "my-org/target-repo"`,
From 986870450bfa26d156d6b8446540a0755cf2eb81 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sun, 19 Apr 2026 22:04:42 +0000
Subject: [PATCH 08/14] chore: plan timeout update for activity report job
Agent-Logs-Url: https://github.com/github/gh-aw/sessions/3ee21205-4c7f-42f8-bae5-186916afc5a1
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
---
.github/workflows/agentics-maintenance.yml | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/.github/workflows/agentics-maintenance.yml b/.github/workflows/agentics-maintenance.yml
index 21f18014915..e53af01a221 100644
--- a/.github/workflows/agentics-maintenance.yml
+++ b/.github/workflows/agentics-maintenance.yml
@@ -350,14 +350,13 @@ jobs:
run: make build
- name: Cache activity report logs
- uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v5.0.5
+ uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
path: ./.cache/gh-aw/activity-report-logs
key: ${{ runner.os }}-activity-report-logs-${{ github.repository }}-${{ github.ref_name }}
restore-keys: |
${{ runner.os }}-activity-report-logs-${{ github.repository }}-
${{ runner.os }}-activity-report-logs-
-
- name: Generate agentic workflow activity report
uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9
env:
From 0bf0d88f92a380adcc1c7c6b617430fb7ecb5d78 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sun, 19 Apr 2026 22:12:06 +0000
Subject: [PATCH 09/14] feat: set 2-hour timeout for activity report jobs
Agent-Logs-Url: https://github.com/github/gh-aw/sessions/3ee21205-4c7f-42f8-bae5-186916afc5a1
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
---
.github/workflows/agentics-maintenance.yml | 1 +
pkg/workflow/maintenance_workflow_test.go | 3 +++
pkg/workflow/maintenance_workflow_yaml.go | 1 +
pkg/workflow/side_repo_maintenance.go | 1 +
pkg/workflow/side_repo_maintenance_integration_test.go | 2 ++
5 files changed, 8 insertions(+)
diff --git a/.github/workflows/agentics-maintenance.yml b/.github/workflows/agentics-maintenance.yml
index e53af01a221..6f18c1a9a06 100644
--- a/.github/workflows/agentics-maintenance.yml
+++ b/.github/workflows/agentics-maintenance.yml
@@ -315,6 +315,7 @@ jobs:
activity_report:
if: ${{ (github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call') && inputs.operation == 'activity_report' && (!(github.event.repository.fork)) }}
runs-on: ubuntu-slim
+ timeout-minutes: 120
permissions:
actions: read
contents: read
diff --git a/pkg/workflow/maintenance_workflow_test.go b/pkg/workflow/maintenance_workflow_test.go
index 00356b5a48b..a5750b65ac1 100644
--- a/pkg/workflow/maintenance_workflow_test.go
+++ b/pkg/workflow/maintenance_workflow_test.go
@@ -380,6 +380,9 @@ func TestGenerateMaintenanceWorkflow_OperationJobConditions(t *testing.T) {
if !strings.Contains(activityReportSection, "contents: read") {
t.Errorf("Job activity_report should include contents: read permission in:\n%s", activityReportSection)
}
+ if !strings.Contains(activityReportSection, "timeout-minutes: 120") {
+ t.Errorf("Job activity_report should set timeout-minutes: 120 in:\n%s", activityReportSection)
+ }
}
if !strings.Contains(yaml, "Cache activity report logs") {
t.Errorf("Job activity_report should include a cache step in:\n%s", yaml)
diff --git a/pkg/workflow/maintenance_workflow_yaml.go b/pkg/workflow/maintenance_workflow_yaml.go
index 60ef60c5c25..b8aabcd0ac1 100644
--- a/pkg/workflow/maintenance_workflow_yaml.go
+++ b/pkg/workflow/maintenance_workflow_yaml.go
@@ -355,6 +355,7 @@ jobs:
activity_report:
if: ${{ ` + RenderCondition(buildDispatchOperationCondition("activity_report")) + ` }}
runs-on: ` + runsOnValue + `
+ timeout-minutes: 120
permissions:
actions: read
contents: read
diff --git a/pkg/workflow/side_repo_maintenance.go b/pkg/workflow/side_repo_maintenance.go
index 53122edd5b1..f3951e2330f 100644
--- a/pkg/workflow/side_repo_maintenance.go
+++ b/pkg/workflow/side_repo_maintenance.go
@@ -430,6 +430,7 @@ jobs:
activity_report:
if: ${{ ` + RenderCondition(buildDispatchOperationCondition("activity_report")) + ` }}
runs-on: ` + runsOnValue + `
+ timeout-minutes: 120
permissions:
actions: read
contents: read
diff --git a/pkg/workflow/side_repo_maintenance_integration_test.go b/pkg/workflow/side_repo_maintenance_integration_test.go
index 6d54679e621..4bcfc2399c4 100644
--- a/pkg/workflow/side_repo_maintenance_integration_test.go
+++ b/pkg/workflow/side_repo_maintenance_integration_test.go
@@ -96,6 +96,8 @@ This workflow operates on a separate repository.
"generated workflow should set GH_AW_ACTIVITY_REPORT_OUTPUT_DIR for activity_report logs")
assert.Contains(t, contentStr, "actions: read\n contents: read\n issues: write",
"activity_report job should include contents: read with explicit permissions")
+ assert.Contains(t, contentStr, "timeout-minutes: 120",
+ "activity_report job should include a 2 hour timeout")
// GH_AW_TARGET_REPO_SLUG must be wired with the correct slug.
assert.Contains(t, contentStr, `GH_AW_TARGET_REPO_SLUG: "my-org/target-repo"`,
From ea685c606544fbd2dda513951aa75d0666a1abcf Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sun, 19 Apr 2026 22:15:46 +0000
Subject: [PATCH 10/14] chore: keep activity report cache pin stable in
workflow yaml
Agent-Logs-Url: https://github.com/github/gh-aw/sessions/3ee21205-4c7f-42f8-bae5-186916afc5a1
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
---
.github/workflows/agentics-maintenance.yml | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/.github/workflows/agentics-maintenance.yml b/.github/workflows/agentics-maintenance.yml
index 6f18c1a9a06..85434897f20 100644
--- a/.github/workflows/agentics-maintenance.yml
+++ b/.github/workflows/agentics-maintenance.yml
@@ -351,13 +351,14 @@ jobs:
run: make build
- name: Cache activity report logs
- uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
+ uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v5.0.5
with:
path: ./.cache/gh-aw/activity-report-logs
key: ${{ runner.os }}-activity-report-logs-${{ github.repository }}-${{ github.ref_name }}
restore-keys: |
${{ runner.os }}-activity-report-logs-${{ github.repository }}-
${{ runner.os }}-activity-report-logs-
+
- name: Generate agentic workflow activity report
uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9
env:
From 116ffb92038017d93d48e917d1565fdb46e1b7a7 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sun, 19 Apr 2026 22:20:27 +0000
Subject: [PATCH 11/14] chore: plan cache key update for latest restore
behavior
Agent-Logs-Url: https://github.com/github/gh-aw/sessions/63d7139a-2204-468c-97f5-35631eb4bf35
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
---
.github/workflows/agentics-maintenance.yml | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/.github/workflows/agentics-maintenance.yml b/.github/workflows/agentics-maintenance.yml
index 85434897f20..6f18c1a9a06 100644
--- a/.github/workflows/agentics-maintenance.yml
+++ b/.github/workflows/agentics-maintenance.yml
@@ -351,14 +351,13 @@ jobs:
run: make build
- name: Cache activity report logs
- uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v5.0.5
+ uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
path: ./.cache/gh-aw/activity-report-logs
key: ${{ runner.os }}-activity-report-logs-${{ github.repository }}-${{ github.ref_name }}
restore-keys: |
${{ runner.os }}-activity-report-logs-${{ github.repository }}-
${{ runner.os }}-activity-report-logs-
-
- name: Generate agentic workflow activity report
uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9
env:
From f74b4061ac9c54240298a674afd5ac44d526f2a2 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sun, 19 Apr 2026 22:27:08 +0000
Subject: [PATCH 12/14] feat: use per-run cache keys for activity report logs
Agent-Logs-Url: https://github.com/github/gh-aw/sessions/63d7139a-2204-468c-97f5-35631eb4bf35
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
---
.github/workflows/agentics-maintenance.yml | 2 +-
pkg/workflow/maintenance_workflow_test.go | 4 ++++
pkg/workflow/maintenance_workflow_yaml.go | 2 +-
pkg/workflow/side_repo_maintenance.go | 2 +-
pkg/workflow/side_repo_maintenance_integration_test.go | 2 ++
5 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/.github/workflows/agentics-maintenance.yml b/.github/workflows/agentics-maintenance.yml
index 6f18c1a9a06..bce44757eaa 100644
--- a/.github/workflows/agentics-maintenance.yml
+++ b/.github/workflows/agentics-maintenance.yml
@@ -354,7 +354,7 @@ jobs:
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
path: ./.cache/gh-aw/activity-report-logs
- key: ${{ runner.os }}-activity-report-logs-${{ github.repository }}-${{ github.ref_name }}
+ key: ${{ runner.os }}-activity-report-logs-${{ github.repository }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }}
restore-keys: |
${{ runner.os }}-activity-report-logs-${{ github.repository }}-
${{ runner.os }}-activity-report-logs-
diff --git a/pkg/workflow/maintenance_workflow_test.go b/pkg/workflow/maintenance_workflow_test.go
index a5750b65ac1..30e70b42bb6 100644
--- a/pkg/workflow/maintenance_workflow_test.go
+++ b/pkg/workflow/maintenance_workflow_test.go
@@ -387,6 +387,10 @@ func TestGenerateMaintenanceWorkflow_OperationJobConditions(t *testing.T) {
if !strings.Contains(yaml, "Cache activity report logs") {
t.Errorf("Job activity_report should include a cache step in:\n%s", yaml)
}
+ if !strings.Contains(yaml, "${{ github.run_id }}-${{ github.run_attempt }}") {
+ t.Errorf("Job activity_report cache key should include run_id and run_attempt for latest-cache resolution in:\n%s", yaml)
+ }
+
if !strings.Contains(yaml, "GH_AW_ACTIVITY_REPORT_OUTPUT_DIR: ./.cache/gh-aw/activity-report-logs") {
t.Errorf("Job activity_report should set GH_AW_ACTIVITY_REPORT_OUTPUT_DIR in:\n%s", yaml)
}
diff --git a/pkg/workflow/maintenance_workflow_yaml.go b/pkg/workflow/maintenance_workflow_yaml.go
index b8aabcd0ac1..f3ee28eb7b0 100644
--- a/pkg/workflow/maintenance_workflow_yaml.go
+++ b/pkg/workflow/maintenance_workflow_yaml.go
@@ -388,7 +388,7 @@ jobs:
uses: ` + getActionPin("actions/cache") + `
with:
path: ./.cache/gh-aw/activity-report-logs
- key: ${{ runner.os }}-activity-report-logs-${{ github.repository }}-${{ github.ref_name }}
+ key: ${{ runner.os }}-activity-report-logs-${{ github.repository }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }}
restore-keys: |
${{ runner.os }}-activity-report-logs-${{ github.repository }}-
${{ runner.os }}-activity-report-logs-
diff --git a/pkg/workflow/side_repo_maintenance.go b/pkg/workflow/side_repo_maintenance.go
index f3951e2330f..a09c2f4a15d 100644
--- a/pkg/workflow/side_repo_maintenance.go
+++ b/pkg/workflow/side_repo_maintenance.go
@@ -463,7 +463,7 @@ jobs:
uses: ` + getActionPin("actions/cache") + `
with:
path: ./.cache/gh-aw/activity-report-logs
- key: ${{ runner.os }}-activity-report-logs-` + repoSlug + `-${{ github.ref_name }}
+ key: ${{ runner.os }}-activity-report-logs-` + repoSlug + `-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }}
restore-keys: |
${{ runner.os }}-activity-report-logs-` + repoSlug + `-
${{ runner.os }}-activity-report-logs-
diff --git a/pkg/workflow/side_repo_maintenance_integration_test.go b/pkg/workflow/side_repo_maintenance_integration_test.go
index 4bcfc2399c4..19ac8eb8c9f 100644
--- a/pkg/workflow/side_repo_maintenance_integration_test.go
+++ b/pkg/workflow/side_repo_maintenance_integration_test.go
@@ -98,6 +98,8 @@ This workflow operates on a separate repository.
"activity_report job should include contents: read with explicit permissions")
assert.Contains(t, contentStr, "timeout-minutes: 120",
"activity_report job should include a 2 hour timeout")
+ assert.Contains(t, contentStr, "${{ github.run_id }}-${{ github.run_attempt }}",
+ "activity_report cache key should include run id and attempt for latest-cache resolution")
// GH_AW_TARGET_REPO_SLUG must be wired with the correct slug.
assert.Contains(t, contentStr, `GH_AW_TARGET_REPO_SLUG: "my-org/target-repo"`,
From aa64a4626f4d13c87fcecea65e49ec46d4fb4014 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sun, 19 Apr 2026 22:40:46 +0000
Subject: [PATCH 13/14] chore: use github.run_id in activity report cache keys
Agent-Logs-Url: https://github.com/github/gh-aw/sessions/12531c2f-2b64-4d48-a924-0808d53f98c2
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
---
.github/workflows/agentics-maintenance.yml | 2 +-
pkg/workflow/maintenance_workflow_test.go | 4 ++--
pkg/workflow/maintenance_workflow_yaml.go | 2 +-
pkg/workflow/side_repo_maintenance.go | 2 +-
pkg/workflow/side_repo_maintenance_integration_test.go | 4 ++--
5 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/.github/workflows/agentics-maintenance.yml b/.github/workflows/agentics-maintenance.yml
index bce44757eaa..226acf666f4 100644
--- a/.github/workflows/agentics-maintenance.yml
+++ b/.github/workflows/agentics-maintenance.yml
@@ -354,7 +354,7 @@ jobs:
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
path: ./.cache/gh-aw/activity-report-logs
- key: ${{ runner.os }}-activity-report-logs-${{ github.repository }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }}
+ key: ${{ runner.os }}-activity-report-logs-${{ github.repository }}-${{ github.ref_name }}-${{ github.run_id }}
restore-keys: |
${{ runner.os }}-activity-report-logs-${{ github.repository }}-
${{ runner.os }}-activity-report-logs-
diff --git a/pkg/workflow/maintenance_workflow_test.go b/pkg/workflow/maintenance_workflow_test.go
index 30e70b42bb6..a8174de8eb0 100644
--- a/pkg/workflow/maintenance_workflow_test.go
+++ b/pkg/workflow/maintenance_workflow_test.go
@@ -387,8 +387,8 @@ func TestGenerateMaintenanceWorkflow_OperationJobConditions(t *testing.T) {
if !strings.Contains(yaml, "Cache activity report logs") {
t.Errorf("Job activity_report should include a cache step in:\n%s", yaml)
}
- if !strings.Contains(yaml, "${{ github.run_id }}-${{ github.run_attempt }}") {
- t.Errorf("Job activity_report cache key should include run_id and run_attempt for latest-cache resolution in:\n%s", yaml)
+ if !strings.Contains(yaml, "${{ github.run_id }}") {
+ t.Errorf("Job activity_report cache key should include run_id for latest-cache resolution in:\n%s", yaml)
}
if !strings.Contains(yaml, "GH_AW_ACTIVITY_REPORT_OUTPUT_DIR: ./.cache/gh-aw/activity-report-logs") {
diff --git a/pkg/workflow/maintenance_workflow_yaml.go b/pkg/workflow/maintenance_workflow_yaml.go
index f3ee28eb7b0..91a701fb911 100644
--- a/pkg/workflow/maintenance_workflow_yaml.go
+++ b/pkg/workflow/maintenance_workflow_yaml.go
@@ -388,7 +388,7 @@ jobs:
uses: ` + getActionPin("actions/cache") + `
with:
path: ./.cache/gh-aw/activity-report-logs
- key: ${{ runner.os }}-activity-report-logs-${{ github.repository }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }}
+ key: ${{ runner.os }}-activity-report-logs-${{ github.repository }}-${{ github.ref_name }}-${{ github.run_id }}
restore-keys: |
${{ runner.os }}-activity-report-logs-${{ github.repository }}-
${{ runner.os }}-activity-report-logs-
diff --git a/pkg/workflow/side_repo_maintenance.go b/pkg/workflow/side_repo_maintenance.go
index a09c2f4a15d..a490ee7a171 100644
--- a/pkg/workflow/side_repo_maintenance.go
+++ b/pkg/workflow/side_repo_maintenance.go
@@ -463,7 +463,7 @@ jobs:
uses: ` + getActionPin("actions/cache") + `
with:
path: ./.cache/gh-aw/activity-report-logs
- key: ${{ runner.os }}-activity-report-logs-` + repoSlug + `-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }}
+ key: ${{ runner.os }}-activity-report-logs-` + repoSlug + `-${{ github.ref_name }}-${{ github.run_id }}
restore-keys: |
${{ runner.os }}-activity-report-logs-` + repoSlug + `-
${{ runner.os }}-activity-report-logs-
diff --git a/pkg/workflow/side_repo_maintenance_integration_test.go b/pkg/workflow/side_repo_maintenance_integration_test.go
index 19ac8eb8c9f..9cdfcb3cec6 100644
--- a/pkg/workflow/side_repo_maintenance_integration_test.go
+++ b/pkg/workflow/side_repo_maintenance_integration_test.go
@@ -98,8 +98,8 @@ This workflow operates on a separate repository.
"activity_report job should include contents: read with explicit permissions")
assert.Contains(t, contentStr, "timeout-minutes: 120",
"activity_report job should include a 2 hour timeout")
- assert.Contains(t, contentStr, "${{ github.run_id }}-${{ github.run_attempt }}",
- "activity_report cache key should include run id and attempt for latest-cache resolution")
+ assert.Contains(t, contentStr, "${{ github.run_id }}",
+ "activity_report cache key should include run id for latest-cache resolution")
// GH_AW_TARGET_REPO_SLUG must be wired with the correct slug.
assert.Contains(t, contentStr, `GH_AW_TARGET_REPO_SLUG: "my-org/target-repo"`,
From 7b8183fde6d6a3798fb3a5afc6c7a9ee90e41e87 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sun, 19 Apr 2026 23:26:53 +0000
Subject: [PATCH 14/14] chore: remove 30 day activity report section
Agent-Logs-Url: https://github.com/github/gh-aw/sessions/398968c8-4b25-42c6-a1f1-6c382a43f2f3
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
---
actions/setup/js/run_activity_report.cjs | 1 -
actions/setup/js/run_activity_report.test.cjs | 32 +++----------------
2 files changed, 4 insertions(+), 29 deletions(-)
diff --git a/actions/setup/js/run_activity_report.cjs b/actions/setup/js/run_activity_report.cjs
index d2944beebc3..27cd0cb920a 100644
--- a/actions/setup/js/run_activity_report.cjs
+++ b/actions/setup/js/run_activity_report.cjs
@@ -16,7 +16,6 @@ const DEFAULT_REPORT_OUTPUT_DIR = "./.cache/gh-aw/activity-report-logs";
const REPORT_RANGES = [
{ key: "24h", heading: "Last 24 hours", startDate: "-1d", optionalOnRateLimit: false },
{ key: "7d", heading: "Last 7 days", startDate: "-1w", optionalOnRateLimit: false },
- { key: "30d", heading: "Last 30 days", startDate: "-1mo", optionalOnRateLimit: true },
];
/**
diff --git a/actions/setup/js/run_activity_report.test.cjs b/actions/setup/js/run_activity_report.test.cjs
index 549d9caff83..e858ee64d48 100644
--- a/actions/setup/js/run_activity_report.test.cjs
+++ b/actions/setup/js/run_activity_report.test.cjs
@@ -58,16 +58,13 @@ describe("run_activity_report", () => {
vi.clearAllMocks();
});
- it("creates an activity report issue with all three time ranges", async () => {
- mockExec.getExecOutput
- .mockResolvedValueOnce({ stdout: "## 24h report\nok", stderr: "", exitCode: 0 })
- .mockResolvedValueOnce({ stdout: "## 7d report\nok", stderr: "", exitCode: 0 })
- .mockResolvedValueOnce({ stdout: "## 30d report\nok", stderr: "", exitCode: 0 });
+ it("creates an activity report issue with 24h and 7d time ranges", async () => {
+ mockExec.getExecOutput.mockResolvedValueOnce({ stdout: "## 24h report\nok", stderr: "", exitCode: 0 }).mockResolvedValueOnce({ stdout: "## 7d report\nok", stderr: "", exitCode: 0 });
const { main } = await import("./run_activity_report.cjs");
await main();
- expect(mockExec.getExecOutput).toHaveBeenCalledTimes(3);
+ expect(mockExec.getExecOutput).toHaveBeenCalledTimes(2);
expect(mockExec.getExecOutput).toHaveBeenNthCalledWith(
1,
"gh",
@@ -80,13 +77,6 @@ describe("run_activity_report", () => {
expect.arrayContaining(["aw", "logs", "--repo", "testowner/testrepo", "--start-date", "-1w", "--count", "1000", "--output", "./.cache/gh-aw/activity-report-logs", "--format", "markdown"]),
expect.objectContaining({ ignoreReturnCode: true })
);
- expect(mockExec.getExecOutput).toHaveBeenNthCalledWith(
- 3,
- "gh",
- expect.arrayContaining(["aw", "logs", "--repo", "testowner/testrepo", "--start-date", "-1mo", "--count", "1000", "--output", "./.cache/gh-aw/activity-report-logs", "--format", "markdown"]),
- expect.objectContaining({ ignoreReturnCode: true })
- );
-
expect(mockGithub.rest.issues.create).toHaveBeenCalledWith(
expect.objectContaining({
owner: "testowner",
@@ -101,24 +91,10 @@ describe("run_activity_report", () => {
expect(issueBody).toContain("");
expect(issueBody).toContain("Last 24 hours
");
expect(issueBody).toContain("Last 7 days
");
- expect(issueBody).toContain("Last 30 days
");
+ expect(issueBody).not.toContain("Last 30 days
");
expect(issueBody).toContain("#### 24h report");
});
- it("skips the 30-day query when rate limited", async () => {
- mockExec.getExecOutput
- .mockResolvedValueOnce({ stdout: "24h", stderr: "", exitCode: 0 })
- .mockResolvedValueOnce({ stdout: "7d", stderr: "", exitCode: 0 })
- .mockResolvedValueOnce({ stdout: "", stderr: "API rate limit exceeded", exitCode: 1 });
-
- const { main } = await import("./run_activity_report.cjs");
- await main();
-
- expect(mockCore.warning).toHaveBeenCalledWith(expect.stringContaining("Skipping Last 30 days report"));
- const issueBody = mockGithub.rest.issues.create.mock.calls[0][0].body;
- expect(issueBody).toContain("Skipped due to GitHub API rate limiting.");
- });
-
it("detects rate limit text helper", async () => {
const { hasRateLimitText } = await import("./run_activity_report.cjs");
expect(hasRateLimitText("API rate limit exceeded")).toBe(true);