Skip to content

Refactor token env lookup and schedule helpers to remove semantic drift#45298

Merged
pelikhan merged 3 commits into
mainfrom
copilot/refactor-semantic-function-clustering-again
Jul 14, 2026
Merged

Refactor token env lookup and schedule helpers to remove semantic drift#45298
pelikhan merged 3 commits into
mainfrom
copilot/refactor-semantic-function-clustering-again

Conversation

Copilot AI commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

This addresses semantic clustering drift in three hotspots: duplicated GitHub token env lookup across build variants, repeated numeric cron-field parsing, and repeated schedule warning emission boilerplate. The refactor centralizes these behaviors without changing user-facing semantics.

  • Token lookup precedence unified across wasm/non-wasm

    • Added githubTokenFromEnv(log *logger.Logger) string in pkg/parser/github_token_env.go.
    • Updated both GetGitHubToken variants to use the same GITHUB_TOKENGH_TOKEN lookup path.
    • Kept non-wasm gh auth token fallback behavior unchanged.
  • Cron numeric-field logic consolidated

    • Added isNumericCronField(string) bool and shared cronFields(...)([]string, bool) in pkg/parser/schedule_cron_detection.go.
    • Rewired IsDailyCron, IsHourlyCron, and IsWeeklyCron to use shared helpers instead of inline repeated scans.
  • Schedule warning bookkeeping centralized

    • Added emitScheduleWarning(warning string) in pkg/workflow/schedule_preprocessing.go.
    • Reused it in daily/hourly/weekly warning constructors so warning count + storage behavior is defined in one place.
  • Focused regression coverage for extracted helpers

    • Added pkg/parser/github_token_env_test.go (env precedence/fallback cases).
    • Extended pkg/parser/schedule_cron_detection_test.go with TestIsNumericCronField.
func githubTokenFromEnv(log *logger.Logger) string {
	if token := envutil.GetStringFromEnv("GITHUB_TOKEN", "", log); token != "" {
		return token
	}
	return envutil.GetStringFromEnv("GH_TOKEN", "", log)
}

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
@github-actions

Copy link
Copy Markdown
Contributor

Hey @app/copilot-swe-agent 👋 — nice work on the semantic function clustering refactor!

This PR is in early WIP stages with no diff yet. Once the implementation lands, here are a few things to verify:

  • Run existing tests — the issue specifically calls out running schedule/cron and parser tests to confirm no behavior change. Make sure make test passes after all three refactors.
  • No behavior change — the githubTokenFromEnv extraction is the highest-risk item (Priority 2); double-check token precedence (GITHUB_TOKEN before GH_TOKEN) is preserved in both wasm and non-wasm builds.

If you would like a hand, you can assign this prompt to your coding agent:

Refactor pkg/ as described in github/gh-aw#45143:
1. Extract a build-tag-agnostic `githubTokenFromEnv(log *logger.Logger) string` helper; wire both GetGitHubToken variants to call it.
2. Extract `isNumericCronField(s string) bool` helper in pkg/parser/schedule_cron_detection.go, replacing the 4 open-coded digit scans.
3. Extract `emitScheduleWarning` boilerplate helper in pkg/workflow/schedule_preprocessing.go.
4. Run: make test — confirm all schedule/cron and parser tests pass.
5. Confirm GITHUB_TOKEN → GH_TOKEN precedence is unchanged in both build-tag variants.

Generated by ✅ Contribution Check · 93.5 AIC · ⌖ 10.7 AIC · ⊞ 6.2K ·

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copilot AI changed the title [WIP] Refactor semantic function clustering for organization drift Refactor token env lookup and schedule helpers to remove semantic drift Jul 13, 2026
Copilot AI requested a review from pelikhan July 13, 2026 17:51
@github-actions

Copy link
Copy Markdown
Contributor

PR Triage (run 29275650494)\n\nCategory: refactor | Risk: medium | Score: 55/100 | Action: batch_review | Batch: draft-quality\n\nScore: Impact 25/50 + Urgency 15/30 + Quality 15/20\n\nCentralizes token env lookup and schedule helpers. 8 files, +129/-62. DRAFT. Similar in nature to #45280 and #45282 - good candidate for batch review.

Generated by 🔧 PR Triage Agent · 181.5 AIC · ⌖ 7.71 AIC · ⊞ 5.6K ·

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Centralizes token lookup, cron parsing, and schedule-warning bookkeeping to reduce duplicated logic.

