diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 8b3972c..e11f893 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -1,53 +1,47 @@ name: Build font and specimen -on: [push, release] +on: push jobs: build: + name: Build and test runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - name: Set up Python 3.8 - uses: actions/setup-python@v2 + - uses: actions/checkout@v4 + - name: Set up Python 3.10 + uses: actions/setup-python@v5 with: - python-version: 3.8 + python-version: "3.10" - name: Install sys tools/deps run: | sudo apt-get update sudo apt-get install ttfautohint sudo snap install yq - - uses: actions/cache@v2 + - uses: actions/cache@v4 with: path: ./venv/ key: ${{ runner.os }}-venv-${{ hashFiles('**/requirements*.txt') }} restore-keys: | ${{ runner.os }}-venv- - - name: Do first-run script if necessary - run: make .init.stamp - if: github.repository != 'googlefonts/googlefonts-project-template' - - uses: stefanzweifel/git-auto-commit-action@v4 - name: First-run setup - if: github.repository != 'googlefonts/googlefonts-project-template' - with: - file_pattern: .init.stamp README.md requirements.txt OFL.txt - commit_message: "Personalize for this repo" - name: gen zip file name id: zip-name shell: bash # Set the archive name to repo name + "-assets" e.g "MavenPro-assets" run: echo "ZIP_NAME=$(echo '${{ github.repository }}' | awk -F '/' '{print $2}')-fonts" >> $GITHUB_ENV - # If a new release is cut, use the release tag to auto-bump the source files - - name: Bump release - if: github.event_name == 'release' - run: | - . venv/bin/activate - SRCS=$(yq e ".sources[]" sources/config.yaml) - TAG_NAME=${GITHUB_REF/refs\/tags\//} - echo "Bumping $SRCS to $TAG_NAME" - for src in $SRCS - do - bumpfontversion sources/$src --new-version $TAG_NAME; - done + + # If a new release is cut, use the release tag to auto-bump the source files + # - name: Bump release + # if: github.event_name == 'release' + # run: | + # . venv/bin/activate + # SRCS=$(yq e ".sources[]" sources/config.yaml) + # TAG_NAME=${GITHUB_REF/refs\/tags\//} + # echo "Bumping $SRCS to $TAG_NAME" + # for src in $SRCS + # do + # bumpfontversion sources/$src --new-version $TAG_NAME; + # done + - name: Build font run: make build - name: Check with fontbakery @@ -58,13 +52,13 @@ jobs: - name: setup site run: cp scripts/index.html out/index.html - name: Deploy - uses: peaceiris/actions-gh-pages@v3 + uses: peaceiris/actions-gh-pages@v4 if: ${{ github.ref == 'refs/heads/main' }} with: github_token: ${{ secrets.GITHUB_TOKEN }} publish_dir: ./out - name: Archive artifacts - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 with: name: ${{ env.ZIP_NAME }} path: | @@ -72,30 +66,51 @@ jobs: out outputs: zip_name: ${{ env.ZIP_NAME }} + + # There are two ways a release can be created: either by pushing a tag, or by + # creating a release from the GitHub UI. Pushing a tag does not automatically + # create a release, so we have to do that ourselves. However, creating a + # release from the GitHub UI *does* push a tag, and we don't want to create + # a new release in that case because one already exists! + release: - # only run if the commit is tagged... - if: github.event_name == 'release' - # ... and it builds successfully - needs: - - build + name: Create and populate release + needs: build runs-on: ubuntu-latest + if: contains(github.ref, 'refs/tags/') env: ZIP_NAME: ${{ needs.build.outputs.zip_name }} + GH_TOKEN: ${{ github.token }} steps: - - uses: actions/checkout@v2 - - name: Download artefact files - uses: actions/download-artifact@v2 + - uses: actions/checkout@v4 + - name: Download font artefact files + uses: actions/download-artifact@v4 with: name: ${{ env.ZIP_NAME }} path: ${{ env.ZIP_NAME }} - - name: Zip files - run: zip -r ${{ env.ZIP_NAME }}.zip ${{ env.ZIP_NAME }} - - name: Upload binaries to release - uses: svenstaro/upload-release-action@v2 - with: - repo_token: ${{ secrets.GITHUB_TOKEN }} - file: ${{ env.ZIP_NAME }}.zip - asset_name: ${{ env.ZIP_NAME }}.zip - tag: ${{ github.ref }} - overwrite: true - body: "Production ready fonts" + - name: Copy DESCRIPTION.en_us.html to artefact directory + run: cp documentation/DESCRIPTION.en_us.html ${{ env.ZIP_NAME }}/DESCRIPTION.en_us.html + - name: Copy ARTICLE.en_us.html to artefact directory + run: cp documentation/ARTICLE.en_us.html ${{ env.ZIP_NAME }}/ARTICLE.en_us.html + continue-on-error: true + - name: Copy OFL.txt to artefact directory + run: cp OFL.txt ${{ env.ZIP_NAME }}/OFL.txt + - name: Remove proof/fontbakery stuff from release + run: rm -rf ${{ env.ZIP_NAME }}/out + - name: gen release file name + shell: bash + run: echo "RELEASE_ZIP_NAME=$(echo '${{ github.repository }}' | awk -F '/' '{print $2}')-${{github.ref_name}}" >> $GITHUB_ENV + - name: Create release bundle + run: mv ${{ env.ZIP_NAME }} ${{ env.RELEASE_ZIP_NAME }}; zip -r ${{ env.RELEASE_ZIP_NAME }}.zip ${{ env.RELEASE_ZIP_NAME }} + - name: Check for release + id: create_release + run: | + if ! gh release view ${{ github.ref_name }}; then + git show -s --format=%B ${{ github.ref_name }} | tail -n +4 | gh release create ${{ github.ref_name }} -t ${{ github.ref_name }} -F - + fi + - name: Populate release + run: | + gh release upload ${{ github.ref_name }} ${{ env.RELEASE_ZIP_NAME }}.zip --clobber + - name: Set release live + run: | + gh release edit ${{ github.ref_name }} --draft=false \ No newline at end of file diff --git a/.templaterc.json b/.templaterc.json deleted file mode 100644 index 6174e0a..0000000 --- a/.templaterc.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "files": [".github/**/*", "Makefile", "scripts/**/*", "requirements.txt"] -} diff --git a/Makefile b/Makefile index 4796c02..91972fe 100644 --- a/Makefile +++ b/Makefile @@ -18,35 +18,53 @@ build: build.stamp venv: venv/touchfile -build.stamp: venv .init.stamp sources/config.yaml $(SOURCES) - . venv/bin/activate; rm -rf fonts/; gftools builder sources/config.yaml && touch build.stamp +venv-test: venv-test/touchfile -.init.stamp: venv - . venv/bin/activate; python3 scripts/first-run.py +customize: venv + . venv/bin/activate; python3 scripts/customize.py + +build.stamp: venv sources/config.yaml $(SOURCES) + rm -rf fonts + (for config in sources/config*.yaml; do . venv/bin/activate; gftools builder $$config; done) && touch build.stamp venv/touchfile: requirements.txt test -d venv || python3 -m venv venv . venv/bin/activate; pip install -Ur requirements.txt touch venv/touchfile -test: venv build.stamp - . venv/bin/activate; mkdir -p out/ out/fontbakery; fontbakery check-googlefonts -l WARN --succinct --badges out/badges --html out/fontbakery/fontbakery-report.html --ghmarkdown out/fontbakery/fontbakery-report.md $(shell find fonts/ttf -type f) +venv-test/touchfile: requirements-test.txt + test -d venv-test || python3 -m venv venv-test + . venv-test/bin/activate; pip install -Ur requirements-test.txt + touch venv-test/touchfile + +test: venv-test build.stamp + TOCHECK=$$(find fonts/variable -type f 2>/dev/null); if [ -z "$$TOCHECK" ]; then TOCHECK=$$(find fonts/ttf -type f 2>/dev/null); fi ; . venv-test/bin/activate; mkdir -p out/ out/fontbakery; fontbakery check-googlefonts -l WARN --full-lists --succinct --badges out/badges --html out/fontbakery/fontbakery-report.html --ghmarkdown out/fontbakery/fontbakery-report.md $$TOCHECK || echo '::warning file=sources/config.yaml,title=Fontbakery failures::The fontbakery QA check reported errors in your font. Please check the generated report.' proof: venv build.stamp - . venv/bin/activate; mkdir -p out/ out/proof; gftools gen-html proof $(shell find fonts/ttf -type f) -o out/proof + TOCHECK=$$(find fonts/variable -type f 2>/dev/null); if [ -z "$$TOCHECK" ]; then TOCHECK=$$(find fonts/ttf -type f 2>/dev/null); fi ; . venv/bin/activate; mkdir -p out/ out/proof; diffenator2 proof $$TOCHECK -o out/proof -images: venv build.stamp $(DRAWBOT_OUTPUT) - git add documentation/*.png && git commit -m "Rebuild images" documentation/*.png +images: venv $(DRAWBOT_OUTPUT) %.png: %.py build.stamp - python3 $< --output $@ + . venv/bin/activate; python3 $< --output $@ clean: rm -rf venv - find . -name "*.pyc" | xargs rm delete + find . -name "*.pyc" -delete + +update-project-template: + npx update-template https://github.com/googlefonts/googlefonts-project-template/ + +update: venv venv-test + venv/bin/pip install --upgrade pip-tools + # See https://pip-tools.readthedocs.io/en/latest/#a-note-on-resolvers for + # the `--resolver` flag below. + venv/bin/pip-compile --upgrade --verbose --resolver=backtracking requirements.in + venv/bin/pip-sync requirements.txt -update-ufr: - npx update-template https://github.com/googlefonts/Unified-Font-Repository/ + venv-test/bin/pip install --upgrade pip-tools + venv-test/bin/pip-compile --upgrade --verbose --resolver=backtracking requirements-test.in + venv-test/bin/pip-sync requirements-test.txt -update: - pip install --upgrade $(dependency); pip freeze > requirements.txt + git commit -m "Update requirements" requirements.txt requirements-test.txt + git push diff --git a/requirements-test.in b/requirements-test.in new file mode 100644 index 0000000..d326066 --- /dev/null +++ b/requirements-test.in @@ -0,0 +1,2 @@ +fontbakery[googlefonts]>=0.9.2 +gftools[qa]>=0.9.23 diff --git a/requirements.in b/requirements.in new file mode 100644 index 0000000..25d651b --- /dev/null +++ b/requirements.in @@ -0,0 +1,6 @@ +fontmake>=3.9.0 +gftools[qa]>=0.9.54 +drawbot-skia>=0.5.0 +sh>=2.0.6 +bumpfontversion>=0.4.1 +diffenator2>=0.3.8 diff --git a/scripts/customize.py b/scripts/customize.py new file mode 100644 index 0000000..f7feab4 --- /dev/null +++ b/scripts/customize.py @@ -0,0 +1,123 @@ +#!/usr/bin/env python3 + +# This script is run by the user using `make customize` after the repository +# is cloned. If you are reading this because `make customize` failed, +# skip down to the section headed "INITIALIZATION STEPS". + +from sh import git +import datetime +import re +import sys +from urllib.parse import quote +import subprocess +import requests + +BASE_OWNER = "googlefonts" +BASE_REPONAME = "googlefonts-project-template" +DUMMY_URL = "https://yourname.github.io/your-font-repository-name" +LATEST_OFL = "https://raw.githubusercontent.com/googlefonts/googlefonts-project-template/main/OFL.txt" + + +def repo_url(owner, name): + return f"https://github.com/{owner}/{name}" + + +def web_url(owner, name): + return f"https://{owner}.github.io/{name}" + + +def raw_url(owner, name): + return f"https://raw.githubusercontent.com/{owner}/{name}" + + +def lose(msg, e=None): + print(msg) + print("You will need to do the initialization steps manually.") + print("Read scripts/customize.py for more instructions how to do this.") + if e: + print( + "\nHere's an additional error message which may help diagnose the problem." + ) + raise e + sys.exit(1) + + +try: + my_repo_url = git.remote("get-url", "origin") +except Exception as e: + lose("Could not use git to find my own repository URL", e) + +m = re.match(r"(?:https://github.com/|git@github.com:)(.*)/(.*)/?", str(my_repo_url)) +if not m: + lose( + f"My git repository URL ({my_repo_url}) didn't look what I expected - are you hosting this on github?" + ) + +owner, reponame = m[1], m[2] + +if owner == BASE_OWNER and reponame == BASE_REPONAME: + print("I am being run on the upstream repository; don't do that") + sys.exit() + +# INITIALIZATION STEPS + +# First, the README file contains URLs to pages in the `gh-pages` branch of the +# repo. When initially cloned, these URLs will point to the +# googlefonts/Unified-Font-Repository itself. But downstream users want links +# and badges about their own font, not ours! So any URLs need to be adjusted to +# refer to the end user's repository. + +# We will also pin the dependencies so future builds are reproducible. + +readme = open("README.md").read() +ghpages_url = web_url(owner, reponame) +project_url = repo_url(owner, reponame) + +print("Fixing URLs:", web_url(BASE_OWNER, BASE_REPONAME), "->", ghpages_url) + +readme = readme.replace(web_url(BASE_OWNER, BASE_REPONAME), ghpages_url) +# In the badges, the URLs to raw.githubusercontent.com are URL-encoded as they +# are passed to shields.io. +readme = readme.replace( + quote(raw_url(BASE_OWNER, BASE_REPONAME), safe=""), + quote(raw_url(owner, reponame), safe=""), +) + +print("Fixing URLs:", DUMMY_URL, "->", ghpages_url) +readme = readme.replace(f"`{DUMMY_URL}`", ghpages_url) + +with open("README.md", "w") as fh: + fh.write(readme) + +git.add("README.md") + +# Fix the OFL +year = datetime.date.today().year +title = reponame.title() +copyright = f"Copyright {year} The {title} Project Authors ({project_url})\n" +print("Fetching the latest OFL..") +ofl = requests.get(LATEST_OFL).text.splitlines() +print("Writing an OFL for you") +print(copyright) +with open("OFL.txt", "w") as fh: + fh.write(copyright) + fh.write("\n".join(ofl[1:])) + +git.add("OFL.txt") + +# Pin the dependencies +print("Pinning dependencies") +dependencies = subprocess.check_output(["pip", "freeze"]) +with open("requirements.txt", "wb") as dependency_file: + dependency_file.write(dependencies) +git.add("requirements.txt") + +# Did anything change? +result = git.status("--porcelain") +if any(line.startswith("M ") for line in result.splitlines()): + git.commit("-m", "Customize repository") + + print("Pushing changes to GitHub") + git.push() +else: + print("Nothing changed, no need to push") diff --git a/scripts/index.html b/scripts/index.html index 4d2be4e..07bb551 100644 --- a/scripts/index.html +++ b/scripts/index.html @@ -12,13 +12,7 @@