Skip to content

ci(release): the smoke launches quit cleanly and check config.toml was saved, and the Windows zip leaves no trace (#2720) - #2933

Merged
mgradwohl merged 2 commits into
mainfrom
ci/smoke-clean-quit-2720
Oct 25, 2026
Merged

mgradwohl merged 2 commits into
mainfrom
ci/smoke-clean-quit-2720

Conversation

@mgradwohl

Copy link
Copy Markdown
Owner

Description

The release smoke checks (validate-linux-package, validate-windows-package) killed TaskSmack after 5 s, so nothing checked that the settings are saved on exit, and nothing checked that the portable .zip can be deleted without leaving anything behind (#2488).

No new hook. The issue proposed TASKSMACK_EXIT_AFTER_FRAMES, but TASKSMACK_SCREENSHOT=<png>;after=N (#2827) already gives a normal quit:

  • ScreenshotLayer::finish() calls Window::requestClose(), the same path the title bar's Close button takes. Application::run() stops, every layer's onDetach() runs, and ShellLayer::onDetach() calls UserConfig::save().
  • main.cpp returns EXIT_FAILURE when the hook was set and no frame got written, so exit code 0 means the capture ran and the app shut down normally.
  • The capture's glReadPixels already runs on Mesa llvmpipe in Windows CI (test_ScreenshotOnDisplay, which also asserts config.toml was saved). The Linux smoke uses SDL's offscreen driver on an EGL pbuffer, which no CI job has captured from until now (Linux CI runs that test under Xvfb). See Additional Notes.

So both smoke steps use TASKSMACK_SCREENSHOT as the quit.

validate-linux-package (smoke-check.sh, used for both the .deb and the .tar.gz):

  • Each launch gets its own mktemp -d TASKSMACK_CONFIG_DIR and TASKSMACK_SCREENSHOT=$work/smoke.png;after=5, under timeout 60 instead of timeout 5.
  • It must exit 0. A timeout (124) or any other status fails, and so does a missing frame.
  • It must leave a config.toml whose [theme] table is followed by id = '...'. With no input, nothing writes that file before the shutdown save, so finding it proves the save ran.
  • The asset log checks (Assets directory found:, no Icon font not found, Loaded theme:) are unchanged.

validate-windows-package ("Smoke-check extracted executable"; same structure, 5-minute step timeout and 15-minute job timeout):

  • The kill is gone. TASKSMACK_SCREENSHOT=<work>\smoke.png;after=$ALIVE_SECONDS is set, and the step waits up to STARTUP_TIMEOUT_SECONDS + ALIVE_SECONDS + 30 s (95 s). It caches $proc.Handle so ExitCode is still readable after exit. The exit code must be 0. The [critical]/[error], Entering main loop, llvmpipe renderer and OpenGL ≥ 3.3 checks are unchanged. The frame and config.toml with [theme] must exist.
  • Leave no trace: before the launch and again after the exit, the step lists every entry under %APPDATA% and %LOCALAPPDATA% whose name matches tasksmack (case-insensitive, -Depth 5, which reaches Local\Microsoft\Windows\WER\ReportArchive\<report>). Any new entry fails the step unless it is under the config dir or a %TEMP%. That means the private one, or the runner's own temp folder under both its GetTempPath() spelling and %LOCALAPPDATA%\Temp, since the runner's TEMP can be an 8.3 short path. The step then deletes the folder TaskSmack ran from with Remove-Item -Recurse -Force -ErrorAction Stop, so any locked file fails it (a leftover helper process, for example).
  • Two new lines in the step summary: "Quit by itself with config.toml saved" and "Left no trace".

The signed x64 leg runs the signed package unchanged. The smoke still runs a temporary copy of the extracted folder with Mesa beside the exe, and that copy is the folder that gets deleted, because it is the one TaskSmack ran from. The untouched extracted/ folder was never run, so deleting it would prove nothing.

CONTRIBUTING.md ("Release Artifact Validation") now describes the clean quit and the trace check in place of the 5-second timeout.

Closes #2720

PR Size

Small: about 160 lines changed in release.yml (mostly the rewritten Windows smoke step) and 12 in CONTRIBUTING.md.

Type of Change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update
  • Build/CI improvement

Checklist

  • I have read the CONTRIBUTING guidelines
  • My code follows the project's coding standards
  • I have run clang-tidy and addressed any warnings (no C++ changed)
  • I have run clang-format on my changes (no C++ changed)
  • I have run pre-commit run --all-files or installed pre-commit hooks (pre-commit run --files on both files, actionlint included: all passed)
  • I have added tests that prove my fix/feature works (no new test: both steps were dry-run against fakes, below)
  • All new and existing tests pass
  • I have updated documentation as needed

Testing

pre-commit run --files .github/workflows/release.yml CONTRIBUTING.md   # all passed, incl. "Lint GitHub Actions workflows" (actionlint)
python -I -m unittest discover -s tests/tools -p "test_*.py"           # nothing there covers release.yml

Both steps' scripts were extracted from release.yml with tests/tools/workflow_steps.py and dry-run on Windows against fake binaries:

  • Linux smoke-check.sh (Git Bash, with QUIT_TIMEOUT_SECONDS cut to 3): a fake that quits 0 with the frame and a [theme] id passes. Each of these fails with its own message: no config.toml, no frame, exit 1, a hang (timeout 124), [theme] without an id, and no assets log line.
  • Windows step (pwsh, with a fake TaskSmack.exe compiled from C#): the good run passes and writes the summary. Each of these fails for the right reason: no config.toml, exit 1, an [error] log line, a new %LOCALAPPDATA%\TaskSmack-dryrun-leak directory (flagged by name), and a child process left with its working directory in the package folder (Remove-Item reports "being used by another process"). On a dev machine the two AppData scans took about 4 s in all.

The real binaries weren't launched: no local release package exists, and no local build has the hook. The end-to-end proof is the next release run, or a dry run of release.yml dispatched from this branch.

Additional Notes

  • Linux offscreen readback: this is the first time the screenshot hook's glReadPixels runs on SDL's offscreen driver in CI; Linux CI's test_ScreenshotOnDisplay runs under Xvfb. Reading back from Mesa's EGL pbuffer is expected to work. If it doesn't, the Linux legs fail with "exited with status 1" and a TASKSMACK_SCREENSHOT: ... not written log line, not by hanging. A release.yml dry run (workflow_dispatch, dry_run: true) from this branch would confirm it before a release depends on it.
  • The trace check covers files and folders only; it doesn't cover registry keys.
  • No retry on the folder delete, as the issue asks: a lock that is only briefly held (an antivirus scan, say) would fail the release smoke.
  • Labelled backport:0.9 (milestone v0.9.1); this only touches release.yml and docs.

🤖 Generated with Claude Code

…s saved, and the Windows zip leaves no trace (#2720)

The release smoke checks killed TaskSmack after 5 s, so nothing checked that settings are saved on
exit, and nothing checked that the portable .zip can be deleted without a trace (#2488).

No new hook: TASKSMACK_SCREENSHOT=<png>;after=N (#2827) already gives a normal quit. ScreenshotLayer
writes the frame and calls Window::requestClose(), the title bar Close button's path, so every layer
detaches and ShellLayer::onDetach() saves config.toml; a run that wrote no frame exits non-zero. Its
glReadPixels already runs on Mesa llvmpipe in Windows CI (test_ScreenshotOnDisplay).

- validate-linux-package: each launch (.deb and .tar.gz) gets its own TASKSMACK_CONFIG_DIR and
  TASKSMACK_SCREENSHOT after=5, must exit 0 within 60 s, write the frame, and leave a config.toml
  whose [theme] table has an id. The asset log checks are unchanged.
- validate-windows-package: the same quit and config.toml check in place of the kill (the wait is
  STARTUP_TIMEOUT_SECONDS + ALIVE_SECONDS + 30 s; the step's 5-minute timeout is unchanged), with
  the log, llvmpipe and OpenGL 3.3 checks as before. Then leave no trace: TaskSmack-named entries
  under %APPDATA% and %LOCALAPPDATA% (case-insensitive, 5 levels deep) are listed before the launch
  and after the exit, and any new one outside the config dir and %TEMP% fails; then the folder
  TaskSmack ran from is deleted with Remove-Item -ErrorAction Stop, failing on any locked file.
- CONTRIBUTING.md's "Release Artifact Validation" describes the clean quit and the trace check.

Closes #2720

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@mgradwohl mgradwohl added this to the v0.9.1 milestone Oct 25, 2026
@mgradwohl mgradwohl added ci Refers to issues in the ci workflow release testing agent:Windows Owned by the Windows Claude session (bug-fix conveyor) backport:0.9 Cherry-pick to release/0.9 after merge labels Oct 25, 2026
@github-actions github-actions Bot added the documentation Improvements or additions to documentation label Oct 25, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Scanned Files

None

@mgradwohl

Copy link
Copy Markdown
Owner Author

Release dry run 40200876251 on this branch: every smoke launch quit by itself and saved config.toml. Linux: the .deb and the .tar.gz on x64 and arm64. Windows: the .zip on x64 and arm64, which also left no trace. (The first dry run hit the #2906 sign-off flake in the Windows build's tests, before #2931 landed.)

@mgradwohl
mgradwohl merged commit 3026a44 into main Oct 25, 2026
33 checks passed
@mgradwohl
mgradwohl deleted the ci/smoke-clean-quit-2720 branch October 25, 2026 14:39
@mgradwohl

Copy link
Copy Markdown
Owner Author

Git push to origin failed for release/0.9 with exitcode 1

@mgradwohl

Copy link
Copy Markdown
Owner Author

Backport held: the backport action failed to push (its token can't push a release.yml change), and a hand cherry-pick onto release/0.9 applies cleanly but would break that branch's release smoke checks. release/0.9 has no TASKSMACK_SCREENSHOT hook (#2827, v0.10.0 work), and these checks quit TaskSmack through it, so every launch there would run into the timeout. Asking the maintainer whether #2720 stays main-only (v0.10.0) or the hook goes to release/0.9 too.

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

Labels

agent:Windows Owned by the Windows Claude session (bug-fix conveyor) ci Refers to issues in the ci workflow documentation Improvements or additions to documentation release testing

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[CI] Clean-exit hook for smoke checks (assert config saved on exit) and a zip leave-no-trace check

1 participant