A PySide6 desktop app for dispatching GitHub Actions workflows across many repositories.
- Resizable and movable table columns.
- Checkbox filter: only show repositories with the global branch/pattern.
- Checkbox filter: only show repositories with the selected workflow.
- Global branch supports wildcard patterns such as:
feature/core_revamp_archiving/revamp_archiving_*
It first uses shell-style wildcard matching and then falls back to regex matching. When multiple branches match, the lexicographically last branch is used.
- Validation now marks queued/stuck rows as finished when the validation worker completes.
- Save/load repository bundle JSON files for later reuse.
python -m venv .venv
. .\.venv\Scripts\Activate.ps1
python -m pip install --upgrade pip
pip install -r requirements.txtSet a GitHub token:
$env:GITHUB_TOKEN="ghp_xxx"Copy and edit config:
copy config.example.yaml config.yamlRun:
python app.py- Click Refresh.
- Enter the global branch or wildcard pattern.
- Click Validate visible.
- Enable either:
- Only repos with global branch/pattern
- Only repos with workflow
- Click Select visible.
- Click Save bundle if this repo set should be reused.
- Click Run selected.
Bundles are JSON files:
{
"organization": "ManiVaultStudio",
"workflow": "build.yml",
"global_branch": "feature/core_revamp_archiving/revamp_archiving_*",
"selected_repositories": [
{
"full_name": "ManiVaultStudio/core",
"branch_override": ""
}
]
}Branch names containing / are now URL-encoded for GitHub branch checks and compare calls. This matters for branches such as:
feature/core_revamp_archiving/revamp_archiving
The branch/pattern filter still depends on validation results. After changing the global branch/pattern, click Validate visible. If the strict branch/workflow filters hide all rows before validation, Validate visible now validates all repositories instead of doing nothing.
Validation of large repository sets is now more robust:
- every worker creates and closes its own
httpx.Clientinside the worker thread; - the main GUI thread no longer shares one HTTP client with background workers;
- validation reports progress with a progress bar;
- validation adds a small pause every 20 repositories to reduce GUI event pressure and GitHub secondary rate-limit risk.
This should fix crashes during validation of large organization-wide selections.
This version separates validation state from CI state.
Statusmeans the application state, for exampleReady,Validating,Dispatching.Latest CImeans the latest GitHub Actions result for the selected workflow and branch, for examplesuccess,failure,queued, orin_progress.
Poll once and continuous polling now rediscover the latest workflow run for each repository every cycle. This means:
- after reopening the app,
Validate visible+Poll oncewill find an existing failed/successful CI run; - if someone re-runs CI in GitHub while the app is open, the app switches to the newer run automatically;
- polling can be used as a dashboard, not only for runs launched by this app.
This version removes GUI-updating lambdas connected directly to worker-thread signals and replaces them with @Slot methods on the main window. This avoids Qt's:
QObject: Cannot create children for a parent that is in a different thread
The crash was caused by starting follow-up polling from the dispatch worker's thread instead of the GUI thread.
This version reverts the custom smart-sort item implementation because it could crash after refresh on some PySide/Qt builds.
Sorting is now handled by Qt's built-in QTableWidget sorting:
- click a column header to sort ascending/descending;
- columns remain resizable and movable;
- sorting is disabled while rows are being refreshed, then re-enabled;
Auto-sort during updatescontrols whether updates reapply the current sort automatically.
This is less fancy than v8's smart sorting, but significantly safer.
This version fixes a table-indexing bug that occurred after sorting.
Older versions used the repository index as if it were the physical table row. After sorting, those are no longer the same. During validation, updates could therefore be written into the wrong rows, leaving some repositories stuck as Queued validation or Validating.
v10 now:
- stores a stable repository index in each row;
- finds the current physical table row before updating;
- temporarily disables auto-sort during validation;
- restores the previous auto-sort setting after validation;
- normalizes any rows still marked as active when the worker finishes.