add-wizard: offer schedule frequency selection for scheduled workflows#19709
Merged
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>
Copilot
AI
changed the title
[WIP] Add frequency options for scheduled workflow wizard
add-wizard: offer schedule frequency selection for scheduled workflows
Mar 5, 2026
This was referenced Mar 5, 2026
…dd-frequency-options-scheduler
…hub.com/github/gh-aw into copilot/add-frequency-options-scheduler
Contributor
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.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…hub.com/github/gh-aw into copilot/add-frequency-options-scheduler
dsyme
approved these changes
Mar 7, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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