Skip to content

Commit

Permalink
Implement automatic package updates (#4)
Browse files Browse the repository at this point in the history
  • Loading branch information
scaramallion authored Jun 29, 2024
1 parent 8999266 commit afc86de
Show file tree
Hide file tree
Showing 4 changed files with 131 additions and 23 deletions.
55 changes: 55 additions & 0 deletions .github/workflows/update-package.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
name: Automated package update

on:
workflow_dispatch:

jobs:
update-package:
runs-on: ubuntu-latest
env:
GH_TOKEN: ${{ secrets.AUTO_UPDATE_PACKAGE }}
steps:
- name: Set branch name
id: branch
run: echo "BRANCH=autobot-update-$(date +'%Y%m%d-%H%M%S')" >> $GITHUB_OUTPUT
- name: Checkout package
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: "3.10"
- name: Get latest pydicom hash
id: hash
run: |
CWD=$(pwd)
git clone https://github.com/pydicom/pydicom ../pydicom
cd ../pydicom
echo "PYDICOM_HASH=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT
cd $CWD
- name: Install dependencies
run: |
pip install -U pip
pip install mypy
pip install -e ../pydicom
- name: Update package
run: |
python scripts/update_package.py
git add src/pydicom-stubs
git status
- name: Create pull request
id: create_pr
# Only creates a new PR if there are changes
uses: peter-evans/create-pull-request@v6
with:
token: ${{ secrets.AUTO_UPDATE_PACKAGE }}
title: "[update-bot] Update README.md"
branch: ${{ steps.branch.outputs.BRANCH }}
commit-message: "Automated package update"
body: |
Automated package update using https://github.com/pydicom/pydicom/commit/${{ steps.hash.outputs.PYDICOM_HASH }}
- name: Automerge pull request
if: ${{ steps.create_pr.outputs.pull-request-operation }} == 'created'
env:
BRANCH: ${{ steps.branch.outputs.BRANCH }}
run: |
gh pr merge --auto --delete-branch --squash "$BRANCH"
8 changes: 6 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,11 @@ version = "3.0.0.0.dev0"
pydicom_stubs = ["*.pyi"]

[project.optional-dependencies]
dev = ["mypy", "pydicom", "build"]
dev = [
"mypy",
"pydicom @ git+https://github.com/pydicom/pydicom.git@main",
"build",
]

[project.urls]
homepage = "https://github.com/pydicom/types-pydicom"
Expand All @@ -42,4 +46,4 @@ warn_unreachable = false
ignore_missing_imports = true
disallow_untyped_calls = true
disallow_untyped_defs = true
disallow_incomplete_defs = true
disallow_incomplete_defs = true
2 changes: 1 addition & 1 deletion scripts/generate_stubs.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

BASE_DIRECTORY = Path(__file__).parent.parent
DS_DST = BASE_DIRECTORY / "custom" / "dataset.pyi"
DS_SRC = BASE_DIRECTORY / "pydicom-stubs" / "dataset.pyi"
DS_SRC = BASE_DIRECTORY / "src" / "pydicom-stubs" / "dataset.pyi"


ElementDictType = dict[int, tuple[str, str, str, str]]
Expand Down
89 changes: 69 additions & 20 deletions scripts/update_package.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@
import subprocess
import sys

from pydicom import __version__


BASE_DIRECTORY = Path(__file__).parent.parent
SRC_DIRECTORY = BASE_DIRECTORY / "custom"
DST_DIRECTORY = BASE_DIRECTORY / "pydicom-stubs"
DST_DIRECTORY = BASE_DIRECTORY / "src" / "pydicom-stubs"
PYDICOM_DIRECTORY = BASE_DIRECTORY.parent / "pydicom" / "src" / "pydicom"


Expand All @@ -31,45 +33,92 @@
]


if __name__ == "__main__":
def update_stubs() -> None:
# Clear out the stub files
if DST_DIRECTORY.exists():
shutil.rmtree(DST_DIRECTORY)

# Generate basic stub files using mypy's `stubgen`
if (BASE_DIRECTORY / "pydicom").exists():
shutil.rmtree(BASE_DIRECTORY / "pydicom")

print("Generating basic stub files with stubgen")
subprocess.run(["which", "stubgen"], shell=True)
returncode = subprocess.run(
[
f". {os.fspath(BASE_DIRECTORY / 'env' / 'env310' / 'bin' / 'activate')};"
f"stubgen {os.fspath(PYDICOM_DIRECTORY)} -o .",
],
p = subprocess.run(
[f"stubgen {os.fspath(PYDICOM_DIRECTORY)} -o ."],
shell=True,
)

if not list(DST_DIRECTORY.glob("*.pyi")):
if p.returncode != 0:
print(" Failed to generate the basic stub files")
sys.exit(1)

# Generate the custom stub files
print(f"Moving basic stub files to {DST_DIRECTORY}")
shutil.move(BASE_DIRECTORY / "pydicom", DST_DIRECTORY)

print("Generating custom stub files")
if not SRC_DIRECTORY.exists():
SRC_DIRECTORY.mkdir(parents=True, exist_ok=True)

subprocess.run(
[
f". {os.fspath(BASE_DIRECTORY / 'env' / 'env310' / 'bin' / 'activate')};"
"python scripts/generate_stubs.py",
],
shell=True,
)
subprocess.run(["python scripts/generate_stubs.py"], shell=True)

# Replace basic stub files with custom ones
print("Replacing basic stub files with custom ones")
for path in SRC_DIRECTORY.glob("*.pyi"):
shutil.copyfile(path, DST_DIRECTORY / path.name)

# Remove unnecessary stubs
print("Removing unnecessary stubs")
for path in REMOVALS:
path.unlink(missing_ok=True)


def update_version() -> None:
# Get the current package version
typd_version = ""
contents = []
with open(BASE_DIRECTORY / "pyproject.toml", "r") as f:
for line in f.readlines():
contents.append(line.rstrip())
if line.startswith("version = "):
typd_version = line.rstrip()

# types-pydicom version: X.Y.Z.N[.dev0]
typd_version = typd_version.strip("version = ")
typd_version = typd_version.strip("\"")
print(f"Found current package version '{typd_version}'")
typd_version = typd_version.split(".")
if not typd_version or len(typd_version) < 3:
raise RuntimeError(
f"Unable to determine the current package version from '{typd_version}'"
)

# pydicom version: X.Y.Z[.dev0]
pyd_version = __version__.strip().split(".")
if len(pyd_version) not in (3, 4):
raise RuntimeError(f"Unexpected pydicom version string '{pyd_version}'")

# Determine new package version
if pyd_version[-1] == "dev0":
# If pydicom is dev0 then use X.Y.Z.0.dev0:
version = f"{'.'.join(pyd_version[:-1])}.0.dev0"
elif pyd_version == typd_version[:3]:
# If X.Y.Z match -> increment N
version = f"{'.'.join(pyd_version)}.{int(typd_version[3]) + 1}"
else:
# If X.Y.Z don't match, use X.Y.Z.0
version = f"{'.'.join(pyd_version)}.0"

if version.split(".") == typd_version:
print(f"No package version change required")
return

print(f"Changing package version to '{version}'")
for idx, line in enumerate(contents):
if line.startswith("version = "):
contents[idx] = f"version = \"{version}\""
break

with open(BASE_DIRECTORY / "pyproject.toml", "w") as f:
f.write("\n".join(contents))


if __name__ == "__main__":
update_stubs()
update_version()

0 comments on commit afc86de

Please sign in to comment.