ui-ux-pro-max-skill/.github/workflows/refresh-catalogs.yml
Viet Tran a38d04c3d5
feat(search): overhaul relevance and curated design data
Overhaul BM25 relevance, reasoning and data-quality contracts; refresh UI styles and framework guidance; add resilient text, chip, badge and micro-interaction guidance; strengthen release, provenance and catalog refresh gates; update bilingual documentation.
2026-08-14 00:08:23 +07:00

219 lines
9.3 KiB
YAML

name: Refresh upstream catalogs
on:
schedule:
- cron: '17 3 * * 1'
workflow_dispatch:
permissions:
contents: read
concurrency:
group: refresh-upstream-catalogs
cancel-in-progress: false
jobs:
refresh:
name: Build review-only catalog candidates
runs-on: ubuntu-latest
timeout-minutes: 20
env:
CORE_VERSION: '2.1.1'
REACT_VERSION: '2.1.10'
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: '3.x'
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '22'
- name: Prepare isolated candidate workspace
run: |
mkdir -p "${RUNNER_TEMP}/catalog-work/npm" \
"${RUNNER_TEMP}/catalog-review/candidates" \
"${RUNNER_TEMP}/catalog-review/raw" \
"${RUNNER_TEMP}/catalog-review/reports"
echo "Catalog refresh has not reached candidate generation." \
>"${RUNNER_TEMP}/catalog-review/reports/refresh-status.txt"
- name: Fetch Google Fonts Developer API snapshot
env:
GOOGLE_FONTS_API_KEY: ${{ secrets.GOOGLE_FONTS_API_KEY }}
run: |
set +e
python3 - <<'PY' \
>"${RUNNER_TEMP}/catalog-review/reports/google-fonts-fetch.log" 2>&1
import json
import os
import sys
import urllib.parse
import urllib.request
from pathlib import Path
key = os.environ.get("GOOGLE_FONTS_API_KEY")
if not key:
print("GOOGLE_FONTS_API_KEY is not configured", file=sys.stderr)
raise SystemExit(2)
url = "https://www.googleapis.com/webfonts/v1/webfonts?" + urllib.parse.urlencode(
{"key": key, "capability": "VF"}
)
try:
with urllib.request.urlopen(url, timeout=30) as response:
raw = response.read(25_000_001)
except Exception:
print("Google Fonts API request failed; credentials were not logged", file=sys.stderr)
raise SystemExit(2)
if len(raw) > 25_000_000:
print("Google Fonts response exceeds 25000000 bytes", file=sys.stderr)
raise SystemExit(2)
payload = json.loads(raw)
target = Path(os.environ["RUNNER_TEMP"]) / "catalog-review/raw/google-fonts-api.json"
target.write_text(json.dumps(payload, ensure_ascii=False, indent=2) + "\n", encoding="utf-8")
PY
fetch_status=$?
printf 'google_fonts_fetch=%s\n' "${fetch_status}" \
>"${RUNNER_TEMP}/catalog-review/reports/fetch-status.txt"
exit 0
- name: Fetch official Google Fonts license metadata
run: |
set +e
metadata_root="${RUNNER_TEMP}/catalog-work/google-fonts"
git clone --depth 1 --filter=blob:none --no-checkout \
https://github.com/google/fonts.git "${metadata_root}" \
>"${RUNNER_TEMP}/catalog-review/reports/google-fonts-repository.log" 2>&1
clone_status=$?
metadata_status=${clone_status}
if [ "${clone_status}" -eq 0 ]; then
git -C "${metadata_root}" sparse-checkout init --no-cone
git -C "${metadata_root}" ls-tree -r --name-only HEAD \
| grep 'METADATA.pb$' \
>"${RUNNER_TEMP}/catalog-work/google-font-metadata-paths.txt"
git -C "${metadata_root}" sparse-checkout set --stdin \
<"${RUNNER_TEMP}/catalog-work/google-font-metadata-paths.txt"
git -C "${metadata_root}" checkout \
>>"${RUNNER_TEMP}/catalog-review/reports/google-fonts-repository.log" 2>&1
metadata_status=$?
if [ "${metadata_status}" -eq 0 ]; then
git -C "${metadata_root}" rev-parse HEAD \
>"${RUNNER_TEMP}/catalog-review/raw/google-fonts-revision.txt"
metadata_status=$?
fi
fi
printf 'google_fonts_repository=%s\ngoogle_fonts_metadata=%s\n' \
"${clone_status}" "${metadata_status}" \
>>"${RUNNER_TEMP}/catalog-review/reports/fetch-status.txt"
exit 0
- name: Fetch pinned Phosphor packages and extract official inputs
working-directory: ${{ runner.temp }}/catalog-work/npm
run: |
set +e
npm init --yes >/dev/null
npm install --ignore-scripts --no-audit --no-fund \
"@phosphor-icons/core@${CORE_VERSION}" \
"@phosphor-icons/react@${REACT_VERSION}" \
react@19 \
>"${RUNNER_TEMP}/catalog-review/reports/phosphor-packages.log" 2>&1
package_status=$?
if [ "${package_status}" -eq 0 ]; then
node --input-type=module <<'JS' \
>>"${RUNNER_TEMP}/catalog-review/reports/phosphor-packages.log" 2>&1
import { writeFile } from "node:fs/promises";
import { icons } from "@phosphor-icons/core";
import * as client from "@phosphor-icons/react";
import * as ssr from "@phosphor-icons/react/ssr";
const root = `${process.env.RUNNER_TEMP}/catalog-review/raw`;
const names = (exports) => Object.keys(exports).sort();
await writeFile(`${root}/phosphor-core.json`, JSON.stringify(icons, null, 2) + "\n");
await writeFile(
`${root}/phosphor-react-exports.json`,
JSON.stringify({ client: names(client), ssr: names(ssr) }, null, 2) + "\n",
);
JS
extract_status=$?
if [ "${extract_status}" -eq 0 ]; then
cp node_modules/@phosphor-icons/core/package.json \
"${RUNNER_TEMP}/catalog-review/raw/phosphor-core-package.json"
cp node_modules/@phosphor-icons/react/package.json \
"${RUNNER_TEMP}/catalog-review/raw/phosphor-react-package.json"
extract_status=$?
fi
else
extract_status=${package_status}
fi
printf 'phosphor_packages=%s\nphosphor_extract=%s\n' \
"${package_status}" "${extract_status}" \
>>"${RUNNER_TEMP}/catalog-review/reports/fetch-status.txt"
exit 0
- name: Generate candidates and review diffs
id: generate
env:
REVIEW_ROOT: ${{ runner.temp }}/catalog-review
run: |
set +e
review_date="$(date -u +%F)"
python3 scripts/refresh-google-fonts.py \
--api-input "${REVIEW_ROOT}/raw/google-fonts-api.json" \
--metadata-root "${RUNNER_TEMP}/catalog-work/google-fonts" \
--existing-csv src/ui-ux-pro-max/data/google-fonts.csv \
--output-csv "${REVIEW_ROOT}/candidates/google-fonts.csv" \
--license-output "${REVIEW_ROOT}/candidates/google-font-licenses.json" \
--metadata-revision "$(cat "${REVIEW_ROOT}/raw/google-fonts-revision.txt")" \
--verified-at "${review_date}" \
--approve-changes \
>"${REVIEW_ROOT}/reports/google-fonts-change-report.json" \
2>"${REVIEW_ROOT}/reports/google-fonts-error.log"
font_status=$?
python3 scripts/refresh-icon-catalog.py \
--input "${REVIEW_ROOT}/raw/phosphor-core.json" \
--package-json "${REVIEW_ROOT}/raw/phosphor-core-package.json" \
--react-package-json "${REVIEW_ROOT}/raw/phosphor-react-package.json" \
--react-exports-input "${REVIEW_ROOT}/raw/phosphor-react-exports.json" \
--curated-csv src/ui-ux-pro-max/data/icons.csv \
--output "${REVIEW_ROOT}/candidates/phosphor-icons-upstream.json" \
--verified-at "${review_date}" \
>"${REVIEW_ROOT}/reports/phosphor-refresh.log" \
2>"${REVIEW_ROOT}/reports/phosphor-error.log"
icon_status=$?
diff -u src/ui-ux-pro-max/data/google-fonts.csv \
"${REVIEW_ROOT}/candidates/google-fonts.csv" \
>"${REVIEW_ROOT}/reports/google-fonts.diff" 2>&1 || true
diff -u src/ui-ux-pro-max/data/google-font-licenses.json \
"${REVIEW_ROOT}/candidates/google-font-licenses.json" \
>"${REVIEW_ROOT}/reports/google-font-licenses.diff" 2>&1 || true
diff -u src/ui-ux-pro-max/data/phosphor-icons-upstream.json \
"${REVIEW_ROOT}/candidates/phosphor-icons-upstream.json" \
>"${REVIEW_ROOT}/reports/phosphor-icons-upstream.diff" 2>&1 || true
printf 'google_fonts=%s\nphosphor=%s\n' "${font_status}" "${icon_status}" \
>"${REVIEW_ROOT}/reports/refresh-status.txt"
git status --porcelain >"${REVIEW_ROOT}/reports/checkout-status.txt"
echo "font_status=${font_status}" >>"${GITHUB_OUTPUT}"
echo "icon_status=${icon_status}" >>"${GITHUB_OUTPUT}"
exit 0
- name: Upload review candidates and diffs
if: always()
uses: actions/upload-artifact@v4
with:
name: catalog-refresh-review-${{ github.run_id }}
path: ${{ runner.temp }}/catalog-review/
if-no-files-found: error
retention-days: 14
- name: Report refresh validation failure
if: steps.generate.outputs.font_status != '0' || steps.generate.outputs.icon_status != '0'
run: |
echo "A catalog candidate failed validation; inspect the uploaded review artifact."
exit 1