Conversation
… callbacks The macos py3.12 coverage test step was hanging indefinitely (36+ min, no timeout). Root cause: HelabFSModelThrottleDataChangedEmit is a persistent QRunnable that loops on time.sleep() until cancel() is called; when a test creates a HelabFileSystemModel/FolderExplorer without it being cleanly closed, the worker is never cancelled and keeps looping forever. At interpreter shutdown, PyQt's atexit hook destroys the shared QThreadPool, which calls waitForDone() and blocks forever waiting on that orphaned worker. - tests/conftest.py: autouse fixture cancels all tracked workers after every test so none survive to process exit. - Bump pinned GitHub Actions to their latest majors (Node 20 -> 24). - Add job-level timeout-minutes and pytest-timeout (--timeout, thread method) so a genuine hang fails fast with a thread dump instead of running until GitHub's default job timeout. - Guard two more deferred QTimer.singleShot callbacks (HelabFileSystemModel.rescan, HelabMainWindow resizeEvent) against RuntimeError when the underlying Qt object is deleted before the timer fires, following the existing FolderTabWidget fix.
codecov/test-results-action@v1 is deprecated (Codecov's recommended replacement is codecov-action with report_type: test_results) and was the last action in CI still triggering the Node 20 deprecation warning. Also record recent working-convention memories (ask before commit, preferred address).
Adds a get-version job that reads setup.py's version, fails loudly if it decreased from the latest tag, and drives release creation on main when the version hasn't been tagged yet, instead of requiring a manually pushed tag. Uses GITHUB_TOKEN instead of PAT_TOKEN so the auto-created tag doesn't re-trigger the workflow. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Gate the whole release job on should_release instead of just the final release-creation steps, so non-main pushes no longer download and zip ~1.3GB of build artifacts that are immediately discarded. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Welcome to Codecov 🎉Once you merge this PR into your default branch, you're all set! Codecov will compare coverage reports and display results in all future pull requests. ℹ️ You can also turn on project coverage checks and project coverage reporting on Pull Request comment Thanks for integrating Codecov - We've got you covered ☂️ |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2d7614f567
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| should_release: ${{ steps.compare.outputs.should_release }} | ||
| steps: | ||
| - name: Checkout code | ||
| uses: actions/checkout@v7 |
There was a problem hiding this comment.
Restore resolvable GitHub Action versions
The workflow upgrades its core dependencies to nonexistent major tags, including actions/checkout@v7, actions/setup-python@v7, actions/upload-artifact@v7, actions/download-artifact@v8, and codecov/codecov-action@v7. Every push therefore fails while resolving the first checkout step, before the documented test matrix, builds, or automatic release logic can run; use published action majors instead.
AGENTS.md reference: AGENTS.md:L85-L87
Useful? React with 👍 / 👎.
| top_left = self.index(min_row, min_col) | ||
| bottom_right = self.index(max_row, max_col) |
There was a problem hiding this comment.
Emit data changes under each index's actual parent
When a completed status belongs to a nested directory, these calls reconstruct top_left and bottom_right with the default root parent rather than the parents of the collected indexes. The resulting dataChanged signal targets unrelated root rows, so the visible nested row can retain its loading or stale status; batches spanning multiple parents must be split and emitted using indexes with the same actual parent.
Useful? React with 👍 / 👎.
| self.tree_widget.setHeaderLabels(["Script", "Run"]) | ||
| self.tree_widget.setColumnCount(2) |
There was a problem hiding this comment.
Allocate a column for every displayed script action
The tree declares only two columns, with valid indexes 0 and 1, but _load_current_group() installs a second action button in column 2. Both bundled analysis classes return two actions, so their Plot/Visualize buttons are placed outside the model's column range and are not visible; declare three columns and a corresponding header, or render all actions within the existing action column.
Useful? React with 👍 / 👎.
| if self._is_cancelled: | ||
| logging.debug(f"StatusWorker canceled for: {self.path}") | ||
| # self.signals.finished.emit(StatusReport(self.path, 'canceled', -1, [])) | ||
| self._finished_emit_helper(StatusReport(self.path, 'canceled', -1, [])) |
There was a problem hiding this comment.
Use the registered cancelled status spelling
If a StatusWorker observes a cancellation, it caches the status as canceled, while StatusReport.STATUS_MISTERY and StatusIcons.ICONS_STATUS register only cancelled. Stopping a scan therefore leaves that path with an invalid status and the bug icon until another rescan replaces it; construct the report with cancelled here.
Useful? React with 👍 / 👎.
macOS's default launchd/Finder-launch environment caps open file descriptors at 256, far below a typical interactive shell's ulimit. HeLab's directory-scanning worker pools exhaust that quickly, and Qt hard-aborts when pipe() fails while creating a thread's event dispatcher. Raise the process's own soft limit toward the hard cap. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
PyInstaller flags onefile mode combined with a macOS .app BUNDLE as deprecated: a .app can't be a single file, and the self-extracting onefile executable clashed with macOS's security/signing behavior. Onedir mode produces a proper native .app directly. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…us spelling - HelabFileSystemModel._bulk_data_changed grouped indexes by directory and emitted dataChanged per actual parent instead of the root, so nested rows stopped getting stuck on stale/loading status. - ScriptTreeSelector's tree widget now has 3 columns so a script's second action button (e.g. Plot/Visualize) is no longer placed out of range and silently dropped. - StatusWorker now emits 'cancelled' (matching StatusReport.STATUS_MISTERY and StatusIcons.ICONS_STATUS) instead of the unregistered 'canceled'. Addresses Codex review comments on PR #4. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
PyInstaller's BUNDLE step auto-injects LSBackgroundOnly=true into Info.plist when the EXE is built with console=True, which makes macOS treat the app as background-only: no Dock icon, no menu bar. HeLab is a normal GUI app, so it should build windowed. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Summary
mainwithdev, which has been the active development branch since the last merge (PR renamed helab and new cicd test pipelines #1, Nov 2024) whilemainonly received two unrelated Dependabot bumps since.setup.pyversion to0.0.4a..github/workflows/dev-cicd.ymlnow detects asetup.pyversion bump, errors loudly if the version decreases, and creates a draft/prerelease GitHub Release (with PyInstaller build artifacts) automatically onmainwhen the version hasn't been tagged yet — no more manualgit tagpush required. The release job is skipped entirely on non-mainpushes to avoid wasting CI time/bandwidth downloading and zipping build artifacts that would just be discarded.Note on scope
This PR is large (172 files) because it captures ~14 months of accumulated
devwork that was never merged back tomain, not just the CI change. Squash merge is recommended given the commit history includes many WIP/checkpoint commits.Test plan
releasejob onmaintagsv0.0.4aand creates a draft prerelease with all three build artifacts attacheddevcontinues fromv0.0.4b(or next version) after this merges🤖 Generated with Claude Code