Autoupdate uv lock file #2
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
name: Autoupdate uv lock file | |
on: | |
schedule: | |
# Every Sunday at 00:00. | |
- cron: "0 0 * * 0" | |
jobs: | |
uv_lock_autoupdate: | |
env: | |
lockfile_path: uv.lock | |
requirements_doc_path: requirements-doc.txt | |
update_message_path: /tmp/message.txt | |
update_branch: chore/uv-lock-autoupdate | |
runs-on: ubuntu-latest | |
steps: | |
- name: Generate a token | |
id: generate-token | |
uses: actions/create-github-app-token@v1 | |
with: | |
app-id: ${{ vars.WRITE_CONTENTS_PR_APP }} | |
private-key: ${{ secrets.WRITE_CONTENTS_PR_KEY }} | |
- uses: actions/checkout@v4 | |
with: | |
ref: main | |
- name: Create or checkout update branch | |
id: create_branch | |
env: | |
GH_TOKEN: ${{ steps.generate-token.outputs.token }} | |
run: | | |
export pr_number=$( gh pr view ${{ env.update_branch }} --json number --jq '.number' ) | |
export pr_state=$( gh pr view ${{ env.update_branch }} --json state --jq '.state' ) | |
echo "pr_number=$pr_number" >> "$GITHUB_OUTPUT" | |
echo "pr_state=$pr_state" >> "$GITHUB_OUTPUT" | |
if git fetch origin ${{ env.update_branch }}; then | |
# If branch wasn't deleted after merge, do so here | |
if [ "$pr_state" = "MERGED" ]; then | |
git push -d origin ${{ env.update_branch }} | |
git checkout -b ${{ env.update_branch }} | |
git push origin ${{ env.update_branch }} | |
fi | |
git checkout ${{ env.update_branch }} | |
else | |
git checkout -b ${{ env.update_branch }} | |
git push origin ${{ env.update_branch }} | |
fi | |
# uv setup and lockfile upgrading steps | |
- name: Set up Python 3.12 | |
uses: actions/setup-python@v5 | |
with: | |
python-version: 3.12 | |
cache: pip | |
- name: Upgrade Pip | |
run: python -m pip install --upgrade pip | |
- name: Install uv | |
run: pip install uv | |
- name: Store hash of baseline files for comparison | |
id: old_hash | |
run: | | |
echo "lockfile=$( sha256sum $lockfile_path )" >> $GITHUB_OUTPUT | |
echo "requirements_doc=$( sha256sum $requirements_doc_path )" >> $GITHUB_OUTPUT | |
- name: Overwrite config on branch with version from main | |
run: | | |
git checkout main ${{ env.lockfile_path }} | |
git checkout main ${{ env.requirements_doc_path }} | |
- name: Store hash of main files for comparison | |
id: main_hash | |
run: | | |
echo "lockfile=$( sha256sum $lockfile_path )" >> $GITHUB_OUTPUT | |
echo "requirements_doc=$( sha256sum $requirements_doc_path )" >> $GITHUB_OUTPUT | |
- name: Run `uv lock --upgrade` on main lockfile | |
id: autoupdate | |
run: | | |
uv lock --upgrade > ${{ env.update_message_path }} | |
cat ${{ env.update_message_path }} | |
sed -i "/updated/!d" ${{ env.update_message_path }} | |
- name: Update requirements-docs.txt | |
run: > | |
uv export | |
--frozen | |
--format requirements-txt | |
--no-hashes | |
--no-dev | |
--no-emit-project | |
--extra doc | |
--output-file requirements-doc.txt | |
- name: Store hash of new files for comparison | |
id: new_hash | |
run: | | |
echo "lockfile=$( sha256sum $lockfile_path )" >> $GITHUB_OUTPUT | |
echo "requirements_doc=$( sha256sum $requirements_doc_path )" >> $GITHUB_OUTPUT | |
# Commit authoring and pull-request creation/updating | |
- name: Commit (with signature) lockfile | |
id: commit_lockfile | |
if: steps.old_hash.outputs.lockfile != steps.new_hash.outputs.lockfile | |
env: | |
GH_TOKEN: ${{ steps.generate-token.outputs.token }} | |
run: | | |
export message="chore(deps): autoupdate uv.lock" | |
export sha=$( git rev-parse ${{ env.update_branch }}:${{ env.lockfile_path }} ) | |
base64 -i ${{ env.lockfile_path }} > $RUNNER_TEMP/base64_lockfile | |
gh api --method PUT /repos/:owner/:repo/contents/${{ env.lockfile_path }} \ | |
--field message="$message" \ | |
--field content="@$RUNNER_TEMP/base64_lockfile" \ | |
--field branch=${{ env.update_branch }} \ | |
--field sha="$sha" | |
- name: Commit (with signature) new requirements-doc | |
id: commit_requirements_doc | |
if: steps.old_hash.outputs.requirements_doc != steps.new_hash.outputs.requirements_doc | |
env: | |
GH_TOKEN: ${{ steps.generate-token.outputs.token }} | |
run: | | |
export message="chore(deps): autoupdate requirements-doc" | |
export sha=$( git rev-parse ${{ env.update_branch }}:${{ env.requirements_doc_path }} ) | |
base64 -i ${{ env.requirements_doc_path }} > $RUNNER_TEMP/base64_requirements_doc | |
gh api --method PUT /repos/:owner/:repo/contents/${{ env.requirements_doc_path }} \ | |
--field message="$message" \ | |
--field content="@$RUNNER_TEMP/base64_requirements_doc" \ | |
--field branch=${{ env.update_branch }} \ | |
--field sha="$sha" | |
- name: Create or update lockfile-autoupdate pull-request | |
# note that we don't check whether requirements-doc was updated, as | |
# requirements-doc should only change if the lockfile also changes | |
if: steps.commit_lockfile.conclusion == 'success' || ( steps.main_lockfile.outputs.hash != steps.new_lockfile.outputs.hash ) | |
env: | |
GH_TOKEN: ${{ steps.generate-token.outputs.token }} | |
run: | | |
export title="chore(deps): autoupdate uv.lock" | |
export body=$( cat ${{ env.update_message_path }} ) | |
export pr_number=${{ steps.create_branch.outputs.pr_number }} | |
export pr_state=${{ steps.create_branch.outputs.pr_state }} | |
# If the PR is closed, can it be reopened, or is the PR already open? | |
if ( [ "$pr_state" = "CLOSED" ] && gh pr reopen $pr_number ) || [ "$pr_state" = "OPEN" ]; then | |
gh api --method PATCH /repos/:owner/:repo/pulls/$pr_number \ | |
--field title="$title" \ | |
--field body="$body" | |
else | |
# If a PR doesn't already exist, and no previous PR can be reopened, create a new PR. | |
gh pr create -t "$title" -b "$body" -l dependencies -B main -H ${{ env.update_branch }} | |
fi |