-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
🧪 Add a GHA workflow for updating lockfiles
- Loading branch information
Showing
2 changed files
with
319 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,292 @@ | ||
--- | ||
|
||
name: 🔒 pip-tools | ||
|
||
on: | ||
workflow_dispatch: | ||
inputs: | ||
package-distribuition: | ||
# github.event_name == 'workflow_dispatch' | ||
# && github.event.inputs.package-distribuition | ||
description: >- | ||
A target Python package distribution to upgrade | ||
required: false | ||
pull_request: | ||
paths: | ||
- .github/workflows/pip-tools.yml | ||
schedule: | ||
- cron: 1 0 * * * # Run daily at 0:01 UTC | ||
|
||
env: | ||
GIT_BRANCH: >- | ||
maintenance/pip-tools-constraint-lockfiles${{ | ||
( | ||
github.event_name == 'workflow_dispatch' | ||
&& github.event.inputs.package-distribuition | ||
) | ||
&& format('-updating-{0}', github.event.inputs.package-distribuition) | ||
|| '' | ||
}} | ||
PIP_DISABLE_PIP_VERSION_CHECK: 1 | ||
PIP_NO_PYTHON_VERSION_WARNING: 1 | ||
PIP_NO_WARN_SCRIPT_LOCATION: 1 | ||
PY_COLORS: 1 | ||
|
||
concurrency: | ||
group: >- | ||
${{ | ||
github.workflow | ||
}}-${{ | ||
github.event.inputs.package-distribuition | ||
|| github.event.pull_request.number | ||
|| github.sha | ||
}} | ||
cancel-in-progress: true | ||
|
||
jobs: | ||
|
||
deps: | ||
name: >- | ||
⛓🔒 🐍${{ | ||
matrix.python-version | ||
}} @ ${{ | ||
matrix.os | ||
}} | ||
runs-on: ${{ matrix.os }} | ||
strategy: | ||
matrix: | ||
python-version: | ||
# NOTE: The latest and the lowest supported Pythons are prioritized | ||
# NOTE: to improve the responsiveness. It's nice to see the most | ||
# NOTE: important results first. | ||
- 3.12 | ||
- 3.8 | ||
- pypy-3.10 | ||
- 3.11 | ||
- >- | ||
3.10 | ||
- 3.9 | ||
os: | ||
- ubuntu-20.04 | ||
- macOS-13.0 | ||
- windows-2019 | ||
|
||
env: | ||
TOXENV: pip-compile-tox-env-lock | ||
|
||
steps: | ||
- name: Grab the source from Git | ||
uses: actions/checkout@v4 # Keep before `setup-python` for cache to work | ||
|
||
- name: Set up Python ${{ matrix.python-version }} | ||
uses: actions/setup-python@v5 | ||
with: | ||
cache: pip | ||
cache-dependency-path: requirements/** | ||
python-version: ${{ matrix.python-version }} | ||
|
||
- name: Install tox | ||
run: python -Im pip install tox | ||
|
||
- name: Pre-populate the tox env | ||
run: python -Im tox --skip-missing-interpreters false --notest | ||
|
||
- name: Setup git user as [bot] | ||
# Refs: | ||
# * https://gh.neting.ccmunity/t/github-actions-bot-email-address/17204/6 | ||
# * https://github.com/actions/checkout/issues/13#issuecomment-724415212 | ||
uses: fregante/setup-git-user@v2.0.1 | ||
|
||
- name: Generate constraints files | ||
run: >- | ||
python -Im tox r -- py pyproject.toml | ||
${{ | ||
( | ||
github.event_name == 'workflow_dispatch' | ||
&& github.event.inputs.package-distribuition | ||
) | ||
&& format( | ||
'--upgrade-package="{0}"', | ||
github.event.inputs.package-distribuition | ||
) | ||
|| '--upgrade' | ||
}} | ||
- name: Commit version bumps to Git | ||
id: constraints | ||
run: | | ||
LOCK_BASE_NAME=$(python bin/print_lockfile_base_name.py py) | ||
git add "requirements/${LOCK_BASE_NAME}.txt" | ||
git commit "requirements/${LOCK_BASE_NAME}.txt" \ | ||
-m "Update ${LOCK_BASE_NAME} constraints${{ | ||
( | ||
github.event_name == 'workflow_dispatch' | ||
&& github.event.inputs.package-distribuition | ||
) | ||
&& format(' for {0}', github.event.inputs.package-distribuition) | ||
|| '' | ||
}}" \ | ||
&& { | ||
echo "patch=${{ | ||
runner.temp | ||
}}/patches/0001-Update-${LOCK_BASE_NAME}-constraints.patch" \ | ||
>> "${GITHUB_OUTPUT}" | ||
} \ | ||
|| : | ||
shell: bash # windows compat | ||
|
||
- name: Log the patch | ||
if: steps.constraints.outputs.patch | ||
run: git show --color | ||
- name: Create a temporary patch directory | ||
if: steps.constraints.outputs.patch | ||
run: mkdir -pv '${{ runner.temp }}/patches' | ||
shell: bash # windows compat | ||
- name: Create a patch from the last Git commit | ||
if: steps.constraints.outputs.patch | ||
run: >- | ||
git format-patch | ||
--output='${{ steps.constraints.outputs.patch }}' | ||
-1 | ||
HEAD | ||
- name: Make a GHA artifact suffix | ||
if: steps.constraints.outputs.patch | ||
id: random | ||
run: echo uuid=$(uuidgen) >> "${GITHUB_OUTPUT}" | ||
shell: bash # windows compat | ||
- name: Save the package bump patch as a GHA artifact | ||
if: steps.constraints.outputs.patch | ||
uses: actions/upload-artifact@v4 | ||
with: | ||
name: pip-constraints-git-patches--${{ steps.random.outputs.uuid }} | ||
path: ${{ steps.constraints.outputs.patch }} | ||
|
||
check: # This job does nothing and is only used for the branch protection | ||
name: >- | ||
check | ||
⮸ | ||
${{ | ||
( | ||
github.event_name == 'workflow_dispatch' | ||
&& github.event.inputs.package-distribuition | ||
) | ||
&& format('`{0}`', github.event.inputs.package-distribuition) | ||
|| 'everything' | ||
}} | ||
if: always() | ||
|
||
needs: | ||
- deps | ||
|
||
runs-on: ubuntu-latest | ||
|
||
steps: | ||
- name: Decide whether the needed jobs succeeded or failed | ||
uses: re-actors/alls-green@release/v1 | ||
with: | ||
jobs: ${{ toJSON(needs) }} | ||
|
||
publish-pr: | ||
name: Open/refresh a PR | ||
if: github.event_name != 'pull_request' | ||
needs: | ||
- check | ||
runs-on: Ubuntu-latest | ||
|
||
environment: pip-tools | ||
|
||
permissions: | ||
contents: write # Needed to enable auto-merge | ||
pull-requests: write | ||
|
||
steps: | ||
- name: Download all the dists | ||
id: artifacts-download | ||
continue-on-error: true # and judge whether there's updates later | ||
uses: actions/download-artifact@v4 | ||
with: | ||
merge-multiple: true | ||
path: ${{ runner.temp }}/patches/ | ||
pattern: pip-constraints-git-patches--* | ||
- name: >- | ||
Determine whether any change suggestions to lockfiles | ||
have been produced | ||
if: steps.artifacts-download.outcome == 'success' | ||
id: artifacts | ||
run: >- | ||
echo "lockfile-updates-needed=true" >> "${GITHUB_OUTPUT}" | ||
- name: Grab the source from Git | ||
if: steps.artifacts.outputs.lockfile-updates-needed | ||
uses: actions/checkout@v4 | ||
- name: Setup git user as [bot] | ||
if: steps.artifacts.outputs.lockfile-updates-needed | ||
# Refs: | ||
# * https://gh.neting.ccmunity/t/github-actions-bot-email-address/17204/6 | ||
# * https://github.com/actions/checkout/issues/13#issuecomment-724415212 | ||
uses: fregante/setup-git-user@v2.0.1 | ||
|
||
- name: Figure out if the pre-existing remote branch exists | ||
if: steps.artifacts.outputs.lockfile-updates-needed | ||
id: pre-existing-remote-branch | ||
run: >- | ||
echo "info=$( | ||
git ls-remote origin "${GIT_BRANCH}" | ||
)" >> "${GITHUB_OUTPUT}" | ||
- name: Fetch the existing remote PR branch | ||
if: steps.pre-existing-remote-branch.outputs.info | ||
run: git fetch origin "${GIT_BRANCH}" | ||
- name: Switch to the PR branch | ||
if: steps.artifacts.outputs.lockfile-updates-needed | ||
run: git checkout -B "${GIT_BRANCH}" | ||
|
||
- name: List Git patches | ||
if: steps.artifacts.outputs.lockfile-updates-needed | ||
run: ls -alh '${{ runner.temp }}/patches/' | ||
- name: Apply patches to the Git repo | ||
if: steps.artifacts.outputs.lockfile-updates-needed | ||
run: git am '${{ runner.temp }}/patches'/*.patch | ||
- name: Force-push the PR branch to remote | ||
if: steps.artifacts.outputs.lockfile-updates-needed | ||
run: git push origin "HEAD:${GIT_BRANCH}" --force-with-lease | ||
|
||
- name: Create a PR | ||
if: >- | ||
!steps.pre-existing-remote-branch.outputs.info | ||
&& steps.artifacts.outputs.lockfile-updates-needed | ||
id: pr | ||
uses: vsoch/pull-request-action@1.1.1 | ||
env: | ||
BRANCH_PREFIX: '' | ||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
PULL_REQUEST_BODY: >- | ||
Automated pip-tools-managed pip constraint lockfiles update. | ||
PULL_REQUEST_BRANCH: ${{ github.event.repository.default_branch }} | ||
PULL_REQUEST_DRAFT: true | ||
PULL_REQUEST_FROM_BRANCH: ${{ env.GIT_BRANCH }} | ||
PULL_REQUEST_TITLE: >- | ||
⛓🔒 Bump transitive deps in pip-tools-managed lockfiles${{ | ||
( | ||
github.event_name == 'workflow_dispatch' | ||
&& github.event.inputs.package-distribuition | ||
) | ||
&& format(' for {0}', github.event.inputs.package-distribuition) | ||
|| '' | ||
}} | ||
- name: Log the pull request details | ||
run: >- | ||
echo | ||
"PR number: ${{ steps.pr.outputs.pull_request_number }}" | ||
"\nPR URL: ${{ steps.pr.outputs.pull_request_url }}" | ||
- name: Instruct the maintainers to trigger CI by undrafting the PR | ||
env: | ||
GITHUB_TOKEN: ${{ github.token }} | ||
run: >- | ||
gh pr comment | ||
--body 'Please mark the PR as ready for review to trigger PR checks.' | ||
--repo '${{ github.repository }}' | ||
'${{ steps.pr.outputs.pull_request_number }}' | ||
... |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
#! /usr/bin/env python | ||
"""A script that prints platform-specific constraints file name base.""" | ||
|
||
from __future__ import annotations | ||
|
||
import sys | ||
|
||
from pip_constraint_helpers import ( | ||
get_constraint_file_path, | ||
get_runtime_python_tag, | ||
) | ||
|
||
|
||
def compute_constraint_base_name(toxenv: str) -> str: | ||
"""Get the lock file name stem. | ||
:param toxenv: Name of the tox env. | ||
""" | ||
return get_constraint_file_path( | ||
req_dir='', | ||
toxenv=toxenv, | ||
python_tag=get_runtime_python_tag(), | ||
).stem | ||
|
||
|
||
if __name__ == '__main__': | ||
print(compute_constraint_base_name(sys.argv[1])) |