Skip to content

Commit a2296cd

Browse files
authored
feat: add 7zz version locking and PR-only upstream updates (#25)
## Summary - Lock the bundled 7zz version in `py7zz/7zz_version.txt` and surface it via `py7zz --version` for reproducible builds. - Add `scripts/get_7zz.sh` modes (detect/get/update) with download verification and robust version comparison. - Use the locked version across CI/release workflows; no dynamic fetch during builds. - Add a new check-upstream workflow that monitors upstream 7zz, updates the lock file on a fixed branch, and opens/refreshes a single PR—no direct push/tag/release; publishing stays owner-driven. ## Key Changes - `py7zz/7zz_version.txt`: single source of truth for the bundled 7zz. - `scripts/get_7zz.sh`: mode-based helper, fixes PATCH parsing for pre-release suffixes, download verification. - `py7zz/cli.py`: `--version` now shows both py7zz and bundled 7zz. - Workflows: - `.github/workflows/ci.yml`, `.github/workflows/release.yml`: consume the locked version. - `.github/workflows/check-upstream.yml`: new PR-only auto-update (peter-evans/create-pull-request), fixed branch `chore/update-7zz`, `dpkg --compare-versions`, deduped PRs, labels `dependencies`, `automated`, `chore`, no auto tag/release. - `REUSE.toml`: licensing metadata for the version file. - Formatting cleanups (trailing whitespace/newlines). ## Behavior - Daily (00:30 UTC) or manual check; when a newer 7zz is found, update the lock file, verify download (artifacts gitignored), push to `chore/update-7zz`, and create/update one PR. - No automatic tag or release; the owner merges and triggers release when ready. - Changelog category: `chore` (dependency maintenance); includes CI workflow addition for PR-only updates. ## Testing - pre-commit hook: `ruff format` (check) + `ruff check` passed during commit. - No additional tests were run in this branch (existing suite remains applicable).
2 parents 881abca + 07f6496 commit a2296cd

File tree

10 files changed

+254
-100
lines changed

10 files changed

+254
-100
lines changed
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
# SPDX-License-Identifier: MIT
2+
# SPDX-FileCopyrightText: 2025 py7zz contributors
3+
4+
name: Check Upstream 7zz
5+
6+
on:
7+
schedule:
8+
- cron: '30 0 * * *' # Run daily at 00:30 UTC (avoiding midnight congestion)
9+
workflow_dispatch: # Allow manual trigger
10+
11+
permissions:
12+
contents: write
13+
pull-requests: write
14+
15+
jobs:
16+
check-and-update:
17+
runs-on: ubuntu-latest
18+
steps:
19+
- uses: actions/checkout@v4
20+
with:
21+
fetch-depth: 0 # Fetch all history for git describe
22+
23+
- name: Check for updates
24+
id: check
25+
run: |
26+
chmod +x scripts/get_7zz.sh
27+
28+
# Get latest version from online (with error handling)
29+
echo "Detecting latest 7zz version from upstream..."
30+
if ! LATEST_ONLINE=$(./scripts/get_7zz.sh --detect-latest 2>&1); then
31+
echo "::error::Failed to detect latest 7zz version from upstream"
32+
echo "Output: $LATEST_ONLINE"
33+
exit 1
34+
fi
35+
36+
# Validate version format (should be like "25.01")
37+
if ! [[ "$LATEST_ONLINE" =~ ^[0-9]+\.[0-9]+$ ]]; then
38+
echo "::error::Invalid version format detected: '$LATEST_ONLINE'"
39+
exit 1
40+
fi
41+
42+
# Get current bundled version (with error handling)
43+
echo "Reading current bundled version..."
44+
if ! CURRENT_BUNDLED=$(./scripts/get_7zz.sh --get-current 2>&1); then
45+
echo "::error::Failed to read current bundled version"
46+
echo "Output: $CURRENT_BUNDLED"
47+
exit 1
48+
fi
49+
50+
echo "Latest online 7zz: $LATEST_ONLINE"
51+
echo "Current bundled 7zz: $CURRENT_BUNDLED"
52+
53+
# Compare versions
54+
if dpkg --compare-versions "$LATEST_ONLINE" gt "$CURRENT_BUNDLED"; then
55+
echo "✨ Update found: $CURRENT_BUNDLED -> $LATEST_ONLINE"
56+
echo "update_needed=true" >> $GITHUB_OUTPUT
57+
echo "new_version=$LATEST_ONLINE" >> $GITHUB_OUTPUT
58+
else
59+
echo "✅ Up to date"
60+
echo "update_needed=false" >> $GITHUB_OUTPUT
61+
fi
62+
63+
- name: Prepare 7zz version bump
64+
if: steps.check.outputs.update_needed == 'true'
65+
run: |
66+
set -euo pipefail
67+
68+
NEW_VERSION="${{ steps.check.outputs.new_version }}"
69+
CURRENT_VERSION=$(cat py7zz/7zz_version.txt | tr -d '[:space:]')
70+
71+
echo "$NEW_VERSION" > py7zz/7zz_version.txt
72+
73+
# Verify the new version can be downloaded (no artifacts committed; bin is gitignored)
74+
if ! ./scripts/get_7zz.sh --version "$NEW_VERSION"; then
75+
echo "::error::Failed to verify 7zz $NEW_VERSION download"
76+
exit 1
77+
fi
78+
79+
echo "CURRENT_VERSION=$CURRENT_VERSION" >> $GITHUB_ENV
80+
81+
- name: Create PR for 7zz Update
82+
if: steps.check.outputs.update_needed == 'true'
83+
uses: peter-evans/create-pull-request@v6
84+
with:
85+
token: ${{ secrets.GITHUB_TOKEN }}
86+
branch: chore/update-7zz
87+
delete-branch: true
88+
base: main
89+
title: "chore: bump bundled 7zz to ${{ steps.check.outputs.new_version }}"
90+
commit-message: "chore: bump bundled 7zz to ${{ steps.check.outputs.new_version }}"
91+
labels: dependencies, automated, chore
92+
add-paths: py7zz/7zz_version.txt
93+
body: |
94+
## Summary
95+
Detected a new 7-Zip release: **${{ steps.check.outputs.new_version }}**.
96+
97+
This PR updates the bundled 7zz version. Release and tagging remain manual so branch protection stays intact.
98+
99+
## Changes
100+
- Update `py7zz/7zz_version.txt`: ${{ env.CURRENT_VERSION }} → ${{ steps.check.outputs.new_version }}
101+
102+
## Changelog Category
103+
- chore (dependency maintenance)
104+
105+
## Next Steps
106+
- Review and merge this PR when ready
107+
- Owner can run release workflow after merging to publish a new py7zz version
108+
109+
Generated by [Check Upstream 7zz workflow](https://github.com/${{ github.repository }}/actions/workflows/check-upstream.yml)

.github/workflows/ci.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -91,11 +91,11 @@ jobs:
9191
- name: Download 7zz binary for testing
9292
shell: bash
9393
run: |
94-
# Auto-detect latest 7-Zip version
95-
echo "Detecting latest 7-Zip version..."
94+
# Use locked version from file
95+
echo "Reading configured 7-Zip version..."
9696
chmod +x scripts/get_7zz.sh
97-
VERSION=$(./scripts/get_7zz.sh --detect-version)
98-
echo "Detected version: $VERSION"
97+
VERSION=$(./scripts/get_7zz.sh --get-current)
98+
echo "Configured version: $VERSION"
9999
VERSION_FOR_ASSET=$(echo "$VERSION" | sed 's/\.//g') # e.g., 25.01 -> 2501
100100
101101
# Map platform to 7zz release naming (same logic as release.yml)

.github/workflows/release.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -114,11 +114,11 @@ jobs:
114114
echo "Release type: Pre-release"
115115
fi
116116
117-
# Auto-detect latest 7zz version
118-
echo "Detecting latest 7-Zip version..."
117+
# Get 7zz version from locked file
118+
echo "Reading configured 7-Zip version..."
119119
chmod +x scripts/get_7zz.sh
120-
SEVEN_ZZ_VERSION=$(./scripts/get_7zz.sh --detect-version)
121-
echo "Detected 7zz version: $SEVEN_ZZ_VERSION"
120+
SEVEN_ZZ_VERSION=$(./scripts/get_7zz.sh --get-current)
121+
echo "Configured 7zz version: $SEVEN_ZZ_VERSION"
122122
123123
# Set outputs
124124
echo "git_tag=$TAG" >> $GITHUB_OUTPUT

.roo/rules/rules.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../../CLAUDE.md

AGENTS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
CLAUDE.md

REUSE.toml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,9 @@ path = "uv.lock"
66
SPDX-FileCopyrightText = "NONE"
77
SPDX-FileComment = "Autogenerated by uv; do not edit."
88
SPDX-License-Identifier = "CC0-1.0"
9+
10+
# Version lock file for bundled 7zz binary
11+
[[annotations]]
12+
path = "py7zz/7zz_version.txt"
13+
SPDX-FileCopyrightText = "2025 py7zz contributors"
14+
SPDX-License-Identifier = "MIT"

py7zz/7zz_version.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
25.01

py7zz/cli.py

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
py7zz's value is in automatic binary management and providing Python API.
88
"""
99

10-
import os
1110
import subprocess
1211
import sys
1312

@@ -32,11 +31,28 @@ def main() -> None:
3231
command = sys.argv[1]
3332

3433
if command in ["--version", "-V"]:
35-
# Handle quick version command: print only version string
34+
# Handle quick version command: print version strings
3635
try:
3736
from .version import get_version as _get_version
3837

39-
print(_get_version())
38+
# Get package version
39+
pkg_ver = _get_version()
40+
41+
# Get bundled 7zz version from file
42+
bundled_ver = "unknown"
43+
try:
44+
import os
45+
46+
current_dir = os.path.dirname(os.path.abspath(__file__))
47+
ver_file = os.path.join(current_dir, "7zz_version.txt")
48+
if os.path.exists(ver_file):
49+
with open(ver_file) as f:
50+
bundled_ver = f.read().strip()
51+
except Exception:
52+
pass
53+
54+
print(f"py7zz {pkg_ver}")
55+
print(f"7zz {bundled_ver} (bundled)")
4056
except Exception as _e:
4157
print(f"py7zz error: {_e}", file=sys.stderr)
4258
sys.exit(1)

pyproject.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ packages = ["py7zz"]
1414
# However, since they're in .gitignore, we use artifacts to include them when they exist
1515
# Note: Each platform wheel will only contain the relevant binary files for that platform
1616
artifacts = [
17-
"py7zz/bin/*"
17+
"py7zz/bin/*",
18+
"py7zz/7zz_version.txt",
1819
]
1920

2021
# Include license and legal files

0 commit comments

Comments
 (0)