Skip to content

Add push trigger on repository default branch for .github/workflows/*.md to agentic maintenance workflow generator#28295

Merged
pelikhan merged 4 commits intomainfrom
copilot/update-agentic-maintenance-action
Apr 24, 2026
Merged

Add push trigger on repository default branch for .github/workflows/*.md to agentic maintenance workflow generator#28295
pelikhan merged 4 commits intomainfrom
copilot/update-agentic-maintenance-action

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 24, 2026

Summary

Updates the Agentic Maintenance workflow generator so the generated agentics-maintenance.yml also triggers on pushes to the repository's default branch that affect .github/workflows/*.md files. When this push event fires, only the compile-workflows job runs — all other scheduled jobs are excluded. The compile-workflows job also uses a concurrency group with cancel-in-progress: true so redundant builds are cancelled when a new push arrives.

Changes

Generator changes (pkg/workflow/)

  • maintenance_conditions.go:

    • Added buildNotForkAndScheduleOnly() — same as buildNotForkAndScheduled() but adds an explicit github.event_name != 'push' guard
    • Added buildNotForkAndScheduleOnlyOrOperation() — same as the removed buildNotForkAndScheduledOrOperation() but also excludes push events
    • Removed now-unused buildNotForkAndScheduledOrOperation() (all callers migrated)
    • Clarified buildNotForkAndScheduled() comment to make clear it intentionally includes push events
  • maintenance_workflow.go:

    • Added FetchDefaultBranch(slug string) string — queries gh api /repos/{slug} --jq .default_branch at compilation time to determine the repository's default branch, falling back to "main" when the slug is empty or the API call fails
    • Added repoSlug string parameter to GenerateMaintenanceWorkflow to thread the repository slug through to branch resolution
  • compiler_types.go:

    • Added GetRepositorySlug() getter on Compiler to expose the already-resolved repository slug
  • maintenance_workflow_yaml.go:

    • Added push trigger (dev mode only, since compile-workflows is dev-mode only) using the API-resolved default branch:
      push:
        branches:
          - <default-branch>   # resolved via GitHub API at compile time
        paths:
          - '.github/workflows/*.md'
    • Added concurrency group to compile-workflows job with cancel-in-progress: true:
      concurrency:
        group: ${{ github.workflow }}-compile-workflows-${{ github.repository }}
        cancel-in-progress: true
    • Updated close-expired-entities, cleanup-cache-memory, and secret-validation job conditions to use the new push-excluding builders
    • compile-workflows condition is unchanged — it uses buildNotForkAndScheduled() which includes push events
  • compile_post_processing.go and init.go:

    • Pass compiler.GetRepositorySlug() to GenerateMaintenanceWorkflow so the default branch can be resolved at compile time
  • maintenance_workflow_test.go:

    • Added TestGenerateMaintenanceWorkflow_PushTrigger with sub-tests verifying push trigger presence in dev mode, absence in release mode, push exclusion on schedule-only jobs, push inclusion for compile-workflows, concurrency group, and correct substitution of a custom branch name

Generated file

  • .github/workflows/agentics-maintenance.yml: Regenerated via make recompile

Generated output (agentics-maintenance.yml)

on:
  schedule:
    - cron: "37 */2 * * *"
  push:
    branches:
      - main   # resolved via GitHub API; value reflects the actual default branch
    paths:
      - '.github/workflows/*.md'
  workflow_dispatch: ...

jobs:
  close-expired-entities:
    if: ${{ (!(github.event.repository.fork)) && github.event_name != 'push' && (...) }}
  cleanup-cache-memory:
    if: ${{ (!(github.event.repository.fork)) && github.event_name != 'push' && (...) }}
  compile-workflows:
    if: ${{ (!(github.event.repository.fork)) && (...) }}  # no push exclusion → runs on push
    concurrency:
      group: ${{ github.workflow }}-compile-workflows-${{ github.repository }}
      cancel-in-progress: true
  secret-validation:
    if: ${{ (!(github.event.repository.fork)) && github.event_name != 'push' && (...) }}

Copilot AI and others added 2 commits April 24, 2026 15:06
…ows job in maintenance workflow generator

Agent-Logs-Url: https://github.com/github/gh-aw/sessions/520bb413-72d8-43b4-8d6f-9bcc967cedf2

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
…solidate test constant

