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
38 changes: 38 additions & 0 deletions .github/workflows/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,31 @@
This directory contains the GitHub workflows for this template. Each workflow
and any supporting files will be documented here.

### [Build LaTeX](./build-latex.yml)

[build-latex.yml](./build-latex.yml) is a reusable workflow that can be used to
build a LaTeX document, and upload the resulting PDF as an artifact.

### [Build Release](./build-release.yml)

[build-release.ym](./build-release.yml) contains the main build workflow for
this repo. It will:

- Automatically generate a changelog and bump the version number, based on new
conventional commits.
- Build the LaTeX document using [build-latex.yml](./build-latex.yml).
- Create a new Release on GitHub, uploading the document `.pdf` and changelog.

This will happen whenever any changes are pushed to `main`, which _should_ be
through PR's!

Note that the document name is derived from the repo name by default. To change
this, edit the following line:

```yaml
DOCUMENT_BASE_NAME: ${{ github.event.repository.name }}
```

### [Fast Forward](./fast-forward.yml)

A workflow that allows using the `/fast-forward` command to complete a PR, and
Expand Down Expand Up @@ -33,6 +58,19 @@ Replacing `FF_PAT` with the name of your access token.
> [personal access token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens),
> this workflow will not be able to trigger other workflows when merging.

### [Lint Commits](./lint-commits.yml)