Changes:

  • Shares GitHub token environment precedence across build targets.
  • Extracts common cron and warning helpers with regression tests.
  • Refreshes the smoke workflow lockfile.
Show a summary per file
File Description
pkg/workflow/schedule_preprocessing.go Centralizes warning emission.
pkg/parser/schedule_cron_detection.go Adds shared cron helpers.
pkg/parser/schedule_cron_detection_test.go Tests numeric-field detection.
pkg/parser/github.go Uses shared token lookup.
pkg/parser/github_wasm.go Uses shared token lookup for Wasm.
pkg/parser/github_token_env.go Implements token precedence helper.
pkg/parser/github_token_env_test.go Tests token precedence and fallback.
.github/workflows/smoke-call-workflow.lock.yml Refreshes generated inputs, permissions, and secrets.

Review details

Tip

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

  • Files reviewed: 8/8 changed files
  • Comments generated: 1
  • Review effort level: Medium

Comment on lines +1112 to +1115
actions: read
contents: read
pull-requests: read
issues: write
pull-requests: write

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I re-ran the branch validations (make fmt, make lint, make test-unit, make test, make recompile, make agent-report-progress).

I also re-tested a direct lockfile revert for this file; it still fails check-workflow-drift because the current workflow source recompiles to this lockfile shape. So I did not push a revert that would leave the repo in a drifted state.

@gh-aw-bot

Copy link
Copy Markdown
Collaborator

pr-sous-chef
@copilot please run the pr-finisher skill, address any remaining review feedback, and rerun checks once the branch is up to date.

Run: https://github.com/github/gh-aw/actions/runs/29286484887

Generated by 👨‍🍳 PR Sous Chef · 9.66 AIC · ⌖ 6.15 AIC · ⊞ 5.1K ·
Comment /souschef to run again

Copilot AI commented Jul 13, 2026

Copy link
Copy Markdown
Contributor Author

pr-sous-chef
@copilot please run the pr-finisher skill, address any remaining review feedback, and rerun checks once the branch is up to date.
...

Completed a PR-finisher pass on #45298.

  • Reviewed remaining in-scope feedback: the only open thread is the lockfile expansion note on .github/workflows/smoke-call-workflow.lock.yml.
  • I tested a revert, but it puts lockfiles out of sync with workflow sources and fails make agent-report-progress (check-workflow-drift), so I did not push that change.
  • Re-ran local checks on current HEAD: make fmt, make lint, make test-unit, make test, make recompile, and make agent-report-progress all pass.

No new commit was made in this pass. CI on this head still requires a human re-trigger if a fresh run is needed.

Copilot AI requested a review from gh-aw-bot July 13, 2026 21:55
@gh-aw-bot

Copy link
Copy Markdown
Collaborator

pr-sous-chef
@copilot please run the pr-finisher skill, address this remaining unresolved review comment, and rerun checks once the branch is up to date:

Run: https://github.com/github/gh-aw/actions/runs/29289965782

Generated by 👨‍🍳 PR Sous Chef · 10.9 AIC · ⌖ 3.94 AIC · ⊞ 7.5K ·
Comment /souschef to run again

Copilot AI commented Jul 13, 2026

Copy link
Copy Markdown
Contributor Author

pr-sous-chef
@copilot please run the pr-finisher skill, address this remaining unresolved review comment, and rerun checks once the branch is up to date:

  • copilot-pull-request-reviewer: https://g...

Done. I ran pr-finisher, addressed the remaining Copilot review comment directly on thread discussion_r3574252917, and reran checks on current HEAD:

  • make fmt
  • make lint
  • make test-unit
  • make test
  • make recompile
  • make agent-report-progress

All passed. No new commit was made in this pass.

@github-actions

github-actions Bot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

🧠 Matt Pocock Skills Reviewer has completed the skills-based review. ✅

@github-actions

github-actions Bot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Test Quality Sentinel completed test quality analysis.

@github-actions

github-actions Bot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Design Decision Gate 🏗️ completed the design decision gate check.

@github-actions

github-actions Bot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

PR Code Quality Reviewer completed the code quality review.

