Skip to content

Bump Tool Versions

Bump Tool Versions #9

Workflow file for this run

---
name: Bump Tool Versions
on:
schedule:
- cron: "17 3 * * 1" # weekly (Mon) UTC
workflow_dispatch:
permissions:
contents: write
pull-requests: write
defaults:
run:
shell: bash
jobs:
bump:
name: Bump versions.env
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Compute latest versions
id: latest
env:
GH_TOKEN: ${{ github.token }}
run: |
set -euo pipefail
python - <<'PY'
import json
import os
import time
import urllib.error
import urllib.request
token = os.environ["GH_TOKEN"]
timeout_seconds = 12
max_retries = 4
def latest_tag(repo: str) -> str:
url = f"https://api.github.com/repos/{repo}/releases/latest"
headers = {
"Authorization": f"Bearer {token}",
"X-GitHub-Api-Version": "2022-11-28",
"Accept": "application/vnd.github+json",
"User-Agent": "bump-versions-workflow",
}
for attempt in range(1, max_retries + 1):
req = urllib.request.Request(url, headers=headers)
try:
with urllib.request.urlopen(req, timeout=timeout_seconds) as resp:
data = json.load(resp)
tag = data.get("tag_name")
if not tag:
raise RuntimeError(f"Missing tag_name in GitHub response for {repo}")
return tag
except urllib.error.HTTPError as exc:
retryable = exc.code in (403, 429, 500, 502, 503, 504)
if retryable and attempt < max_retries:
time.sleep(2 ** (attempt - 1))
continue
raise RuntimeError(
f"Failed to fetch latest release for {repo}: HTTP {exc.code}"
) from exc
except (urllib.error.URLError, TimeoutError) as exc:
if attempt < max_retries:
time.sleep(2 ** (attempt - 1))
continue
raise RuntimeError(
f"Failed to fetch latest release for {repo}: {exc}"
) from exc
raise RuntimeError(f"Failed to fetch latest release for {repo} after retries")
def latest_npm_version(package_name: str) -> str:
url = f"https://registry.npmjs.org/{package_name}/latest"
for attempt in range(1, max_retries + 1):
try:
with urllib.request.urlopen(url, timeout=timeout_seconds) as resp:
data = json.load(resp)
version = data.get("version")
if not version:
raise RuntimeError(f"Missing version in npm response for {package_name}")
return version
except urllib.error.HTTPError as exc:
retryable = exc.code in (429, 500, 502, 503, 504)
if retryable and attempt < max_retries:
time.sleep(2 ** (attempt - 1))
continue
raise RuntimeError(
f"Failed to fetch latest npm version for {package_name}: HTTP {exc.code}"
) from exc
except (urllib.error.URLError, TimeoutError) as exc:
if attempt < max_retries:
time.sleep(2 ** (attempt - 1))
continue
raise RuntimeError(
f"Failed to fetch latest npm version for {package_name}: {exc}"
) from exc
raise RuntimeError(f"Failed to fetch latest npm version for {package_name} after retries")
versions = {
"zola": latest_tag("getzola/zola").lstrip("v"),
"tailwind": latest_tag("tailwindlabs/tailwindcss").lstrip("v"),
"daisyui": latest_tag("saadeghi/daisyui").lstrip("v"),
"katex": latest_tag("KaTeX/KaTeX").lstrip("v"),
"fa": latest_tag("FortAwesome/Font-Awesome").lstrip("v"),
"terser": latest_npm_version("terser"),
"esbuild": latest_npm_version("esbuild"),
"pnpm": latest_npm_version("pnpm"),
"eslint": latest_npm_version("eslint"),
"stylelint": latest_npm_version("stylelint"),
}
out_path = os.environ["GITHUB_OUTPUT"]
with open(out_path, "a", encoding="utf-8") as f:
for k, v in versions.items():
f.write(f"{k}={v}\n")
PY
- name: Update versions.env
run: |
set -euo pipefail
file="versions.env"
sed -i -E "s/^ZOLA_VERSION=.*/ZOLA_VERSION=${{ steps.latest.outputs.zola }}/" "$file"
sed -i -E "s/^TAILWIND_VERSION=.*/TAILWIND_VERSION=${{ steps.latest.outputs.tailwind }}/" "$file"
sed -i -E "s/^DAISYUI_VERSION=.*/DAISYUI_VERSION=${{ steps.latest.outputs.daisyui }}/" "$file"
sed -i -E "s/^FA_VERSION=.*/FA_VERSION=${{ steps.latest.outputs.fa }}/" "$file"
sed -i -E "s/^KATEX_VERSION=.*/KATEX_VERSION=${{ steps.latest.outputs.katex }}/" "$file"
sed -i -E "s/^TERSER_VERSION=.*/TERSER_VERSION=${{ steps.latest.outputs.terser }}/" "$file"
sed -i -E "s/^ESBUILD_VERSION=.*/ESBUILD_VERSION=${{ steps.latest.outputs.esbuild }}/" "$file"
sed -i -E "s/^PNPM_VERSION=.*/PNPM_VERSION=${{ steps.latest.outputs.pnpm }}/" "$file"
sed -i -E "s/^ESLINT_VERSION=.*/ESLINT_VERSION=${{ steps.latest.outputs.eslint }}/" "$file"
sed -i -E "s/^STYLELINT_VERSION=.*/STYLELINT_VERSION=${{ steps.latest.outputs.stylelint }}/" "$file"
echo "Updated versions.env:"
cat "$file"
- name: Import GPG Key
uses: crazy-max/ghaction-import-gpg@v7
with:
gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }}
passphrase: ${{ secrets.GPG_PASSPHRASE }}
git_user_signingkey: true
git_commit_gpgsign: true
- name: Create pull request
uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8
with:
commit-message: "chore: bump tool versions"
title: "chore: bump tool versions"
body: |
Automated weekly bump of tool versions in `versions.env`.
- Zola: ${{ steps.latest.outputs.zola }}
- Tailwind: ${{ steps.latest.outputs.tailwind }}
- DaisyUI: ${{ steps.latest.outputs.daisyui }}
- Font Awesome: ${{ steps.latest.outputs.fa }}
- KaTeX: ${{ steps.latest.outputs.katex }}
- Terser: ${{ steps.latest.outputs.terser }}
- esbuild: ${{ steps.latest.outputs.esbuild }}
- pnpm: ${{ steps.latest.outputs.pnpm }}
- ESLint: ${{ steps.latest.outputs.eslint }}
- Stylelint: ${{ steps.latest.outputs.stylelint }}
branch: chore/bump-tool-versions
delete-branch: true
labels: |
dependencies
automation