Agent-Logs-Url: https://github.com/github/gh-aw/sessions/520bb413-72d8-43b4-8d6f-9bcc967cedf2

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copy link
Copy Markdown
Collaborator

@pelikhan pelikhan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot use github api to determine default branch at compilation time (could be other than main)

Copy link
Copy Markdown
Contributor Author

Copilot AI commented Apr 24, 2026

@copilot use github api to determine default branch at compilation time (could be other than main)

Done in commit 40b5c2b. Added FetchDefaultBranch(slug string) string in maintenance_workflow.go that calls gh api /repos/{slug} --jq .default_branch at compilation time, falling back to "main" when the slug is empty or the API call fails. The compiler's repository slug (already resolved from git remote) is passed through to GenerateMaintenanceWorkflow and used to populate the push trigger branch.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • https://api.github.com/graphql
    • Triggering command: /usr/bin/gh /usr/bin/gh api graphql -f query=query($owner: String!, $name: String!) { repository(owner: $owner, name: $name) { hasDiscussionsEnabled } } -f owner=github -f name=gh-aw GOMOD GOMODCACHE sh -c npx prettier --cGOINSECURE GOPROXY 64/bin/go GOSUMDB GOWORK 64/bin/go sh (http block)
    • Triggering command: /usr/bin/gh /usr/bin/gh api graphql -f query=query($owner: String!, $name: String!) { repository(owner: $owner, name: $name) { hasDiscussionsEnabled } } -f owner=github -f name=gh-aw GOMOD GOMODCACHE sh -c npx prettier --cGOINSECURE GOPROXY 64/bin/go GOSUMDB GOWORK 64/bin/go prettier (http block)
    • Triggering command: /usr/bin/gh /usr/bin/gh api graphql -f query=query($owner: String!, $name: String!) { repository(owner: $owner, name: $name) { hasDiscussionsEnabled } } -f owner=github -f name=gh-aw GOMOD GOMODCACHE sh -c npx prettier --cGOINSECURE GOPROXY 64/bin/go GOSUMDB GOWORK 64/bin/go node (http block)
  • https://api.github.com/repos/actions/github-script/git/ref/tags/v9
    • Triggering command: /usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v9 --jq [.object.sha, .object.type] | @tsv (http block)
  • https://api.github.com/repos/astral-sh/setup-uv/git/ref/tags/eac588ad8def6316056a12d4907a9d4d84ff7a3b
    • Triggering command: /usr/bin/gh gh api /repos/astral-sh/setup-uv/git/ref/tags/eac588ad8def6316056a12d4907a9d4d84ff7a3b --jq [.object.sha, .object.type] | @tsv GOSUMDB GOWORK 64/bin/go GOINSECURE GOMOD GOMODCACHE node /opt�� prettier --check 64/bin/go **/*.ts **/*.json --ignore-path /bin/sh (http block)
    • Triggering command: /usr/bin/gh gh api /repos/astral-sh/setup-uv/git/ref/tags/eac588ad8def6316056a12d4907a9d4d84ff7a3b --jq [.object.sha, .object.type] | @tsv che/go-build/84/GOINSECURE GOPROXY $name) { hasDiscussionsEnabled } } GOSUMDB GOWORK 64/bin/go /opt/hostedtoolcGOPROXY -o /tmp/go-build173GOSUMDB -trimpath 64/bin/go -p main -lang=go1.25 go (http block)
    • Triggering command: /usr/bin/gh gh api /repos/astral-sh/setup-uv/git/ref/tags/eac588ad8def6316056a12d4907a9d4d84ff7a3b --jq [.object.sha, .object.type] | @tsv che/go-build/4c/GOINSECURE GOPROXY 64/bin/go GOSUMDB GOWORK 64/bin/go /opt/hostedtoolclog -o /tmp/go-build173--format=%H:%ct -trimpath 64/bin/go -p main -lang=go1.25 go (http block)
  • https://api.github.com/repos/github/gh-aw
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw --jq .default_branch -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go env -json GO111MODULE repository(owner: $owner, name: $name) { hasDiscussionsEnabled } } GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/github/gh-aw/git/ref/tags/v0.47.4
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v0.47.4 --jq [.object.sha, .object.type] | @tsv (http block)