@pelikhan pelikhan merged commit b27408f into main Jul 14, 2026
91 checks passed
@pelikhan pelikhan deleted the copilot/refactor-semantic-function-clustering-again branch July 14, 2026 02:36

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Clean, focused refactoring with no blocking issues.\n\n- Token env lookup correctly preserves GITHUB_TOKENGH_TOKEN precedence across both wasm and non-wasm paths.\n- isNumericCronField and cronFields helpers are correct and well-tested.\n- emitScheduleWarning correctly atomizes the increment+store pairing.\n- Lock file change (replacing secrets: inherit with explicit list) is a security improvement.

🧵 Reviewed using Impeccable skills by Impeccable Skills Reviewer · 12.4 AIC · ⌖ 6.7 AIC · ⊞ 4.8K

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Skills-Based Review 🧠

Applied /tdd and /codebase-design — two minor observations, no blocking issues.

📋 Key Themes & Highlights

Key Themes

  • cronFields lacks a direct unit test — only covered indirectly; a dedicated test would lock in its contract.
  • Inconsistent logger usage in github_token_env_test.gonil vs logger.New(...) across subtests without explanation.

Positive Highlights

  • ✅ Clean, minimal helpers with well-scoped responsibilities (githubTokenFromEnv, isNumericCronField, emitScheduleWarning).
  • ✅ Wasm and non-wasm paths now share a single precedence rule — drift eliminated.
  • TestIsNumericCronField table covers the important edge cases (wildcards, intervals, ranges).
  • emitScheduleWarning removes the boilerplate comments that were being copied three times — good signal cleanup.

🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer · 31 AIC · ⌖ 4.54 AIC · ⊞ 6.6K
Comment /matt to run again


func TestIsDailyCron(t *testing.T) {
tests := []struct {
name string

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

[/tdd] cronFields is extracted as a standalone helper but has no direct test — it is only exercised indirectly through IsDailyCron/IsHourlyCron/IsWeeklyCron. A direct test would lock in its contract (5-field split, short-circuit on wrong field count) and prevent silent regressions if the helper is later reused.

💡 Suggested test skeleton
func TestCronFields(t *testing.T) {
    fields, ok := cronFields("0 0 * * *")
    assert.True(t, ok)
    assert.Equal(t, []string{"0", "0", "*", "*", "*"}, fields)

    _, ok = cronFields("0 0 * *") // only 4 fields
    assert.False(t, ok)

    _, ok = cronFields("") // empty string
    assert.False(t, ok)
}

@copilot please address this.


t.Run("falls back to GH_TOKEN when GITHUB_TOKEN is empty", func(t *testing.T) {
t.Setenv("GITHUB_TOKEN", "")
t.Setenv("GH_TOKEN", "gh-token")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

[/tdd] The second and third test cases pass nil as the logger while the first passes logger.New("parser:test"). There is no documented reason for the inconsistency — if nil is intentionally valid (i.e. the helper is safe to call without a logger), make that explicit with a comment or a dedicated TestGithubTokenFromEnvNilLogger case; otherwise use logger.New(...) consistently to avoid masking nil-pointer panics during future edits.

@copilot please address this.

@github-actions

Copy link
Copy Markdown
Contributor

🧪 Test Quality Sentinel Report

Test Quality Score: 90/100 — Excellent

Analyzed 7 test(s): 7 design, 0 implementation, 0 violation(s).

📊 Metrics (7 tests)
Metric Value
Analyzed 7 (Go: 7, JS: 0)
✅ Design 7 (100%)
⚠️ Implementation 0 (0%)
Edge/error coverage 7 (100%)
Duplicate clusters 0
Inflation Yes — github_token_env_test.go ~2.5:1 (acceptable; prod file is intentionally thin)
🚨 Violations 0
Test File Classification Issues
TestGithubTokenFromEnv github_token_env_test.go design_test None
TestIsCronExpression schedule_cron_detection_test.go design_test None
TestIsNumericCronField schedule_cron_detection_test.go design_test None
TestIsDailyCron schedule_cron_detection_test.go design_test None
TestIsHourlyCron schedule_cron_detection_test.go design_test None
TestIsWeeklyCron schedule_cron_detection_test.go design_test None
TestIsFuzzyCron schedule_cron_detection_test.go design_test None

Verdict

Passed. 0% implementation tests (threshold: 30%). All 7 tests verify behavioral contracts with comprehensive edge-case and negative-case coverage. //go:build tags present on both files; no mock library usage.

Warning

Firewall blocked 1 domain

The following domain was blocked by the firewall during workflow execution:

  • awmgmcpg

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "awmgmcpg"

See Network Configuration for more information.

🧪 Test quality analysis by Test Quality Sentinel · 39 AIC · ⌖ 10.8 AIC · ⊞ 6.8K ·
Comment /review to run again

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

✅ Test Quality Sentinel: 90/100. 0% implementation tests (threshold: 30%). All 7 tests are design tests with behavioral contracts and edge-case coverage. No violations.

@github-actions

Copy link
Copy Markdown
Contributor

🏗️ Design Decision Gate — ADR Required

This PR makes significant changes to core business logic (111 new lines across pkg/parser and pkg/workflow) but does not have a linked Architecture Decision Record (ADR).

📄 Draft ADR committed: docs/adr/45298-centralize-repeated-logic-with-helper-functions.md — review and complete it before merging.

🔒 This PR cannot merge until an ADR is linked in the PR body.

📋 What to do next
  1. Review the draft ADR committed to your branch — it was generated from the PR diff
  2. Complete the missing sections — add context the AI could not infer, refine the decision rationale, and list real alternatives you considered
  3. Commit the finalized ADR to docs/adr/ on your branch
  4. Reference the ADR in this PR body by adding a line such as:

    ADR: ADR-45298: Centralize Repeated Logic with Package-Private Helper Functions

Once an ADR is linked in the PR body, this gate will re-run and verify the implementation matches the decision.

Why ADRs Matter

ADRs create a searchable, permanent record of why the codebase looks the way it does. Future contributors (and your future self) will thank you.

📋 Michael Nygard ADR Format Reference

An ADR must contain these four sections to be considered complete:

  • Context — What is the problem? What forces are at play?
  • Decision — What did you decide? Why?
  • Alternatives Considered — What else could have been done?
  • Consequences — What are the trade-offs (positive and negative)?

All ADRs are stored in docs/adr/ as Markdown files numbered by PR number (e.g., 0042-use-postgresql.md for PR #42).

🏗️ ADR gate enforced by Design Decision Gate 🏗️ · 66 AIC · ⌖ 10.8 AIC · ⊞ 8.5K ·
Comment /review to run again

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Review: medium-risk maintenance issues only

The Go refactors (token env helper, cron field helpers, emitScheduleWarning) are mechanically correct and have adequate test coverage. Two medium-risk issues flagged above.

Findings summary

Medium — emitScheduleWarning / addScheduleWarning split (schedule_preprocessing.go:349): The lower-level addScheduleWarning method (which skips the counter) remains package-accessible. A future caller adding a new warning type via that method directly will silently miscount warnings. Rename it to make the bypass-unsafe path obvious.

Medium — secrets: inherit → explicit list in lock file (smoke-call-workflow.lock.yml:37): Static list is a maintenance snapshot; future secret additions will silently not be forwarded. If this is intentional (scope-limiting), document it clearly.

The permission escalation (pull-requests: write, issues: write) was already flagged in a prior review and is outside this pass's scope.

🔎 Code quality review by PR Code Quality Reviewer · 40.7 AIC · ⌖ 4.57 AIC · ⊞ 5.4K
Comment /review to run again

Comments that could not be inline-anchored

pkg/workflow/schedule_preprocessing.go:349

Silent warning-count miss if addScheduleWarning is called directly: emitScheduleWarning is the correct entry point, but addScheduleWarning (which skips IncrementWarningCount) remains callable from within the same package.

<details>
<summary>💡 Suggested fix</summary>

Rename addScheduleWarning to storeScheduleWarning (or similar) and update emitScheduleWarning to call the renamed method. Keeping the raw storage method named addScheduleWarning invites future callers to accid…

.github/workflows/smoke-call-workflow.lock.yml:37

Switching from secrets: inherit to an explicit list silently drops any future secrets: if the called workflow is updated to require new secrets, callers receive empty values with no error — only silent downstream auth failures.

<details>
<summary>💡 Details</summary>

secrets: inherit forwards all repository secrets automatically. The explicit list here is a static snapshot. As the called workflow evolves, each new secret must also be manually added to this caller — and since this is a…

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[refactor] Semantic function clustering: GetGitHubToken env-lookup drift + scattered cron helpers

4 participants