Skip to content
This repository has been archived by the owner on Sep 2, 2024. It is now read-only.

Commit

Permalink
(#819) Initial attempt at github workflow to pin versions
Browse files Browse the repository at this point in the history
  • Loading branch information
rtuck99 committed Jan 25, 2024
1 parent fd48e80 commit f56b6d3
Show file tree
Hide file tree
Showing 2 changed files with 164 additions and 0 deletions.
126 changes: 126 additions & 0 deletions .github/workflows/pin_versions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
#!/usr/bin/env python3
import argparse
import locale
import os
import re
import subprocess
from functools import partial
from sys import stderr, stdout

SETUP_CFG_PATTERN = re.compile("(.*?)(@(.*))?\n")
PIP = "pip"


def rename_original(suffix):
os.rename("setup.cfg", "setup.cfg" + suffix)


def normalize(package_name: str):
return re.sub(r"[-_.]+", "-", package_name).lower()


def fetch_pin_versions() -> dict[str, str]:
process = subprocess.run(
[PIP, "freeze"], capture_output=True, encoding=locale.getpreferredencoding()
)
if process.returncode == 0:
output = process.stdout
lines = output.split("\n")
pin_versions = {}
for line in lines:
kvpair = line.split("==")
if len(kvpair) != 2:
stderr.write(f"Unable to parse {line} - ignored\n")
else:
pin_versions[normalize(kvpair[0]).strip()] = kvpair[1].strip()
return pin_versions
else:
stderr.write(f"pip freeze failed with error code {process.returncode}\n")
stderr.write(process.stderr)
exit(1)


def process_setup_cfg(input_fname, output_fname, dependency_processor):
with open(input_fname) as input_file:
with open(output_fname, "w") as output_file:
while line := input_file.readline():
output_file.write(line)
if line.startswith("install_requires"):
break

while (line := input_file.readline()) and not line.isspace():
dependency_processor(line, output_file)

output_file.write(line)

while line := input_file.readline():
output_file.write(line)


def strip_comment(line: str):
split = line.split("#", 1)
return split[0], (split[1] if len(split) > 1 else None)


def write_with_comment(comment, text, output_file):
output_file.write(text)
if comment:
output_file.write("#" + comment)
output_file.write("\n")


def update_setup_cfg_line(version_map: dict[str, str], line, output_file):
stripped_line, comment = strip_comment(line)
if match := SETUP_CFG_PATTERN.match(stripped_line):
normalized_name = normalize(match[1].strip())
if normalized_name not in version_map:
stderr.write(
f"Unable to find {normalized_name} in installed python packages\n"
)
exit(1)

write_with_comment(
comment,
f" {normalized_name} @ {version_map[normalized_name]}",
output_file,
)
else:
output_file.write(line)


def write_commit_message(pinned_versions: dict[str, str]):
message = f"Pin dependencies prior to release. Dodal {pinned_versions['dls-dodal']}, nexgen {pinned_versions['nexgen']}"
stdout.write(message)


def unpin_versions(line, output_file):
stripped_line, comment = strip_comment(line)
if match := SETUP_CFG_PATTERN.match(stripped_line):
if match[3] and match[3].strip().startswith("git+"):
write_with_comment(comment, match[1], output_file)
return

output_file.write(line)


if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Pin dependency versions in setup.cfg")
parser.add_argument(
"--unpin",
help="remove pinned hashes from setup.cfg prior to pip installing latest",
action="store_true",
)
args = parser.parse_args()

if args.unpin:
rename_original(".orig")
process_setup_cfg("setup.cfg.orig", "setup.cfg", unpin_versions)
else:
rename_original(".unpinned")
installed_versions = fetch_pin_versions()
process_setup_cfg(
"setup.cfg.unpinned",
"setup.cfg",
partial(update_setup_cfg_line, installed_versions),
)
write_commit_message(installed_versions)
38 changes: 38 additions & 0 deletions .github/workflows/pre_release_workflow.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: pre_release_workflow
on:
workflow_dispatch:
inputs:
tagName:
description: 'Tag to create'
required: true
type: string
default: 'vX.Y.Z'
jobs:
pin_dependency_versions:
runs-on: ubuntu-latest
steps:
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: "3.9"
architecture: x64
- name: checkout
uses: actions/checkout@v4
- name: Reset pinned hash versions
run: .github/workflows/pin_versions.py --unpin
- name: Install with latest dependencies
run: pip install -e .[dev]
- id: pin_versions
name: Pin Versions
run: |
MSG=$(.github/workflows/pin_versions.py)
echo "COMMIT_MESSAGE=\"$MSG\"" >> "$GITHUB_OUTPUT"
- name: Add setup.cfg
run: git add setup.cfg
- name: Commit changes
run: |
git config --global user.name "GitHub Workflow"
git config --global user.email "robert.tuck@diamond.ac.uk"
git commit -m ${{steps.pin_versions.outputs.COMMIT_MESSAGE}}
git tag ${{inputs.tagName}}
git push origin ${{inputs.tagName}}

0 comments on commit f56b6d3

Please sign in to comment.