[lint-commits.yml](./lint-commits.yml) uses [git-cliff](https://git-cliff.org/)
to lint all commits in the repo with every PR, ensuring that they conform to the
[Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0)
specification. It also checks the document revision, to ensure that each PR
correctly updates the document revision to reflect the prospective version bump
based on the commits in the PR.

The main [cliff.toml](../../cliff.toml) is used as the configuration file to
configure `git-cliff`, which should require conventional commits for this
workflow to function correctly.

## [Pull Request](./pull-request.yml)

This workflow simply monitors the commits in a PR, and checks whether they can
Expand Down
95 changes: 95 additions & 0 deletions .github/workflows/build-latex.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
# SPDX-License-Identifier: MIT
# Copyright (c) 2025 Nathaniel Struselis
#
# GitHub Actions workflow to build a LaTeX document.
#
# Note that this workflow is intended to be called by other workflows, after the
# repo has been checked out. It is not intended to be run directly.

name: Build LaTeX Document

# Define environment variables for reuse in the workflow, so that they can be
# easily updated in one place.
env:
BUILD_DIR: build

on:
workflow_call:
inputs:
document-name:
description: "The name to use for the generated PDF document (without the .pdf extension)."
required: true
type: string
artifact-name:
description: "The name to use for the uploaded PDF artifact."
required: true
type: string

jobs:
build-latex:
name: Build LaTeX Document
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v5

# Install packages required to build LaTeX documents. This includes:
# - texlive: The core LaTeX distribution.
# - texlive-fonts-extra: Additional fonts for LaTeX.
# - latexmk: A Perl script that automates the process of building LaTeX
# documents, handling multiple runs to resolve references.
#
# These packages have been selected to provide a good balance between
# install time/size and functionality for most LaTeX documents. Basic
# documents may be built with just texlive or texlive-base, but more
# complex documents may require something like texlive-latex-extra or
# texlive-full.
#
# Adjust this step based on the requirements of your LaTeX document.
- name: Install LaTeX Dependencies
run: |
echo "Updating package lists..."
sudo apt-get update

echo "Installing LaTeX dependencies..."
sudo apt-get install -y \
texlive \
texlive-fonts-extra \
latexmk

# Build the LaTeX document using latexmk. latexmk is a Perl script that
# automatically runs LaTeX the correct number of times to resolve
# cross-references, bibliographies, and indexes.
#
# The following arguments are specified:
# - -pdf: Generate a PDF output.
# - -interaction=nonstopmode: Prevents interactive prompts on errors.
# - -halt-on-error: Stops the build on the first error encountered.
# - -outdir=build: Use the 'build' directory for output files.
# - -jobname=${{ inputs.document-name }}: Set the output file name.
- id: build-latex
name: Build LaTeX document
run: |
# Create the build directory if it doesn't exist.
mkdir -p ${{ env.BUILD_DIR }}

# Build the document using latexmk.
latexmk \
-pdf \
-interaction=nonstopmode \
-halt-on-error \
-outdir=${{ env.BUILD_DIR }} \
-jobname=${{ inputs.document-name }} \
main.tex

# Output the path to the generated PDF as a step output.
echo "pdf=build/${{ inputs.document-name }}.pdf" >> $GITHUB_OUTPUT

# Upload the generated PDF as an artifact for use in subsequent jobs.
- id: upload-pdf
name: Upload PDF Artifact
uses: actions/upload-artifact@v4
with:
name: ${{ inputs.artifact-name }}
path: ${{ steps.build-latex.outputs.pdf }}
if-no-files-found: error
132 changes: 132 additions & 0 deletions .github/workflows/build-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
# SPDX-License-Identifier: MIT
# Copyright (c) 2025 Nathaniel Struselis
#
# GitHub Actions workflow to build the LaTeX document, version it using
# git-cliff, and deploy it as a release on GitHub.

name: Build and Release Document

# Define environment variables for reuse in the workflow, so that they can be
# easily updated in one place.
env:
CLIFF_OUTPUT: CHANGELOG.md
DOCUMENT_BASE_NAME: ${{ github.event.repository.name }}

# Releases will be triggered by changes pushed to main.
on:
push:
branches:
- main

permissions:
contents: write # To create tags and releases.

jobs:
prep:
name: Prepare Version and Changelog
runs-on: ubuntu-latest
outputs:
changelog: ${{ steps.git-cliff.outputs.content }}
version: ${{ steps.sanitise-version.outputs.version }}
filename: ${{ steps.generate-filename.outputs.filename }}
steps:
- name: Checkout Repository
uses: actions/checkout@v5
with:
fetch-depth: 0 # Fetch full history for changelog generation.

# Use git-cliff to generate a changelog and determine the next version.
#
# This will generate a changelog for all unreleased changes and bump the
# version based on commit messages since the last tag.
- name: git-cliff
id: git-cliff
uses: orhun/git-cliff-action@v4
with:
version: latest
config: cliff.toml
args: "--unreleased --bump"
env:
OUTPUT: ${{ env.CLIFF_OUTPUT }}

# Upload the generated changelog for use in subsequent jobs.
- id: upload-changelog
name: Upload Changelog Artifact
uses: actions/upload-artifact@v4
with:
name: changelog
path: ${{ env.CLIFF_OUTPUT }}
if-no-files-found: error

# Sanitise the version number to ensure it has a single 'v' prefix.
- name: Sanitise Version
id: sanitise-version
run: |
version="${{ steps.git-cliff.outputs.version }}"
version="v${version//v}"
echo "Sanitised version: $version"
echo "version=$version" >> $GITHUB_OUTPUT

# Generate the file name for the PDF based on the base name and version.
- name: Generate File Name
id: generate-filename
run: |
echo "Generating filename for version ${{ steps.git-cliff.outputs.version }}"
filename="${{ env.DOCUMENT_BASE_NAME }}_${{ steps.sanitise-version.outputs.version }}"
echo "Generated filename: $filename"
echo "filename=$filename" >> $GITHUB_OUTPUT

build:
name: Build LaTeX Document
uses: ./.github/workflows/build-latex.yml
needs: prep
with:
artifact-name: latex-build
document-name: ${{ needs.prep.outputs.filename }}

release:
name: Create Release
needs: [prep, build]
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v5

- name: Download Build Artifacts
id: download-latex
uses: actions/download-artifact@v5
with:
name: latex-build

- name: Download Changelog Artifact
id: download-changelog
uses: actions/download-artifact@v5
with:
name: changelog

# Create a draft release with the generated changelog and attach the PDF.
# This is needed for repos that use "immutable releases", since otherwise
# the release would be finalised before the PDF is attached causing an
# error.
#
# This also tags the commit with the release.
- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ needs.prep.outputs.version }}
draft: true
body: ${{ needs.prep.outputs.changelog }}
files: |
${{ steps.download-latex.outputs.download-path }}/*.pdf
${{ steps.download-changelog.outputs.download-path }}/${{ env.CLIFF_OUTPUT }}
env:
GIT_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

# Publish the release now that the PDF and changelog have been attached.
# The release becomes immutable after this step if immutable releases are
# enabled.
- name: Publish Draft Release
run: |
gh release edit ${{ needs.prep.outputs.version }} --draft=false
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
106 changes: 106 additions & 0 deletions .github/workflows/lint-commits.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
# SPDX-License-Identifier: MIT
# Copyright (c) 2025 Nathaniel Struselis
#
# GitHub Actions workflow to lint commit messages using git-cliff, ensuring that
# they all follow the Conventional Commits specification
# (https://www.conventionalcommits.org/en/v1.0.0).
#
# This workflow also ensures that the proposed version bump is reflected in the
# LaTeX document's revision field.

name: Lint Commits

# Trigger the workflow on all pull requests.
#
# Note that if you use a squash-and-merge strategy, you could have this only run
# on protected branches to ensure that all commits are squashed and conventional
# before being merged into protected branches. Users could PR into other
# branches to perform the squash, before PRing into the protected branch.
on:
pull_request:
# (OPTIONAL) Only lint PRs into the main branch to allow users to use a
# squash-and-merge strategy into feature branches without the linter
# running.
#branches:
# - main

jobs:
ensure-conventional:
name: Ensure Conventional Commits
runs-on: ubuntu-latest
outputs:
proposed_version: ${{ steps.version-bump.outputs.proposed_version }}
steps:

# Checkout the HEAD of the PR with full history to generate a prospective
# changelog. Checking out the PR HEAD is important, as a merge commit for
# the PR is checked out by default, which is not conventional and wouldn't
# generate a useful changelog.
- name: Checkout PR HEAD
uses: actions/checkout@v5
with:
ref: ${{ github.event.pull_request.head.ref }}
# Ensure the full history is fetched for commit linting.
fetch-depth: 0

# Install git-cliff on the runner using
# https://github.com/taiki-e/install-action.
#
# Note that orhun/git-cliff-action@v4 could be used, but it always outputs
# to a file. In this case, it is better to manually install git-cliff to
# allow more control over its execution.
- name: Install git-cliff
uses: taiki-e/install-action@v2
with:
tool: git-cliff

# Run git-cliff with the main cliff.toml config file that requires
# conventional commits. If any commits are unconventional it will return
# an error and display the non-conventional commits.
#
# This will also output a preview of the changelog that would be generated
# for the PR.
- name: Lint Commits and Preview Changelog
run: git cliff --config cliff.toml

# Determine the proposed version bump based on the commits in the PR.
- name: Propose Version Bump
id: version-bump
run: |
# Use git-cliff to get the proposed version bump.
version="$(git-cliff --bumped-version)"

# Strip any leading 'v' if present to get a clean version number.
version="${version//v}"

echo "Proposed version bump: $version"
echo "proposed_version=$version" >> "$GITHUB_OUTPUT"

# Ensure that the document revision in the LaTeX source is updated to
# match the new version.
ensure-document-revision:
name: Ensure Document Revision is Updated
runs-on: ubuntu-latest
needs: ensure-conventional
steps:
- name: Checkout Repository
uses: actions/checkout@v5

# Ensure that the LaTeX document's revision field is updated to match the
# new version. This step modifies the LaTeX source file and commits the
# change if necessary.
- name: Check for Document Revision
run: |
target_version="${{ needs.ensure-conventional.outputs.proposed_version }}"
echo "Checking ./front_matter/document_revision.tex for $target_version..."

# Check document_revision.tex for the proposed bumped version. Cause
# an error if it isn't present.
if grep "$target_version" ./front_matter/document_revision.tex; then
echo "Document revision is up to date."
exit 0
else
echo "document_revision.tex doesn't contain $target_version!"
echo "Update document_revision.tex to include $target_version."
exit 1
fi
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
# ------------------------------------------------------------------------------
# Repo-specific ignore files.

## Output build directory for LaTeX Workshop.
build/

# ------------------------------------------------------------------------------

# ------------------------------------------------------------------------------
# TeX.gitignore
# From https://github.com/github/gitignore/blob/main/TeX.gitignore
Expand Down
Loading