If you need me to access, download, or install something from one of these locations, you can either:

Copilot AI changed the title Add push trigger on main for .github/workflows/*.md to agentic maintenance workflow generator Add push trigger on repository default branch for .github/workflows/*.md to agentic maintenance workflow generator Apr 24, 2026
Copilot AI requested a review from pelikhan April 24, 2026 15:32
@pelikhan
Copy link
Copy Markdown
Collaborator

@copilot set group concurrency to cancel if a new build arrives for the compile workflows job

Copy link
Copy Markdown
Contributor Author

Copilot AI commented Apr 24, 2026

@copilot set group concurrency to cancel if a new build arrives for the compile workflows job

Done in commit 90227ad. Added a concurrency block to the compile-workflows job with a repository-scoped group and cancel-in-progress: true:

concurrency:
  group: ${{ github.workflow }}-compile-workflows-${{ github.repository }}
  cancel-in-progress: true

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • https://api.github.com/graphql
    • Triggering command: /usr/bin/gh /usr/bin/gh api graphql -f query=query($owner: String!, $name: String!) { repository(owner: $owner, name: $name) { hasDiscussionsEnabled } } -f owner=github -f name=gh-aw (http block)
    • Triggering command: /usr/bin/gh /usr/bin/gh api graphql -f query=query($owner: String!, $name: String!) { repository(owner: $owner, name: $name) { hasDiscussionsEnabled } } -f owner=github -f name=gh-aw -pack /home/REDACTED/work/gh-aw/gh-aw/cmd/gh-aw/main.go 1bOMNmH/mD0eoqAsG7MdR58Q4AA3 /pre�� (http block)
    • Triggering command: /usr/bin/gh /usr/bin/gh api graphql -f query=query($owner: String!, $name: String!) { repository(owner: $owner, name: $name) { hasDiscussionsEnabled } } -f owner=github -f name=gh-aw rdian.lock.yml y.lock.yml lock.yml t-is�� re --log-level=e!../../../pkg/workflow/js/**/*.json tigator.lock.yml--ignore-path /prettier (http block)
  • https://api.github.com/repos/astral-sh/setup-uv/git/ref/tags/eac588ad8def6316056a12d4907a9d4d84ff7a3b
    • Triggering command: /usr/bin/gh gh api /repos/astral-sh/setup-uv/git/ref/tags/eac588ad8def6316056a12d4907a9d4d84ff7a3b --jq [.object.sha, .object.type] | @tsv (http block)
    • Triggering command: /usr/bin/gh gh api /repos/astral-sh/setup-uv/git/ref/tags/eac588ad8def6316056a12d4907a9d4d84ff7a3b --jq [.object.sha, .object.type] | @tsv h ../../../.prettierignore (http block)
  • https://api.github.com/repos/github/gh-aw
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw --jq .default_branch */*.ts&#39; &#39;**/*.json&#39; --ignore-path ../../../.pret.prettierignore --local tions/setup/node_modules/.bin/node http.https://gitgit (http block)

If you need me to access, download, or install something from one of these locations, you can either:

@pelikhan pelikhan marked this pull request as ready for review April 24, 2026 16:04
Copilot AI review requested due to automatic review settings April 24, 2026 16:04
@pelikhan pelikhan merged commit 4e74571 into main Apr 24, 2026
29 checks passed
@pelikhan pelikhan deleted the copilot/update-agentic-maintenance-action branch April 24, 2026 16:05
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Updates the Agentic Maintenance workflow generator to add a dev-mode push trigger (scoped to default-branch changes to .github/workflows/*.md) and to ensure only the compile-workflows job runs for those push events, with concurrency configured to cancel redundant runs.

Changes:

  • Add dev-mode push trigger on the repo default branch for .github/workflows/*.md changes.
  • Update job if: conditions so schedule-only jobs exclude push events while compile-workflows still runs on push.
  • Add compile-workflows job concurrency and thread repository slug/default-branch resolution through the generator + tests.
Show a summary per file
File Description
pkg/workflow/side_repo_maintenance_integration_test.go Updates generator invocation to pass new repoSlug parameter.
pkg/workflow/maintenance_workflow_yaml.go Emits dev-mode push trigger, updates job conditions, adds compile-workflows concurrency.
pkg/workflow/maintenance_workflow_test.go Adds/updates tests for push trigger behavior, job conditions, and concurrency.
pkg/workflow/maintenance_workflow.go Adds default-branch resolution via gh api and threads it into YAML generation.
pkg/workflow/maintenance_conditions.go Introduces push-excluding condition builders for schedule-only jobs.
pkg/workflow/compiler_types.go Exposes repository slug via GetRepositorySlug().
pkg/cli/init.go Passes compiler repository slug into maintenance workflow generation.
pkg/cli/compile_post_processing.go Passes compiler repository slug into maintenance workflow generation.
.github/workflows/agentics-maintenance.yml Regenerated workflow including push trigger and compile-workflows concurrency.

Copilot's findings

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comments suppressed due to low confidence (1)

pkg/workflow/maintenance_workflow_test.go:651

  • Same out-of-bounds slicing risk here: jobSection := yaml[compileIdx : compileIdx+jobSectionSearchRange] can panic if the YAML is shorter than expected. Bound the slice end with min(len(yaml), compileIdx+jobSectionSearchRange) to keep the test robust.
		jobSection := yaml[compileIdx : compileIdx+jobSectionSearchRange]
		if strings.Contains(jobSection, "github.event_name != 'push'") {
			t.Errorf("Job compile-workflows should NOT exclude push events, but condition is:\n%s", jobSection)
		}
  • Files reviewed: 9/9 changed files
  • Comments generated: 4

Comment on lines +174 to +176
// Fetch the default branch for the push trigger (dev mode only)
// Resolved here to avoid passing it through multiple layers; empty slug falls back to "main"
defaultBranch := FetchDefaultBranch(repoSlug)
Copy link

Copilot AI Apr 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FetchDefaultBranch(repoSlug) is called unconditionally, so release-mode generation will still invoke gh api (or at least attempt to) even though the push trigger is only emitted in dev mode. This adds unnecessary network/auth dependency and can slow or flake non-dev runs. Consider only resolving the default branch when actionMode == ActionModeDev (or when the push trigger will be included), and otherwise pass an empty/default value through to buildMaintenanceWorkflowYAML.

Suggested change
// Fetch the default branch for the push trigger (dev mode only)
// Resolved here to avoid passing it through multiple layers; empty slug falls back to "main"
defaultBranch := FetchDefaultBranch(repoSlug)
// Fetch the default branch only when the dev-mode push trigger will be included.
// Outside dev mode, leave it empty so generation does not depend on gh/api auth or network access.
defaultBranch := ""
if actionMode == ActionModeDev {
defaultBranch = FetchDefaultBranch(repoSlug)
}

Copilot uses AI. Check for mistakes.
Comment on lines +52 to +56
yaml.WriteString(` push:
branches:
- ` + defaultBranch + `
paths:
- '.github/workflows/*.md'
Copy link

Copilot AI Apr 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

defaultBranch is interpolated into YAML without quoting/escaping. Unusual branch names (e.g. containing : or starting with YAML 1.1 boolean keywords like on/yes/no) or unexpected characters from the API response could produce invalid YAML or surprising parsing. Safer options: quote the branch value (e.g. single-quote with escaping) and/or validate it against an allowed branch-name pattern before writing, falling back to the default when invalid.

Copilot uses AI. Check for mistakes.
Comment on lines +625 to +628
jobSection := yaml[jobIdx : jobIdx+jobSectionSearchRange]
if !strings.Contains(jobSection, pushExclusionCondition) {
t.Errorf("Job %q should exclude push events (%q) but condition is:\n%s", job, pushExclusionCondition, jobSection)
}
Copy link

Copilot AI Apr 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test slices jobSection := yaml[jobIdx : jobIdx+jobSectionSearchRange] without checking bounds; if the generated YAML is shorter than jobIdx+jobSectionSearchRange this will panic and fail the test for an unrelated reason. Use end := min(len(yaml), jobIdx+jobSectionSearchRange) (similar to the earlier min(500, len(yaml)) usage) before slicing.

This issue also appears on line 648 of the same file.

Copilot uses AI. Check for mistakes.
// non-dispatch/call event including push, or on workflow_dispatch/workflow_call
// with an empty operation, and never on forks. Unlike buildNotForkAndScheduleOnly,
// this function does NOT exclude push events.
// Condition: !fork && ((event_name != 'workflow_dispatch' && event_name != 'workflow_call') || operation == ”)
Copy link

Copilot AI Apr 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This condition comment uses a typographic closing quote () rather than an ASCII quote, which makes the example hard to read/copy and is inconsistent with the rest of the file. Consider changing it to operation == '' (or operation == "") to match the actual expression being built.

Suggested change
// Condition: !fork && ((event_name != 'workflow_dispatch' && event_name != 'workflow_call') || operation == )
// Condition: !fork && ((event_name != 'workflow_dispatch' && event_name != 'workflow_call') || operation == '')

Copilot uses AI. Check for mistakes.
@github-actions
Copy link
Copy Markdown
Contributor

🧪 Test Quality Sentinel Report

Test Quality Score: 93/100

Excellent test quality

Metric Value
New/modified tests analyzed 6
✅ Design tests (behavioral contracts) 6 (100%)
⚠️ Implementation tests (low value) 0 (0%)
Tests with error/edge cases 5 (83%)
Duplicate test clusters 0
Test inflation detected No (ratio ≈ 1.55:1)
🚨 Coding-guideline violations None

Test Classification Details

View all 6 analyzed tests
Test File Classification Notes
TestGenerateMaintenanceWorkflow_PushTrigger/dev mode includes push trigger on main maintenance_workflow_test.go:553 ✅ Design Verifies generated YAML has correct push: trigger and branch
TestGenerateMaintenanceWorkflow_PushTrigger/dev mode uses custom default branch maintenance_workflow_test.go:576 ✅ Design Verifies branch name substitution in push trigger; calls internal helper directly but tests observable output
TestGenerateMaintenanceWorkflow_PushTrigger/release mode does not include push trigger maintenance_workflow_test.go:588 ✅ Design Negative-path: release mode must not emit push trigger
TestGenerateMaintenanceWorkflow_PushTrigger/close-expired-entities and secret-validation exclude push events maintenance_workflow_test.go:605 ✅ Design Verifies github.event_name != 'push' guard on schedule-only jobs
TestGenerateMaintenanceWorkflow_PushTrigger/compile-workflows runs on push events maintenance_workflow_test.go:632 ✅ Design Verifies compile-workflows job has no push exclusion, has cancel-in-progress concurrency
side_repo_maintenance_integration_test.go (signature updates, +5/-5) side_repo_maintenance_integration_test.go ✅ Design Minor call-site update — GenerateMaintenanceWorkflow signature change; existing behavioral coverage unchanged

Verdict

Check passed. 0% of new tests are implementation tests (threshold: 30%). No coding-guideline violations detected.

The new TestGenerateMaintenanceWorkflow_PushTrigger test suite directly exercises the behavioral contract introduced by this PR: the push trigger on the default branch is present in dev mode, absent in release mode, uses a configurable branch name, and does not accidentally activate schedule-only jobs. All five subtests use strings.Contains / strings.NotContains assertions on the generated YAML output — the true observable artifact — rather than mocking internals.

Minor observation (non-blocking): One subtest (dev mode uses custom default branch) calls the internal helper buildMaintenanceWorkflowYAML directly rather than going through GenerateMaintenanceWorkflow. This is an acceptable trade-off to avoid a live FetchDefaultBranch API call in a unit test; the behavioral assertion (branch name appears in output) is still meaningful.

Build tags are correct: //go:build !integration on the unit test file, //go:build integration on the integration test file. No mock libraries used.


📖 Understanding Test Classifications

Design Tests (High Value) verify what the system does:

  • Assert on observable outputs, return values, or state changes
  • Cover error paths and boundary conditions
  • Would catch a behavioral regression if deleted

Implementation Tests (Low Value) verify how the system does it:

  • Assert on internal function calls (mocking internals)
  • Only test the happy path with typical inputs
  • Break during legitimate refactoring even when behavior is correct

References: §24899268915

🧪 Test quality analysis by Test Quality Sentinel · ● 988.1K ·

Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Test Quality Sentinel: 93/100. Test quality is excellent — 0% of new tests are implementation tests (threshold: 30%). The new push-trigger tests are well-structured behavioral contracts covering dev mode, release mode, branch substitution, and per-job push exclusion guards.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants