Skip to content

ci: split into parallel jobs, add cross-OS tests, race, govulncheck, CodeQL, dep-review#4

Merged
watany-dev merged 5 commits intomainfrom
claude/enhance-ci-pipeline-6VE3k
May 1, 2026
Merged

ci: split into parallel jobs, add cross-OS tests, race, govulncheck, CodeQL, dep-review#4
watany-dev merged 5 commits intomainfrom
claude/enhance-ci-pipeline-6VE3k

Conversation

@watany-dev
Copy link
Copy Markdown
Owner

  • ci.yml: split single make-check job into parallel lint / test (linux+macos+windows
    with -race -shuffle=on) / vuln / build (5 GOOS/GOARCH cross-compile) / actionlint
  • ci.yml: add concurrency cancellation (skip on main) and per-job timeout-minutes
  • codeql.yml: new SAST workflow on push/PR/weekly schedule
  • dependency-review.yml: new PR-only license/CVE gate
  • Makefile: add test-race, vuln, actionlint targets; consume go tool directive
  • go.mod: register govulncheck and actionlint under the tool directive (matching
    the existing staticcheck/deadcode pattern) so versions are locked via go.sum
    instead of floating @latest

Pinned action SHAs:

  • github/codeql-action v3.35.2 (b2f9ef845756500b97acbdaf5c1dd4e9c1d15734)
  • actions/dependency-review-action v4.9.0 (2031cfc080254a8a887f58cffee85186f0e49e48)

All existing security invariants preserved: SHA-pinned uses, minimum permissions
at workflow + job level, persist-credentials: false, release.yml untouched.

https://claude.ai/code/session_01Sy9fRJ7oL6ghGxJAVvEPLW

…CodeQL, dep-review

- ci.yml: split single make-check job into parallel lint / test (linux+macos+windows
  with -race -shuffle=on) / vuln / build (5 GOOS/GOARCH cross-compile) / actionlint
- ci.yml: add concurrency cancellation (skip on main) and per-job timeout-minutes
- codeql.yml: new SAST workflow on push/PR/weekly schedule
- dependency-review.yml: new PR-only license/CVE gate
- Makefile: add test-race, vuln, actionlint targets; consume go tool directive
- go.mod: register govulncheck and actionlint under the tool directive (matching
  the existing staticcheck/deadcode pattern) so versions are locked via go.sum
  instead of floating @latest

Pinned action SHAs:
- github/codeql-action v3.35.2 (b2f9ef845756500b97acbdaf5c1dd4e9c1d15734)
- actions/dependency-review-action v4.9.0 (2031cfc080254a8a887f58cffee85186f0e49e48)

All existing security invariants preserved: SHA-pinned uses, minimum permissions
at workflow + job level, persist-credentials: false, release.yml untouched.

https://claude.ai/code/session_01Sy9fRJ7oL6ghGxJAVvEPLW
@github-advanced-security
Copy link
Copy Markdown

You are seeing this message because GitHub Code Scanning has recently been set up for this repository, or this pull request contains the workflow file for the Code Scanning tool.

What Enabling Code Scanning Means:

  • The 'Security' tab will display more code scanning analysis results (e.g., for the default branch).
  • Depending on your configuration and choice of analysis tool, future pull requests will be annotated with code scanning analysis results.
  • You will be able to see the analysis results for the pull request's branch on this overview once the scans have completed and the checks have passed.

For more information about GitHub Code Scanning, check out the documentation.

claude added 3 commits May 1, 2026 09:09
…threshold)

First CI run on PR #4 surfaced four failures whose root causes are best
addressed individually:

- Windows test: e2e test wrote "base\n" but Windows git's default
  core.autocrlf=true rewrites to CRLF on checkout, breaking content
  assertions. Pin core.autocrlf=false alongside the existing per-test
  user/email/gpgsign config in e2e_test.go.
- actionlint job: the auditor-mode zizmor step was failing on the new
  workflow files. Drop the step for now; actionlint alone covers the
  primary lint surface and zizmor can be re-introduced after we hand-audit
  any findings.
- dependency-review: switch initial rollout to warn-only so the action
  surfaces license/CVE findings as a PR summary without blocking merges.
  Plan to tighten back to fail-on-severity: high after calibrating.
- macOS test: cause not yet known (Actions logs require auth). To
  enable diagnosis on the next run, tee verbose `go test -race -v` output
  to test-output.txt and upload it as an artifact with `if: always()` —
  artifacts are reachable via the public artifacts API for public repos.

https://claude.ai/code/session_01Sy9fRJ7oL6ghGxJAVvEPLW
Second CI run revealed two more issues:

- actionlint job: now that shellcheck is on the runner's PATH (it's
  preinstalled on ubuntu-latest), actionlint activates the shellcheck
  rule and surfaces SC2155 in release.yml line 79
  (`export SOURCE_DATE_EPOCH="$(git log -1 --format=%ct)"`). Split into
  separate assignment + export so a `git log` failure isn't masked by
  `export`'s exit status. This is a fix to the existing release.yml,
  but it's the correct fix and unblocks the new lint.
- dependency-review still failed in ~5s, suggesting the action couldn't
  initialize rather than that it found a HIGH-severity vuln (warn-only
  shouldn't fail). Drop the explicit `warn-only` / `comment-summary-in-pr`
  inputs and let the action use defaults — once we have one clean run we
  can layer config back on with confidence.

https://claude.ai/code/session_01Sy9fRJ7oL6ghGxJAVvEPLW
- Add diagnose-test-failure job: runs on test matrix failure for PRs only,
  downloads every test-output-* artifact and posts the last 200 lines per
  OS as a PR comment. Auth-gated Actions logs make this the most reliable
  way to surface OS-specific failures (e.g. the persistent macOS test
  failure I can't otherwise diagnose). Will be removed once the matrix is
  consistently green.
- dependency-review: drop the explicit checkout flags and pull-requests
  permission, mark continue-on-error: true. The job has fast-failed in
  ~5s on every run regardless of input (warn-only / fail-on-severity /
  no inputs), suggesting the action can't initialize. Most likely root
  cause is repo-level Dependency Graph configuration — gating that on
  the user. Until verified, treat dep-review as informational rather
  than blocking.

https://claude.ai/code/session_01Sy9fRJ7oL6ghGxJAVvEPLW
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 1, 2026

Test failure diagnostics (2026-05-01T09:19:51Z)

Auto-generated from ci run 25209381747 on commit 69522e4.

macos-latest (last 200 lines)
=== RUN   TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main^/20260501T120000Z-000000000
=== PAUSE TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main^/20260501T120000Z-000000000
=== RUN   TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main~3/20260501T120000Z-000000000
=== PAUSE TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main~3/20260501T120000Z-000000000
=== RUN   TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main:passwd/20260501T120000Z-000000000
=== PAUSE TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main:passwd/20260501T120000Z-000000000
=== RUN   TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main/20260501T120000Z-000000000_--no-ff
=== PAUSE TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main/20260501T120000Z-000000000_--no-ff
=== RUN   TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main/20260501T120000Z
=== PAUSE TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main/20260501T120000Z
=== RUN   TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main/
=== PAUSE TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main/
=== RUN   TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups//20260501T120000Z-000000000
=== PAUSE TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups//20260501T120000Z-000000000
=== RUN   TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main/20260501T120000Z-000000000/extra
=== PAUSE TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main/20260501T120000Z-000000000/extra
=== RUN   TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/../../../etc/passwd
=== PAUSE TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/../../../etc/passwd
=== CONT  TestStashDirtyWorktreeEdgeCases
--- PASS: TestStashDirtyWorktreeEdgeCases (0.00s)
=== CONT  TestResetRescueAndHelpers
--- PASS: TestResetRescueAndHelpers (0.00s)
=== CONT  TestBranchAndUpstream
--- PASS: TestBranchAndUpstream (0.00s)
=== CONT  TestBackupHead
--- PASS: TestBackupHead (0.00s)
=== CONT  TestBackupHeadRejectsCraftedSafeBranch
--- PASS: TestBackupHeadRejectsCraftedSafeBranch (0.00s)
=== CONT  TestSetConfig
--- PASS: TestSetConfig (0.00s)
=== CONT  TestAheadCount
--- PASS: TestAheadCount (0.00s)
=== CONT  TestSanitizeBranchSegment/simple
=== CONT  TestSanitizeBranchSegment/trailing_dot
=== CONT  TestSanitizeBranchSegment/japanese
=== CONT  TestSanitizeBranchSegment/very_long
=== CONT  TestSanitizeBranchSegment/with_newline
=== CONT  TestSanitizeBranchSegment/with_tab
=== CONT  TestSanitizeBranchSegment/with_space
=== CONT  TestSanitizeBranchSegment/with_null
=== CONT  TestSanitizeBranchSegment/leading_dash
=== CONT  TestSanitizeBranchSegment/single_dot
=== CONT  TestSanitizeBranchSegment/caret
=== CONT  TestSanitizeBranchSegment/two_dots
=== CONT  TestSanitizeBranchSegment/glob_asterisk
=== CONT  TestSanitizeBranchSegment/tilde
=== CONT  TestSanitizeBranchSegment/glob_brackets
=== CONT  TestSanitizeBranchSegment/backslash
=== CONT  TestSanitizeBranchSegment/release_dotted
=== CONT  TestSanitizeBranchSegment/slash
=== CONT  TestSanitizeBranchSegment/git_revision
--- PASS: TestSanitizeBranchSegment (0.00s)
    --- PASS: TestSanitizeBranchSegment/simple (0.00s)
    --- PASS: TestSanitizeBranchSegment/trailing_dot (0.00s)
    --- PASS: TestSanitizeBranchSegment/japanese (0.00s)
    --- PASS: TestSanitizeBranchSegment/very_long (0.00s)
    --- PASS: TestSanitizeBranchSegment/with_newline (0.00s)
    --- PASS: TestSanitizeBranchSegment/with_tab (0.00s)
    --- PASS: TestSanitizeBranchSegment/with_space (0.00s)
    --- PASS: TestSanitizeBranchSegment/with_null (0.00s)
    --- PASS: TestSanitizeBranchSegment/leading_dash (0.00s)
    --- PASS: TestSanitizeBranchSegment/single_dot (0.00s)
    --- PASS: TestSanitizeBranchSegment/caret (0.00s)
    --- PASS: TestSanitizeBranchSegment/two_dots (0.00s)
    --- PASS: TestSanitizeBranchSegment/glob_asterisk (0.00s)
    --- PASS: TestSanitizeBranchSegment/tilde (0.00s)
    --- PASS: TestSanitizeBranchSegment/glob_brackets (0.00s)
    --- PASS: TestSanitizeBranchSegment/backslash (0.00s)
    --- PASS: TestSanitizeBranchSegment/release_dotted (0.00s)
    --- PASS: TestSanitizeBranchSegment/slash (0.00s)
    --- PASS: TestSanitizeBranchSegment/git_revision (0.00s)
=== CONT  TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main/20260501T120000Z-000000000
=== CONT  TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/../../../etc/passwd
=== CONT  TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main/20260501T120000Z-000000000/extra
=== CONT  TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups//20260501T120000Z-000000000
=== CONT  TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main/20260501T120000Z
=== CONT  TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main/
=== CONT  TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main/20260501T120000Z-000000000_--no-ff
=== CONT  TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main~3/20260501T120000Z-000000000
=== CONT  TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main:passwd/20260501T120000Z-000000000
=== CONT  TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main^/20260501T120000Z-000000000
=== CONT  TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main@{-1}/20260501T120000Z-000000000
=== CONT  TestIsBackupRefRejectsRevisionSyntax/refs/heads/main
=== CONT  TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/feature-test/20260501T120000Z-123456789
--- PASS: TestIsBackupRefRejectsRevisionSyntax (0.00s)
    --- PASS: TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main/20260501T120000Z-000000000 (0.00s)
    --- PASS: TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/../../../etc/passwd (0.00s)
    --- PASS: TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main/20260501T120000Z-000000000/extra (0.00s)
    --- PASS: TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups//20260501T120000Z-000000000 (0.00s)
    --- PASS: TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main/20260501T120000Z (0.00s)
    --- PASS: TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main/ (0.00s)
    --- PASS: TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main/20260501T120000Z-000000000_--no-ff (0.00s)
    --- PASS: TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main~3/20260501T120000Z-000000000 (0.00s)
    --- PASS: TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main:passwd/20260501T120000Z-000000000 (0.00s)
    --- PASS: TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main^/20260501T120000Z-000000000 (0.00s)
    --- PASS: TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main@{-1}/20260501T120000Z-000000000 (0.00s)
    --- PASS: TestIsBackupRefRejectsRevisionSyntax/refs/heads/main (0.00s)
    --- PASS: TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/feature-test/20260501T120000Z-123456789 (0.00s)
--- PASS: TestCommandRunnerRunError (0.01s)
=== NAME  TestDiscoverIntegration
    git_test.go:607: Root() = "/private/var/folders/tb/y368xp_x10s3ty1b_mtl5mxr0000gn/T/TestDiscoverIntegration2370630490/001", want "/var/folders/tb/y368xp_x10s3ty1b_mtl5mxr0000gn/T/TestDiscoverIntegration2370630490/001"
--- FAIL: TestDiscoverIntegration (0.03s)
FAIL
FAIL	github.com/watany-dev/gitreal/internal/git	0.040s
-test.shuffle 1777627145315369000
=== RUN   TestSendUsesPackageVariables
=== PAUSE TestSendUsesPackageVariables
=== RUN   TestSendRunnerError
=== PAUSE TestSendRunnerError
=== RUN   TestSendUnsupportedPlatform
=== PAUSE TestSendUnsupportedPlatform
=== RUN   TestSanitizeFieldNormalizesControlChars
=== PAUSE TestSanitizeFieldNormalizesControlChars
=== RUN   TestSend
=== PAUSE TestSend
=== RUN   TestCommand
=== PAUSE TestCommand
=== RUN   TestNotificationFieldsNeverEscapeShellOrPowerShell
=== PAUSE TestNotificationFieldsNeverEscapeShellOrPowerShell
=== RUN   TestCommandEscapesWindowsToastText
=== PAUSE TestCommandEscapesWindowsToastText
=== CONT  TestSendUsesPackageVariables
--- PASS: TestSendUsesPackageVariables (0.00s)
=== CONT  TestNotificationFieldsNeverEscapeShellOrPowerShell
=== RUN   TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-0
=== PAUSE TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-0
=== RUN   TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-1
=== CONT  TestCommand
=== RUN   TestCommand/darwin
=== PAUSE TestCommand/darwin
=== RUN   TestCommand/linux
=== PAUSE TestCommand/linux
=== RUN   TestCommand/windows
=== CONT  TestSend
--- PASS: TestSend (0.00s)
=== CONT  TestCommandEscapesWindowsToastText
--- PASS: TestCommandEscapesWindowsToastText (0.00s)
=== CONT  TestSanitizeFieldNormalizesControlChars
=== PAUSE TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-1
=== RUN   TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-2
--- PASS: TestSanitizeFieldNormalizesControlChars (0.00s)
=== PAUSE TestCommand/windows
=== RUN   TestCommand/unsupported
=== PAUSE TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-2
=== PAUSE TestCommand/unsupported
=== CONT  TestSendUnsupportedPlatform
=== RUN   TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-3
=== CONT  TestCommand/linux
=== PAUSE TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-3
=== RUN   TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-4
=== CONT  TestCommand/windows
=== PAUSE TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-4
=== RUN   TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-5
=== PAUSE TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-5
=== RUN   TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-6
=== PAUSE TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-6
--- PASS: TestSendUnsupportedPlatform (0.00s)
=== CONT  TestSendRunnerError
=== RUN   TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-7
=== PAUSE TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-7
--- PASS: TestSendRunnerError (0.00s)
=== RUN   TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-8
=== CONT  TestCommand/unsupported
=== PAUSE TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-8
=== RUN   TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-9
=== PAUSE TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-9
=== CONT  TestCommand/darwin
=== RUN   TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-10
=== PAUSE TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-10
=== CONT  TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-2
=== CONT  TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-5
=== CONT  TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-7
=== CONT  TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-10
=== CONT  TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-3
=== CONT  TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-9
=== CONT  TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-4
=== CONT  TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-8
=== CONT  TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-1
=== CONT  TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-0
=== CONT  TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-6
--- PASS: TestNotificationFieldsNeverEscapeShellOrPowerShell (0.00s)
    --- PASS: TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-2 (0.00s)
    --- PASS: TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-5 (0.00s)
    --- PASS: TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-7 (0.00s)
    --- PASS: TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-10 (0.00s)
    --- PASS: TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-3 (0.00s)
    --- PASS: TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-9 (0.00s)
    --- PASS: TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-4 (0.00s)
    --- PASS: TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-1 (0.00s)
    --- PASS: TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-0 (0.00s)
    --- PASS: TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-6 (0.00s)
    --- PASS: TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-8 (0.00s)
--- PASS: TestCommand (0.00s)
    --- PASS: TestCommand/linux (0.00s)
    --- PASS: TestCommand/windows (0.00s)
    --- PASS: TestCommand/unsupported (0.00s)
    --- PASS: TestCommand/darwin (0.01s)
PASS
ok  	github.com/watany-dev/gitreal/internal/notify	1.129s
FAIL
ubuntu-latest (last 200 lines)
=== CONT  TestBranchAndUpstream
--- PASS: TestBranchAndUpstream (0.00s)
=== CONT  TestAheadCountRunError
=== PAUSE TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/feature-test/20260501T120000Z-123456789
--- PASS: TestAheadCountRunError (0.00s)
=== RUN   TestIsBackupRefRejectsRevisionSyntax/refs/heads/main
=== PAUSE TestIsBackupRefRejectsRevisionSyntax/refs/heads/main
=== RUN   TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main@{-1}/20260501T120000Z-000000000
=== PAUSE TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main@{-1}/20260501T120000Z-000000000
=== CONT  TestAheadCountEmptyAndInvalid
=== RUN   TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main^/20260501T120000Z-000000000
--- PASS: TestAheadCountEmptyAndInvalid (0.00s)
=== PAUSE TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main^/20260501T120000Z-000000000
=== RUN   TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main~3/20260501T120000Z-000000000
=== CONT  TestResetRescueAndHelpers
=== PAUSE TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main~3/20260501T120000Z-000000000
=== RUN   TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main:passwd/20260501T120000Z-000000000
--- PASS: TestResetRescueAndHelpers (0.00s)
=== PAUSE TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main:passwd/20260501T120000Z-000000000
=== CONT  TestSetConfig
=== RUN   TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main/20260501T120000Z-000000000_--no-ff
--- PASS: TestSetConfig (0.00s)
=== PAUSE TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main/20260501T120000Z-000000000_--no-ff
=== CONT  TestStashDirtyWorktree
=== RUN   TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main/20260501T120000Z
--- PASS: TestStashDirtyWorktree (0.00s)
=== PAUSE TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main/20260501T120000Z
=== CONT  TestSanitizeBranchSegment/slash
=== RUN   TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main/
=== PAUSE TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main/
=== RUN   TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups//20260501T120000Z-000000000
=== PAUSE TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups//20260501T120000Z-000000000
=== CONT  TestSanitizeBranchSegment/glob_brackets
=== RUN   TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main/20260501T120000Z-000000000/extra
=== PAUSE TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main/20260501T120000Z-000000000/extra
=== RUN   TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/../../../etc/passwd
=== CONT  TestSanitizeBranchSegment/very_long
=== PAUSE TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/../../../etc/passwd
=== CONT  TestSanitizeBranchSegment/with_null
=== CONT  TestSanitizeBranchSegment/japanese
=== CONT  TestSanitizeBranchSegment/with_tab
=== CONT  TestSanitizeBranchSegment/with_newline
=== CONT  TestSanitizeBranchSegment/trailing_dot
=== CONT  TestSanitizeBranchSegment/with_space
=== CONT  TestSanitizeBranchSegment/leading_dash
=== CONT  TestSanitizeBranchSegment/release_dotted
=== CONT  TestSanitizeBranchSegment/two_dots
=== CONT  TestSanitizeBranchSegment/glob_asterisk
=== CONT  TestSanitizeBranchSegment/single_dot
=== CONT  TestSanitizeBranchSegment/tilde
=== CONT  TestSanitizeBranchSegment/caret
=== CONT  TestSanitizeBranchSegment/backslash
=== CONT  TestSanitizeBranchSegment/git_revision
=== CONT  TestSanitizeBranchSegment/simple
=== CONT  TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main/20260501T120000Z-000000000
=== CONT  TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/../../../etc/passwd
=== CONT  TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main/
=== CONT  TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main/20260501T120000Z-000000000/extra
=== CONT  TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups//20260501T120000Z-000000000
=== CONT  TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main/20260501T120000Z
=== CONT  TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main:passwd/20260501T120000Z-000000000
=== CONT  TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main^/20260501T120000Z-000000000
=== CONT  TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main~3/20260501T120000Z-000000000
--- PASS: TestSanitizeBranchSegment (0.00s)
    --- PASS: TestSanitizeBranchSegment/slash (0.00s)
    --- PASS: TestSanitizeBranchSegment/glob_brackets (0.00s)
    --- PASS: TestSanitizeBranchSegment/with_null (0.00s)
    --- PASS: TestSanitizeBranchSegment/very_long (0.00s)
    --- PASS: TestSanitizeBranchSegment/japanese (0.00s)
    --- PASS: TestSanitizeBranchSegment/with_tab (0.00s)
    --- PASS: TestSanitizeBranchSegment/trailing_dot (0.00s)
    --- PASS: TestSanitizeBranchSegment/with_newline (0.00s)
    --- PASS: TestSanitizeBranchSegment/with_space (0.00s)
    --- PASS: TestSanitizeBranchSegment/release_dotted (0.00s)
    --- PASS: TestSanitizeBranchSegment/two_dots (0.00s)
    --- PASS: TestSanitizeBranchSegment/glob_asterisk (0.00s)
    --- PASS: TestSanitizeBranchSegment/single_dot (0.00s)
    --- PASS: TestSanitizeBranchSegment/leading_dash (0.00s)
    --- PASS: TestSanitizeBranchSegment/caret (0.00s)
    --- PASS: TestSanitizeBranchSegment/tilde (0.00s)
    --- PASS: TestSanitizeBranchSegment/backslash (0.00s)
    --- PASS: TestSanitizeBranchSegment/simple (0.00s)
    --- PASS: TestSanitizeBranchSegment/git_revision (0.00s)
=== CONT  TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main/20260501T120000Z-000000000_--no-ff
=== CONT  TestIsBackupRefRejectsRevisionSyntax/refs/heads/main
=== CONT  TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main@{-1}/20260501T120000Z-000000000
=== CONT  TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/feature-test/20260501T120000Z-123456789
--- PASS: TestCommandRunnerRunError (0.00s)
--- PASS: TestIsBackupRefRejectsRevisionSyntax (0.00s)
    --- PASS: TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main/20260501T120000Z-000000000 (0.00s)
    --- PASS: TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main/ (0.00s)
    --- PASS: TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups//20260501T120000Z-000000000 (0.00s)
    --- PASS: TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main/20260501T120000Z (0.00s)
    --- PASS: TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main:passwd/20260501T120000Z-000000000 (0.00s)
    --- PASS: TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main/20260501T120000Z-000000000/extra (0.00s)
    --- PASS: TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main^/20260501T120000Z-000000000 (0.00s)
    --- PASS: TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main~3/20260501T120000Z-000000000 (0.00s)
    --- PASS: TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/../../../etc/passwd (0.00s)
    --- PASS: TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main/20260501T120000Z-000000000_--no-ff (0.00s)
    --- PASS: TestIsBackupRefRejectsRevisionSyntax/refs/heads/main (0.00s)
    --- PASS: TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main@{-1}/20260501T120000Z-000000000 (0.00s)
    --- PASS: TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/feature-test/20260501T120000Z-123456789 (0.00s)
--- PASS: TestDiscoverIntegration (0.01s)
PASS
ok  	github.com/watany-dev/gitreal/internal/git	1.019s
-test.shuffle 1777627146564336076
=== RUN   TestSanitizeFieldNormalizesControlChars
=== PAUSE TestSanitizeFieldNormalizesControlChars
=== RUN   TestSendUnsupportedPlatform
=== PAUSE TestSendUnsupportedPlatform
=== RUN   TestCommandEscapesWindowsToastText
=== PAUSE TestCommandEscapesWindowsToastText
=== RUN   TestCommand
=== PAUSE TestCommand
=== RUN   TestSend
=== PAUSE TestSend
=== RUN   TestNotificationFieldsNeverEscapeShellOrPowerShell
=== PAUSE TestNotificationFieldsNeverEscapeShellOrPowerShell
=== RUN   TestSendRunnerError
=== PAUSE TestSendRunnerError
=== RUN   TestSendUsesPackageVariables
=== PAUSE TestSendUsesPackageVariables
=== CONT  TestSendUnsupportedPlatform
--- PASS: TestSendUnsupportedPlatform (0.00s)
=== CONT  TestSanitizeFieldNormalizesControlChars
=== CONT  TestCommandEscapesWindowsToastText
=== CONT  TestSend
=== CONT  TestSendRunnerError
--- PASS: TestSend (0.00s)
--- PASS: TestSendRunnerError (0.00s)
=== CONT  TestSendUsesPackageVariables
--- PASS: TestSendUsesPackageVariables (0.00s)
=== CONT  TestCommand
--- PASS: TestSanitizeFieldNormalizesControlChars (0.00s)
=== RUN   TestCommand/darwin
=== PAUSE TestCommand/darwin
=== RUN   TestCommand/linux
=== CONT  TestNotificationFieldsNeverEscapeShellOrPowerShell
--- PASS: TestCommandEscapesWindowsToastText (0.00s)
=== RUN   TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-0
=== PAUSE TestCommand/linux
=== PAUSE TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-0
=== RUN   TestCommand/windows
=== RUN   TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-1
=== PAUSE TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-1
=== PAUSE TestCommand/windows
=== RUN   TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-2
=== PAUSE TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-2
=== RUN   TestCommand/unsupported
=== RUN   TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-3
=== PAUSE TestCommand/unsupported
=== CONT  TestCommand/darwin
=== CONT  TestCommand/unsupported
=== PAUSE TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-3
=== CONT  TestCommand/linux
=== CONT  TestCommand/windows
=== RUN   TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-4
=== PAUSE TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-4
=== RUN   TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-5
=== PAUSE TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-5
=== RUN   TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-6
=== PAUSE TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-6
=== RUN   TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-7
=== PAUSE TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-7
=== RUN   TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-8
--- PASS: TestCommand (0.00s)
    --- PASS: TestCommand/darwin (0.00s)
    --- PASS: TestCommand/unsupported (0.00s)
    --- PASS: TestCommand/linux (0.00s)
    --- PASS: TestCommand/windows (0.00s)
=== PAUSE TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-8
=== RUN   TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-9
=== PAUSE TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-9
=== RUN   TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-10
=== PAUSE TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-10
=== CONT  TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-0
=== CONT  TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-9
=== CONT  TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-2
=== CONT  TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-7
=== CONT  TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-4
=== CONT  TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-1
=== CONT  TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-5
=== CONT  TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-10
=== CONT  TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-8
=== CONT  TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-3
=== CONT  TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-6
--- PASS: TestNotificationFieldsNeverEscapeShellOrPowerShell (0.00s)
    --- PASS: TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-0 (0.00s)
    --- PASS: TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-9 (0.00s)
    --- PASS: TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-7 (0.00s)
    --- PASS: TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-4 (0.00s)
    --- PASS: TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-5 (0.00s)
    --- PASS: TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-1 (0.00s)
    --- PASS: TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-10 (0.00s)
    --- PASS: TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-6 (0.00s)
    --- PASS: TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-2 (0.00s)
    --- PASS: TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-3 (0.00s)
    --- PASS: TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-8 (0.00s)
PASS
ok  	github.com/watany-dev/gitreal/internal/notify	1.011s
windows-latest (last 200 lines)
=== PAUSE TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main/20260501T120000Z
=== PAUSE TestSanitizeBranchSegment/leading_dash
=== RUN   TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main/
=== RUN   TestSanitizeBranchSegment/trailing_dot
=== PAUSE TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main/
=== PAUSE TestSanitizeBranchSegment/trailing_dot
=== RUN   TestSanitizeBranchSegment/with_space
=== PAUSE TestSanitizeBranchSegment/with_space
=== RUN   TestSanitizeBranchSegment/with_tab
=== PAUSE TestSanitizeBranchSegment/with_tab
=== RUN   TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups//20260501T120000Z-000000000
=== PAUSE TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups//20260501T120000Z-000000000
=== RUN   TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main/20260501T120000Z-000000000/extra
=== PAUSE TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main/20260501T120000Z-000000000/extra
=== RUN   TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/../../../etc/passwd
=== PAUSE TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/../../../etc/passwd
=== RUN   TestSanitizeBranchSegment/with_newline
=== PAUSE TestSanitizeBranchSegment/with_newline
=== RUN   TestSanitizeBranchSegment/with_null
=== PAUSE TestSanitizeBranchSegment/with_null
=== RUN   TestSanitizeBranchSegment/very_long
=== PAUSE TestSanitizeBranchSegment/very_long
=== RUN   TestSanitizeBranchSegment/japanese
=== PAUSE TestSanitizeBranchSegment/japanese
=== CONT  TestBranchAndUpstream
--- PASS: TestBranchAndUpstream (0.00s)
=== CONT  TestAheadCountEmptyAndInvalid
--- PASS: TestAheadCountEmptyAndInvalid (0.00s)
=== CONT  TestResetRescueAndHelpers
--- PASS: TestResetRescueAndHelpers (0.00s)
=== CONT  TestSanitizeBranchSegmentFallback
--- PASS: TestSanitizeBranchSegmentFallback (0.00s)
=== CONT  TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main/20260501T120000Z-000000000_--no-ff
=== CONT  TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/../../../etc/passwd
=== CONT  TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main/20260501T120000Z-000000000
=== CONT  TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main/20260501T120000Z-000000000/extra
=== CONT  TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups//20260501T120000Z-000000000
=== CONT  TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main/
=== CONT  TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main/20260501T120000Z
=== CONT  TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main@{-1}/20260501T120000Z-000000000
=== CONT  TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main~3/20260501T120000Z-000000000
=== CONT  TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main:passwd/20260501T120000Z-000000000
=== CONT  TestIsBackupRefRejectsRevisionSyntax/refs/heads/main
=== CONT  TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main^/20260501T120000Z-000000000
=== CONT  TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/feature-test/20260501T120000Z-123456789
--- PASS: TestIsBackupRefRejectsRevisionSyntax (0.01s)
    --- PASS: TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main/20260501T120000Z-000000000_--no-ff (0.00s)
    --- PASS: TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/../../../etc/passwd (0.00s)
    --- PASS: TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main/20260501T120000Z-000000000 (0.00s)
    --- PASS: TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main/20260501T120000Z-000000000/extra (0.00s)
    --- PASS: TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups//20260501T120000Z-000000000 (0.00s)
    --- PASS: TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main/ (0.00s)
    --- PASS: TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main/20260501T120000Z (0.00s)
    --- PASS: TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main@{-1}/20260501T120000Z-000000000 (0.00s)
    --- PASS: TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main~3/20260501T120000Z-000000000 (0.00s)
    --- PASS: TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main:passwd/20260501T120000Z-000000000 (0.00s)
    --- PASS: TestIsBackupRefRejectsRevisionSyntax/refs/heads/main (0.00s)
    --- PASS: TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/main^/20260501T120000Z-000000000 (0.00s)
    --- PASS: TestIsBackupRefRejectsRevisionSyntax/refs/gitreal/backups/feature-test/20260501T120000Z-123456789 (0.00s)
=== CONT  TestSanitizeBranchSegment/caret
=== CONT  TestSanitizeBranchSegment/very_long
=== CONT  TestSanitizeBranchSegment/japanese
=== CONT  TestSanitizeBranchSegment/with_newline
=== CONT  TestSanitizeBranchSegment/with_tab
=== CONT  TestSanitizeBranchSegment/with_space
=== CONT  TestSanitizeBranchSegment/leading_dash
=== CONT  TestSanitizeBranchSegment/trailing_dot
=== CONT  TestSanitizeBranchSegment/two_dots
=== CONT  TestSanitizeBranchSegment/with_null
=== CONT  TestSanitizeBranchSegment/glob_asterisk
=== CONT  TestSanitizeBranchSegment/single_dot
=== CONT  TestSanitizeBranchSegment/tilde
=== CONT  TestSanitizeBranchSegment/glob_brackets
=== CONT  TestSanitizeBranchSegment/release_dotted
=== CONT  TestSanitizeBranchSegment/git_revision
=== CONT  TestSanitizeBranchSegment/backslash
=== CONT  TestSanitizeBranchSegment/simple
=== CONT  TestSanitizeBranchSegment/slash
--- PASS: TestSanitizeBranchSegment (0.01s)
    --- PASS: TestSanitizeBranchSegment/caret (0.00s)
    --- PASS: TestSanitizeBranchSegment/very_long (0.00s)
    --- PASS: TestSanitizeBranchSegment/japanese (0.00s)
    --- PASS: TestSanitizeBranchSegment/with_newline (0.00s)
    --- PASS: TestSanitizeBranchSegment/with_tab (0.00s)
    --- PASS: TestSanitizeBranchSegment/with_space (0.00s)
    --- PASS: TestSanitizeBranchSegment/leading_dash (0.00s)
    --- PASS: TestSanitizeBranchSegment/trailing_dot (0.00s)
    --- PASS: TestSanitizeBranchSegment/two_dots (0.00s)
    --- PASS: TestSanitizeBranchSegment/with_null (0.00s)
    --- PASS: TestSanitizeBranchSegment/glob_asterisk (0.00s)
    --- PASS: TestSanitizeBranchSegment/single_dot (0.00s)
    --- PASS: TestSanitizeBranchSegment/tilde (0.00s)
    --- PASS: TestSanitizeBranchSegment/glob_brackets (0.00s)
    --- PASS: TestSanitizeBranchSegment/release_dotted (0.00s)
    --- PASS: TestSanitizeBranchSegment/git_revision (0.00s)
    --- PASS: TestSanitizeBranchSegment/backslash (0.00s)
    --- PASS: TestSanitizeBranchSegment/simple (0.00s)
    --- PASS: TestSanitizeBranchSegment/slash (0.00s)
--- PASS: TestCommandRunnerRunError (0.68s)
=== NAME  TestDiscoverIntegration
    git_test.go:607: Root() = "C:/Users/runneradmin/AppData/Local/Temp/TestDiscoverIntegration1722981622/001", want "C:\\Users\\RUNNER~1\\AppData\\Local\\Temp\\TestDiscoverIntegration1722981622\\001"
--- FAIL: TestDiscoverIntegration (0.74s)
FAIL
FAIL	github.com/watany-dev/gitreal/internal/git	0.840s
-test.shuffle 1777627176993076300
=== RUN   TestSendUnsupportedPlatform
=== PAUSE TestSendUnsupportedPlatform
=== RUN   TestCommand
=== PAUSE TestCommand
=== RUN   TestSend
=== PAUSE TestSend
=== RUN   TestSanitizeFieldNormalizesControlChars
=== PAUSE TestSanitizeFieldNormalizesControlChars
=== RUN   TestSendRunnerError
=== PAUSE TestSendRunnerError
=== RUN   TestCommandEscapesWindowsToastText
=== PAUSE TestCommandEscapesWindowsToastText
=== RUN   TestNotificationFieldsNeverEscapeShellOrPowerShell
=== PAUSE TestNotificationFieldsNeverEscapeShellOrPowerShell
=== RUN   TestSendUsesPackageVariables
=== PAUSE TestSendUsesPackageVariables
=== CONT  TestSendUnsupportedPlatform
=== CONT  TestSanitizeFieldNormalizesControlChars
=== CONT  TestNotificationFieldsNeverEscapeShellOrPowerShell
=== CONT  TestSendUsesPackageVariables
=== CONT  TestSend
=== CONT  TestCommandEscapesWindowsToastText
=== CONT  TestCommand
--- PASS: TestSendUnsupportedPlatform (0.00s)
=== CONT  TestSendRunnerError
=== RUN   TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-0
--- PASS: TestSendRunnerError (0.00s)
--- PASS: TestSanitizeFieldNormalizesControlChars (0.00s)
=== RUN   TestCommand/darwin
--- PASS: TestSend (0.00s)
=== PAUSE TestCommand/darwin
--- PASS: TestSendUsesPackageVariables (0.00s)
=== RUN   TestCommand/linux
=== PAUSE TestCommand/linux
=== PAUSE TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-0
=== RUN   TestCommand/windows
=== PAUSE TestCommand/windows
=== RUN   TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-1
--- PASS: TestCommandEscapesWindowsToastText (0.00s)
=== RUN   TestCommand/unsupported
=== PAUSE TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-1
=== PAUSE TestCommand/unsupported
=== RUN   TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-2
=== CONT  TestCommand/darwin
=== CONT  TestCommand/windows
=== CONT  TestCommand/linux
=== CONT  TestCommand/unsupported
=== PAUSE TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-2
=== RUN   TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-3
=== PAUSE TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-3
--- PASS: TestCommand (0.00s)
    --- PASS: TestCommand/darwin (0.00s)
    --- PASS: TestCommand/linux (0.00s)
    --- PASS: TestCommand/unsupported (0.00s)
    --- PASS: TestCommand/windows (0.00s)
=== RUN   TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-4
=== PAUSE TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-4
=== RUN   TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-5
=== PAUSE TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-5
=== RUN   TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-6
=== PAUSE TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-6
=== RUN   TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-7
=== PAUSE TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-7
=== RUN   TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-8
=== PAUSE TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-8
=== RUN   TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-9
=== PAUSE TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-9
=== RUN   TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-10
=== PAUSE TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-10
=== CONT  TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-0
=== CONT  TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-5
=== CONT  TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-10
=== CONT  TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-2
=== CONT  TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-6
=== CONT  TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-9
=== CONT  TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-4
=== CONT  TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-1
=== CONT  TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-8
=== CONT  TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-3
=== CONT  TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-7
--- PASS: TestNotificationFieldsNeverEscapeShellOrPowerShell (0.00s)
    --- PASS: TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-0 (0.00s)
    --- PASS: TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-5 (0.00s)
    --- PASS: TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-10 (0.00s)
    --- PASS: TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-2 (0.00s)
    --- PASS: TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-9 (0.00s)
    --- PASS: TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-6 (0.00s)
    --- PASS: TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-1 (0.00s)
    --- PASS: TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-4 (0.00s)
    --- PASS: TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-3 (0.00s)
    --- PASS: TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-7 (0.00s)
    --- PASS: TestNotificationFieldsNeverEscapeShellOrPowerShell/payload-8 (0.00s)
PASS
ok  	github.com/watany-dev/gitreal/internal/notify	1.065s
FAIL

The diagnose-test-failure job uploaded test artifacts and showed the
exact failure on both macOS and Windows is the same:

  macOS:   Root() = "/private/var/folders/.../001"
           want    "/var/folders/.../001"
  Windows: Root() = "C:/Users/runneradmin/AppData/Local/Temp/.../001"
           want    "C:\\Users\\RUNNER~1\\AppData\\Local\\Temp\\...\\001"

`git rev-parse --show-toplevel` (which Discover() returns verbatim):

- Resolves symlinks on macOS — /var → /private/var
- Returns forward slashes on Windows where Go's filepath uses backslash
- Returns the Windows long-path form (runneradmin) where t.TempDir()
  may return the 8.3 short form (RUNNER~1)

These are real OS differences exposed by the new cross-OS test matrix,
not bugs in Discover() itself. Fix the comparison in the test by piping
both sides through filepath.FromSlash + filepath.EvalSymlinks before
the equality check.

Also drop the temporary diagnose-test-failure job — its purpose was to
surface this failure once, and it's no longer needed.

https://claude.ai/code/session_01Sy9fRJ7oL6ghGxJAVvEPLW
@watany-dev watany-dev merged commit d5c548c into main May 1, 2026
13 of 14 checks passed
@watany-dev watany-dev deleted the claude/enhance-ci-pipeline-6VE3k branch May 1, 2026 09:40
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