Uh oh!
There was an error while loading. Please reload this page.
add-wizard: offer schedule frequency selection for scheduled workflows - #19709
Conversation
When adding a scheduled workflow via `gh aw add-wizard`, the wizard now detects the schedule trigger and offers a choice of standard frequencies: hourly, every 3 hours, daily, weekly, or monthly. - The form defaults to the workflow's existing schedule. - Custom schedules (not matching a standard frequency) are shown as a "Custom: <expr> (keep existing)" option which is the default. - If the user selects the same frequency or "Custom", the frontmatter is left unchanged. - For multi-trigger workflows (schedule + other triggers), the selector is skipped to avoid losing other triggers. New files: pkg/cli/add_interactive_schedule.go - detection & selection logic pkg/cli/add_interactive_schedule_test.go - unit tests Changed files: pkg/cli/add_interactive_orchestrator.go - calls selectScheduleFrequency as step 7b in RunAddInteractive Co-authored-by: dsyme <7204669+dsyme@users.noreply.github.com>
…dd-frequency-options-scheduler
…hub.com/github/gh-aw into copilot/add-frequency-options-scheduler
There was a problem hiding this comment.
Pull request overview
Adds a new gh aw add-wizard step to detect scheduled workflows and let users choose a standard schedule frequency (hourly/3-hourly/daily/weekly/monthly) while preparing the PR.
Changes:
- Introduces schedule detection/classification + interactive selection, and applies the selected schedule to in-memory workflow content before PR creation.
- Integrates the new schedule-selection step into the interactive add orchestrator flow.
- Adds unit tests for schedule classification/detection and option-building.
- Updates the
create_pull_requestsafe-output handler (context guarding, run URL construction, footer args, and permission-denied handling).
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 5 comments.
| File | Description |
|---|---|
| pkg/cli/add_interactive_schedule.go | Adds schedule detection/classification, builds select options, and attempts to rewrite frontmatter based on user choice. |
| pkg/cli/add_interactive_schedule_test.go | Adds unit tests for schedule frequency classification, schedule detection, and option ordering. |
| pkg/cli/add_interactive_orchestrator.go | Inserts the schedule-frequency selection step into the wizard flow. |
| actions/setup/js/create_pull_request.cjs | Adjusts PR creation handler behavior around context usage, footer generation, run URL construction, and permission-denied flow. |
Comments suppressed due to low confidence (1)
actions/setup/js/create_pull_request.cjs:727
- The same manual
runUrlconstruction is duplicated in the git-push failure fallback path. Consider factoring this back to the sharedbuildWorkflowRunUrlhelper (and/or a local function) to avoid divergence and to ensure the URL always targets the workflow-run repo even whenrepoPartsis a different target repo.
const runId = context.runId;
const githubServer = process.env.GITHUB_SERVER_URL || "https://github.com";
const runUrl = context.payload.repository ? `${context.payload.repository.html_url}/actions/runs/${runId}` : `${githubServer}/${repoParts.owner}/${repoParts.repo}/actions/runs/${runId}`;
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…hub.com/github/gh-aw into copilot/add-frequency-options-scheduler
Uh oh!
There was an error while loading. Please reload this page.
gh aw add-wizardhad no way to change the schedule of a workflow being added — users got whatever frequency was baked into the upstream workflow.Changes
Schedule detection (
add_interactive_schedule.go)detectWorkflowScheduleInfo— extracts the raw schedule expression from frontmatter, handling both simple string form (on: daily) and map form (on: {schedule: [{cron: ...}], workflow_dispatch: null}). Skips multi-trigger workflows (e.g.on: schedule + push) to avoid clobbering unrelated triggers.classifyScheduleFrequency— maps any schedule expression tohourly | 3-hourly | daily | weekly | monthly | custom, covering friendly strings (daily,every 3h), FUZZY placeholders (FUZZY:DAILY * * *), and standard cron patterns.buildScheduleOptions— constructs the orderedhuhselect list; the current frequency is placed first and marked(current). Custom/unrecognised schedules get aCustom: <expr> (keep existing)option as the default.selectScheduleFrequency— wizard step: presents the form, and on a changed selection rewriteswf.Content/wf.SourceInfo.Contentin memory before the PR is created. No-op when user picks the same frequency or "Custom".Wizard integration (
add_interactive_orchestrator.go)selectScheduleFrequency()as step 7b inRunAddInteractive, after file enumeration and before the confirmation prompt.Frequency → expression mapping
on:every 1hevery 3hdailyweekly0 0 1 * *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/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 --local 64/pkg/tool/linux_amd64/vet git rev-�� --show-toplevel QX/ympLdpf_SIHeLx8ALucz/ItF6Ey0Q-tests /usr/bin/git te '**/*.cjs' '*git .cfg x_amd64/link git(http block)https://api.github.com/repos/actions/ai-inference/git/ref/tags/v1/usr/bin/gh gh api /repos/actions/ai-inference/git/ref/tags/v1 --jq .object.sha --get l /usr/bin/git ../pkg/workflow/git(http block)https://api.github.com/repos/actions/checkout/git/ref/tags/v3/usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v3 --jq .object.sha -unreachable=false /tmp/go-build1158601089/b264/vet.cfg /opt/hostedtoolcache/uv/0.10.8/x86_64/bash(http block)https://api.github.com/repos/actions/checkout/git/ref/tags/v5/usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v5 --jq .object.sha --verify main 64/pkg/tool/linux_amd64/vet(http block)/usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v5 --jq .object.sha --show-toplevel x_amd64/vet /usr/bin/git(http block)/usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v5 --jq .object.sha --show-toplevel 64/pkg/tool/linux_amd64/vet /usr/bin/git tants.go tants_test.go 64/pkg/tool/linu--show-toplevel git rev-�� --show-toplevel 64/pkg/tool/linux_amd64/compile /usr/bin/git g_.a 8601089/b251/vetrev-parse .cfg git(http block)https://api.github.com/repos/actions/checkout/git/ref/tags/v6/usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v6 --jq .object.sha XFJrOcRib(http block)/usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v6 --jq .object.sha tags/v5(http block)/usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v6 --jq .object.sha --show-toplevel 64/pkg/tool/linux_amd64/vet /usr/bin/git HEAD .cfg 64/pkg/tool/linu--show-toplevel git rev-�� --show-toplevel 64/pkg/tool/linu--json /usr/bin/git git status --porgit(http block)https://api.github.com/repos/actions/download-artifact/git/ref/tags/v8/usr/bin/gh gh api /repos/actions/download-artifact/git/ref/tags/v8 --jq .object.sha se 8601089/b010/vet.cfg ache/go/1.25.0/x64/pkg/tool/linux_amd64/vet(http block)/usr/bin/gh gh api /repos/actions/download-artifact/git/ref/tags/v8 --jq .object.sha se 8601089/b234/vet.cfg ache/go/1.25.0/x64/pkg/tool/linux_amd64/vet(http block)/usr/bin/gh gh api /repos/actions/download-artifact/git/ref/tags/v8 --jq .object.sha t0 m0s 8601089/b292/vet.cfg assifyScheduleFrgit(http block)https://api.github.com/repos/actions/github-script/git/ref/tags/v8/usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v8 --jq .object.sha(http block)/usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v8 --jq .object.sha -c=4 -nolocalimports -importcfg /tmp/go-build3677500810/b385/importcfg -embedcfg /tmp/go-build3677500810/b385/embedcfg -pack(http block)/usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v8 --jq .object.sha on' --ignore-path ../../../.pret.prettierignore(http block)https://api.github.com/repos/actions/setup-go/git/ref/tags/v4/usr/bin/gh gh api /repos/actions/setup-go/git/ref/tags/v4 --jq .object.sha /tmp/gh-aw-test-runs/20260305-095513-12636/test-3102792710/.github/workflows config /usr/bin/git remote.origin.urgit(http block)https://api.github.com/repos/actions/setup-node/git/ref/tags/v4/usr/bin/gh gh api /repos/actions/setup-node/git/ref/tags/v4 --jq .object.sha --show-toplevel(http block)https://api.github.com/repos/actions/upload-artifact/git/ref/tags/v4/usr/bin/gh gh api /repos/actions/upload-artifact/git/ref/tags/v4 --jq .object.sha 7500810/b386/_pkg_.a .cfg 7500810/b386=> -p bracelet/x/exp/grev-parse -lang=go1.17 /opt/hostedtoolcache/go/1.25.0/x64/pkg/tool/linux_amd64/vet -ato�� tructions-test-2759340695/.github/workflows -buildtags /opt/hostedtoolcache/go/1.25.0/x64/pkg/tool/linux_amd64/vet -errorsas -ifaceassert -nilfunc 7500810/b386/importcfg(http block)https://api.github.com/repos/actions/upload-artifact/git/ref/tags/v7/usr/bin/gh gh api /repos/actions/upload-artifact/git/ref/tags/v7 --jq .object.sha te '../../../**/*.json' '!../../../pkg/workflow/-errorsas(http block)/usr/bin/gh gh api /repos/actions/upload-artifact/git/ref/tags/v7 --jq .object.sha te '../../../**/*.json' '!../../../pkg/workflow/js/**/*.json' ---p --noheadings .cfg(http block)/usr/bin/gh gh api /repos/actions/upload-artifact/git/ref/tags/v7 --jq .object.sha on rkflow/js/**/*.json x_amd64/compile erignore(http block)https://api.github.com/repos/github/gh-aw/actions/runs/1/artifacts/usr/bin/gh gh run download 1 --dir test-logs/run-1 --local 64/pkg/tool/linux_amd64/vet nore(http block)https://api.github.com/repos/github/gh-aw/actions/runs/12345/artifacts/usr/bin/gh gh run download 12345 --dir test-logs/run-12345 --local 64/pkg/tool/linux_amd64/vet nore(http block)https://api.github.com/repos/github/gh-aw/actions/runs/12346/artifacts/usr/bin/gh gh run download 12346 --dir test-logs/run-12346 --local 64/pkg/tool/linux_amd64/vet nore(http block)https://api.github.com/repos/github/gh-aw/actions/runs/2/artifacts/usr/bin/gh gh run download 2 --dir test-logs/run-2 --local x_amd64/link nore(http block)https://api.github.com/repos/github/gh-aw/actions/runs/3/artifacts/usr/bin/gh gh run download 3 --dir test-logs/run-3 les 64/pkg/tool/linux_amd64/vet nore(http block)https://api.github.com/repos/github/gh-aw/actions/runs/4/artifacts/usr/bin/gh gh run download 4 --dir test-logs/run-4 --local 64/pkg/tool/linux_amd64/vet nore(http block)https://api.github.com/repos/github/gh-aw/actions/runs/5/artifacts/usr/bin/gh gh run download 5 --dir test-logs/run-5 --local 64/pkg/tool/linu-nolocalimports nore(http block)https://api.github.com/repos/github/gh-aw/actions/workflows/usr/bin/gh gh workflow list --json name,state,path(http block)/usr/bin/gh gh run list --json databaseId,number,url,status,conclusion,workflowName,createdAt,startedAt,updatedAt,event,headBranch,headSha,displayTitle --workflow nonexistent-workflow-12345 --limit 100(http block)/usr/bin/gh gh run list --json databaseId,number,url,status,conclusion,workflowName,createdAt,startedAt,updatedAt,event,headBranch,headSha,displayTitle --workflow nonexistent-workflow-12345 --limit 6(http block)https://api.github.com/repos/github/gh-aw/git/ref/tags/v1.0.0/usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v1.0.0 --jq .object.sha --local .cfg 64/pkg/tool/linux_amd64/vet(http block)https://api.github.com/repos/github/gh-aw/git/ref/tags/v1.2.3/usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v1.2.3 --jq .object.sha(http block)https://api.github.com/repos/github/gh-aw/git/ref/tags/v2.0.0/usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v2.0.0 --jq .object.sha(http block)/usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v2.0.0 --jq .object.sha ./../pkg/workflo-errorsas(http block)https://api.github.com/repos/github/gh-aw/git/ref/tags/v3.0.0/usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v3.0.0 --jq .object.sha(http block)https://api.github.com/repos/nonexistent/action/git/ref/tags/v999.999.999/usr/bin/gh gh api /repos/nonexistent/action/git/ref/tags/v999.999.999 --jq .object.sha --local .cfg 64/pkg/tool/linux_amd64/vet(http block)https://api.github.com/repos/nonexistent/repo/actions/runs/12345/usr/bin/gh gh run view 12345 --repo nonexistent/repo --json status,conclusion nore(http block)https://api.github.com/repos/owner/repo/actions/workflows/usr/bin/gh gh workflow list --json name,state,path --repo owner/repo 0/x64/bin/git(http block)/usr/bin/gh gh workflow list --json name,state,path --repo owner/repo -importcfg /tmp/go-build103549757/b123/importcfg -pack /home/REDACTED/work/gh-aw/gh-aw/pkg/cli/access_log.go /home/REDACTED/work/gh-aw/gh-aw/pkg/cli/actionlint.go(http block)https://api.github.com/repos/owner/repo/contents/file.md/tmp/go-build3677500810/b383/cli.test /tmp/go-build3677500810/b383/cli.test -test.testlogfile=/tmp/go-build3677500810/b383/testlog.txt -test.paniconexit0 -test.v=true -test.parallel=4 -test.timeout=10m0s -test.run=^Test -test.short=true(http block)https://api.github.com/repos/test-owner/test-repo/actions/secrets/usr/bin/gh gh api /repos/test-owner/test-repo/actions/secrets --jq .secrets[].name(http block)/usr/bin/gh gh api /repos/test-owner/test-repo/actions/secrets --jq .secrets[].name --show-toplevel eutil.test /usr/bin/git se 8601089/b097/vetrev-parse ache/go/1.25.0/x--show-toplevel git rev-�� --show-toplevel ache/go/1.25.0/x64/pkg/tool/linux_amd64/vet /usr/bin/git se 8601089/b270/vetrev-parse ache/go/1.25.0/x--show-toplevel git(http block)If you need me to access, download, or install something from one of these locations, you can either:
Original prompt
💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.
✨ PR Review Safe Output Test - Run 22718413768