Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 70 additions & 0 deletions .github/scripts/update_action_pins.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
"""Re-pin actions-ext references to the current main commit of each action repo.

Dependabot cannot maintain these pins: the template workflows are .jinja files
outside any .github/workflows directory, so it never sees them, and the pins
point at main commits rather than tags, which is all Dependabot can resolve.
"""

import json
import os
import re
import subprocess
import sys
import urllib.request

USES = re.compile(r"(?<=uses: )actions-ext/([\w.-]+)(/[\w./-]+)?@([0-9a-f]{40})")
API = "https://api.github.com/repos/actions-ext/{}/commits/main"


def tracked_files():
out = subprocess.run(["git", "ls-files", "-z"], capture_output=True, check=True).stdout
return [f.decode() for f in out.split(b"\0") if f]


def main_sha(repo):
request = urllib.request.Request(API.format(repo), headers={"Accept": "application/vnd.github+json"})
token = os.environ.get("GITHUB_TOKEN")
if token:
request.add_header("Authorization", f"Bearer {token}")
with urllib.request.urlopen(request) as response:
return json.load(response)["sha"]


def main():
check_only = "--check" in sys.argv

contents = {}
repos = set()
for path in tracked_files():
try:
text = open(path, encoding="utf-8").read()
except (UnicodeDecodeError, OSError):
continue
found = USES.findall(text)
if found:
contents[path] = text
repos.update(repo for repo, _, _ in found)

latest = {repo: main_sha(repo) for repo in sorted(repos)}

stale = []
for path, text in contents.items():
updated = USES.sub(lambda m: f"actions-ext/{m[1]}{m[2] or ''}@{latest[m[1]]}", text)
if updated == text:
continue
stale += sorted({f"actions-ext/{repo}" for repo, _, sha in USES.findall(text) if sha != latest[repo]})
print(f"{'stale' if check_only else 'updated'}: {path}")
if not check_only:
open(path, "w", encoding="utf-8").write(updated)

if not stale:
print(f"all pins current ({', '.join(f'{r}@{s[:8]}' for r, s in latest.items())})")
return 0
if check_only:
print(f"\nout of date: {', '.join(sorted(set(stale)))}", file=sys.stderr)
return 1
return 0


if __name__ == "__main__":
sys.exit(main())
48 changes: 48 additions & 0 deletions .github/workflows/update-action-pins.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
name: Update Action Pins

on:
schedule:
- cron: "0 6 * * 1"
repository_dispatch:
types:
- actions-ext-updated
workflow_dispatch:

concurrency:
group: ${{ github.workflow }}
cancel-in-progress: true

permissions:
contents: write
pull-requests: write

jobs:
update:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

- name: Re-pin actions-ext references
run: python3 .github/scripts/update_action_pins.py
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Open pull request
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
if git diff --quiet; then
echo "nothing to update"
exit 0
fi
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git switch -c bot/update-action-pins
git commit -am "Update actions-ext pins"
git push -f origin bot/update-action-pins
gh pr view bot/update-action-pins >/dev/null 2>&1 || gh pr create \
--base main \
--head bot/update-action-pins \
--title "Update actions-ext pins" \
--body "Re-pins the actions-ext references in the templates and in this repo's own workflow to the current main commit of each action repo."
7 changes: 7 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,13 @@ fix: ## fix formatting in this repo
format: fix
test: ## run tests for this repo

.PHONY: update-action-pins check-action-pins
update-action-pins: ## re-pin actions-ext references to each action repo's current main
python3 .github/scripts/update_action_pins.py

check-action-pins: ## check whether any actions-ext pin is out of date
python3 .github/scripts/update_action_pins.py --check

.PHONY: gen-python gen-cpp gen-js gen-jupyter gen-rust gen-rustjswasm gen-cppjswasm gen-uitk-svelte gen-uitk-webawesome gen-site-react gen-site-sveltekit gen-site-webawesome
gen-python: ## regenerate the python template from scratch
mkdir -p ../python-template && cd ../python-template && rm -rf ./* && rm -rf .copier-answers.yaml .gitignore .github .gitattributes
Expand Down
Loading