Skip to content

Add release backups and search/sort on the Repositories page - #144

Merged
GitTimeraider merged 2 commits into
developfrom
feature/release-backups
Sep 28, 2026
Merged

GitTimeraider merged 2 commits into
developfrom
feature/release-backups

Conversation

@GitTimeraider

@GitTimeraider GitTimeraider commented Sep 28, 2026 •

Copy link
Copy Markdown
Owner

Summary

This PR adds two features:

  1. A per-repository option to also back up GitHub release files.
  2. Search and sorting on the Repositories page.

1. Release backups

Each repository gets a new Release Files setting:

Option Behaviour
Don't back up releases (default) Same as before, no releases
Latest release Newest published release
Last 5 releases 5 newest published releases
All releases Every published release

For each selected release, the backup gets _releases/<tag>/ containing:

  • every uploaded release asset
  • the release's source code zip (<repo>-<tag>-source.zip)

This works for folder, ZIP and TAR.GZ backups. Retention cleanup is unchanged.

  • models.py: new Repository.release_mode column (none / latest / last5 / all) and a RELEASE_MODES map.
  • init_db.py: adds the column to existing databases on container start (ALTER TABLE). Existing repositories get none, so their behaviour doesn't change.
  • backup_service.py: _download_releases() runs after the clone. It lists releases through the GitHub API (newest first) and streams the assets and source zips to disk. It uses the repository's stored token, which private repositories need.
  • app.py: the add, add-by-username and edit routes save the setting. Unknown values fall back to none.
  • Templates: a dropdown on the add, add-by-username and edit pages. The repository card shows the setting when it isn't none.

Behaviour choices:

  • Draft releases are skipped. Pre-releases are included, so "Latest release" can be a pre-release.
  • If a release download fails, the whole backup job is marked failed, so a backup can't be missing releases without anyone noticing.
  • Tag and asset names are sanitised before they're used as file names, so path traversal isn't possible.

2. Search and sort on the Repositories page

  • Search box: case-insensitive filter on repository name and owner. It also matches owner/name, so wemino finds all of that user's repositories, co-op finds every repository with "co-op" in its name, and wemino/co narrows to both. It shows "Showing X of Y", or a "No repositories match" message.
  • Sort dropdown: Date added (the previous order), Repository name A–Z / Z–A, Owner A–Z / Z–A (then by name), Last backup newest / oldest first. Repositories that were never backed up always go last.
  • Filtering and sorting run in the browser, so there's no page reload. The last used sort and search are kept in localStorage.
  • New Repository.owner property, taken from the URL (HTTPS and git@ formats). Each card now shows the owner.
  • The /repositories query now orders by id explicitly, so "Date added" is deterministic.

Testing

  • Migration: upgraded a database with the old schema through init_db.py. The column was added, the existing row got none, and a second run did nothing.
  • Release downloads: tested against fake releases on a local HTTP server, with PyGithub mocked. Draft skipped, latest/last 5/all limits correct, token and Accept: application/octet-stream sent for assets, _releases/ included in the ZIP backup. The code reached the real GitHub API successfully on this repository, but the repository has no releases, so no real download was tested end-to-end. Please try one repository that has releases before merging.
  • Search/sort: rendered /repositories through the Flask test client with 5 sample repositories and drove it in headless Chromium. Checked all 7 sort orders; the searches wemino, co-op, COOP, wemino/co and a search with no matches; that the choices are restored after reload; and that there are no JavaScript errors.
  • All changed templates parse with Jinja.

🤖 Generated with Claude Code

https://claude.ai/code/session_01TWkh86yGwethdcSzje555s

Each repository can now also back up release files: none (default,
unchanged behaviour), the latest release, the last 5 releases, or all
releases. For each release the uploaded assets and the source code zip
are stored in a _releases/<tag>/ folder inside the backup. Draft
releases are skipped.

init_db.py adds the new release_mode column to existing databases.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TWkh86yGwethdcSzje555s
Repositories can be sorted by date added, repository name, owner
(A-Z / Z-A) or last backup time (newest / oldest first; never backed
up repositories go last). A search box filters on repository name and
owner, including "owner/name". Filtering and sorting happen in the
browser, and the last used sort and search are remembered.

Adds a Repository.owner property derived from the URL, which is also
shown on each repository card.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TWkh86yGwethdcSzje555s
@GitTimeraider GitTimeraider changed the title Add per-repository option to back up GitHub releases Add release backups and search/sort on the Repositories page Sep 28, 2026
@GitTimeraider
GitTimeraider merged commit e8d74d7 into develop Sep 28, 2026
1 check passed
@GitTimeraider
GitTimeraider deleted the feature/release-backups branch September 28, 2026 11:41
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.

2 participants