Added script to archive EOL stable branches.

This also fixed a small bash issue in `confirm_release.sh` script.
This commit is contained in:
Natalia 2025-11-26 13:22:52 -03:00 committed by nessita
parent 18b13cf6c4
commit 532c1058a7
2 changed files with 152 additions and 1 deletions

View file

@ -0,0 +1,151 @@
#! /usr/bin/env python3
import argparse
import os
import subprocess
import sys
def run(cmd, *, cwd=None, env=None, dry_run=True):
"""Run a command with optional dry-run behavior."""
environ = os.environ.copy()
if env:
environ.update(env)
if dry_run:
print("[DRY RUN]", " ".join(cmd))
else:
print("[EXECUTE]", " ".join(cmd))
try:
result = subprocess.check_output(
cmd, cwd=cwd, env=environ, stderr=subprocess.STDOUT
)
except subprocess.CalledProcessError as e:
result = e.output
print(" [ERROR]", result)
raise
else:
print(" [RESULT]", result)
return result.decode().strip()
def validate_env(checkout_dir):
if not checkout_dir:
sys.exit("Error: checkout directory not provided (--checkout-dir).")
if not os.path.exists(checkout_dir):
sys.exit(f"Error: checkout directory '{checkout_dir}' does not exist.")
if not os.path.isdir(checkout_dir):
sys.exit(f"Error: '{checkout_dir}' is not a directory.")
def get_remote_branches(checkout_dir, include_fn):
"""Return list of remote branches filtered by include_fn."""
result = run(
["git", "branch", "--list", "-r"],
cwd=checkout_dir,
dry_run=False,
)
branches = [b.strip() for b in result.split("\n") if b.strip()]
return [b for b in branches if include_fn(b)]
def get_branch_info(checkout_dir, branch):
"""Return (commit_hash, last_update_date) for a given branch."""
commit_hash = run(["git", "rev-parse", branch], cwd=checkout_dir, dry_run=False)
last_update = run(
["git", "show", branch, "--format=format:%ai", "-s"],
cwd=checkout_dir,
dry_run=False,
)
return commit_hash, last_update
def create_tag(checkout_dir, branch, commit_hash, last_update, *, dry_run=True):
"""Create a tag locally for a given branch at its last update."""
tag_name = branch.replace("origin/", "", 1)
msg = f'"Tagged {tag_name} for EOL stable branch removal."'
run(
["git", "tag", "--sign", "--message", msg, tag_name, commit_hash],
cwd=checkout_dir,
env={"GIT_COMMITTER_DATE": last_update},
dry_run=dry_run,
)
return tag_name
def delete_remote_and_local_branch(checkout_dir, branch, *, dry_run=True):
"""Delete a remote branch from origin and the maching local branch."""
try:
run(
["git", "branch", "-D", branch],
cwd=checkout_dir,
dry_run=dry_run,
)
except subprocess.CalledProcessError:
print(f"[ERROR] Local branch {branch} can not be deleted.")
run(
["git", "push", "origin", "--delete", branch.replace("origin/", "", 1)],
cwd=checkout_dir,
dry_run=dry_run,
)
def main():
parser = argparse.ArgumentParser(
description="Archive Django branches into tags and optionally delete them."
)
parser.add_argument(
"--checkout-dir", required=True, help="Path to Django git checkout"
)
parser.add_argument(
"--dry-run",
action="store_true",
help="Print commands instead of executing them",
)
parser.add_argument(
"--branches", nargs="*", help="Specific remote branches to include (optional)"
)
args = parser.parse_args()
validate_env(args.checkout_dir)
dry_run = args.dry_run
checkout_dir = args.checkout_dir
if args.branches:
wanted = set(f"origin/{b}" for b in args.branches)
else:
wanted = set()
branches = get_remote_branches(checkout_dir, include_fn=lambda b: b in wanted)
if not branches:
print("No branches matched inclusion criteria.")
return
print("\nMatched branches:")
print("\n".join(branches))
print()
branch_updates = {b: get_branch_info(checkout_dir, b) for b in branches}
print("\nLast updates:")
for b, (h, d) in branch_updates.items():
print(f"{b}\t{h}\t{d}")
if (
input("\nDelete remote branches and create tags? [y/N]: ").strip().lower()
== "y"
):
for b, (commit_hash, last_update_date) in branch_updates.items():
print(f"Creating tag for {b} at {commit_hash=} with {last_update_date=}")
create_tag(checkout_dir, b, commit_hash, last_update_date, dry_run=dry_run)
print(f"Deleting remote branch {b}")
delete_remote_and_local_branch(checkout_dir, b, dry_run=dry_run)
run(
["git", "push", "--tags"],
cwd=checkout_dir,
dry_run=dry_run,
)
print("Done.")
if __name__ == "__main__":
main()

View file

@ -25,7 +25,7 @@ echo "Download checksum file ..."
curl --fail --output "$CHECKSUM_FILE" "${MEDIA_URL_PREFIX}/pgp/${CHECKSUM_FILE}"
echo "Verify checksum file ..."
if [ -n "${GPG_KEY}" ] ; then
if [ -n "${GPG_KEY:-}" ] ; then
gpg --recv-keys "${GPG_KEY}"
fi
gpg --verify "${CHECKSUM_FILE}"