diff --git a/.github/workflows/README.md b/.github/workflows/README.md index b81ed2b..084cbf9 100644 --- a/.github/workflows/README.md +++ b/.github/workflows/README.md @@ -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 @@ -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 diff --git a/.github/workflows/build-latex.yml b/.github/workflows/build-latex.yml new file mode 100644 index 0000000..ec29e85 --- /dev/null +++ b/.github/workflows/build-latex.yml @@ -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 diff --git a/.github/workflows/build-release.yml b/.github/workflows/build-release.yml new file mode 100644 index 0000000..08a0a0b --- /dev/null +++ b/.github/workflows/build-release.yml @@ -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 }} diff --git a/.github/workflows/lint-commits.yml b/.github/workflows/lint-commits.yml new file mode 100644 index 0000000..9243a1e --- /dev/null +++ b/.github/workflows/lint-commits.yml @@ -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 diff --git a/.gitignore b/.gitignore index 90a5dc6..63b5578 100644 --- a/.gitignore +++ b/.gitignore @@ -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 diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..1446b31 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,11 @@ +{ + "recommendations": [ + "github.vscode-github-actions", + "james-yu.latex-workshop", + "mushan.vscode-paste-image", + "shardulm94.trailing-spaces", + "streetsidesoftware.code-spell-checker", + "tamasfe.even-better-toml", + "yzhang.markdown-all-in-one" + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..c3d2e66 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,17 @@ +{ + "cSpell.language": "en-GB", + "editor.bracketPairColorization.independentColorPoolPerBracketType": true, + "editor.rulers": [ + 80, + 100 + ], + "editor.wordWrap": "wordWrapColumn", + "latex-workshop.latex.autoBuild.cleanAndRetry.enabled": false, + "latex-workshop.latex.clean.subfolder.enabled": true, + "latex-workshop.latex.outDir": "%DIR%/build", + "markdown.extension.toc.levels": "2..6", + "pasteImage.insertPattern": "\\begin{center}\n \\includegraphics[width=\\linewidth]{${imageSyntaxPrefix}${imageFilePath}${imageSyntaxSuffix}}\n\\end{center}", + "pasteImage.path": "${projectRoot}/images", + "pasteImage.showFilePathConfirmInputBox": true, + "trailing-spaces.deleteModifiedLinesOnly": true +} \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f247dd9..0636755 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -12,10 +12,158 @@ starting point for any repos based off this template. ## Contents +- [VSCode Setup](#vscode-setup) + - [LaTeX Workshop](#latex-workshop) + - [Paste Image](#paste-image) + - [Trailing Spaces](#trailing-spaces) + - [Code Spell Checker](#code-spell-checker) + - [Markdown All in One](#markdown-all-in-one) + - [Editor Settings](#editor-settings) - [Conventional Commits](#conventional-commits) - [Breaking Changes](#breaking-changes) - [Types](#types) - [Scopes](#scopes) +- [Document Revision History](#document-revision-history) + +## VSCode Setup + +This repo contains a [VSCode workspace](.vscode/) to make setup easier. Simply +open this repo in VSCode and install the recommended VSCode extensions: + +- [GitHub Actions](https://marketplace.visualstudio.com/items?itemName=GitHub.vscode-github-actions): + Useful when creating and maintaining GitHub Actions. +- [LaTeX Workshop](https://marketplace.visualstudio.com/items?itemName=James-Yu.latex-workshop): + This extension does a majority of the heavy lifting when working with `.tex` + files including preview, syntax highlighting, linting, formatting, + intellisense and more. Note that this extension does have some + [requirements](#latex-workshop). +- [Paste Image](https://marketplace.visualstudio.com/items?itemName=mushan.vscode-paste-image): + Allows pasting images directly into markdown documents, and has been + configured in this workspace to allow pasting directly into `.tex` documents. +- [Trailing Spaces](https://marketplace.visualstudio.com/items?itemName=shardulm94.trailing-spaces): + This just highlights trailing whitespace, which helps keeps the document + source neater. +- [Code Spell Checker](https://marketplace.visualstudio.com/items?itemName=streetsidesoftware.code-spell-checker): + A spell checker that supports most source files. +- [Even Better TOML](https://marketplace.visualstudio.com/items?itemName=tamasfe.even-better-toml): + Adds language support for TOML, which is used by the `git-cliff` configuration + files. +- [Markdown All in One](https://marketplace.visualstudio.com/items?itemName=yzhang.markdown-all-in-one): + This extension makes it trivial to work with Markdown files in VSCode, + allowing easy previewing and linting to make repo documentation easy to + maintain. + +> [!NOTE] +> Most of these extensions have been configured in the shared workspace. Any +> changes are detailed below. + +### LaTeX Workshop + +The [LaTeX Workshop](https://marketplace.visualstudio.com/items?itemName=James-Yu.latex-workshop) +extension requires a compatible LaTeX distribution to be available on the system +PATH. See the +[installation requirements](https://github.com/James-Yu/LaTeX-Workshop/wiki/Install#requirements) +for a list of compatible distributions, and make sure you have one installed. +_Note that you may need to restart VSCode after installing a distribution for it +to be recognised!_ + +The following [workspace settings](.vscode/settings.json) have been configured +for LaTeX Workshop: + +```jsonc +{ + // Disable auto clean and retry for LaTeX builds, as if a build fails there is + // likely an issue that requires fixing manually. + "latex-workshop.latex.autoBuild.cleanAndRetry.enabled": false, + // Enable cleaning of the outDir subfolders during build, as the outDir has + // been specified to a non-root location. + "latex-workshop.latex.clean.subfolder.enabled": true, + // Specify a separate outDir to ensure that any artifacts of previews / builds + // are separated from the source. + "latex-workshop.latex.outDir": "%DIR%/build", +} +``` + +### Paste Image + +[Paste Image](https://marketplace.visualstudio.com/items?itemName=mushan.vscode-paste-image) +has been configured to allow pasting into the LaTeX document, won't be able to +paste images into Markdown documents with how it has been configured in the +[workspace settings](.vscode/settings.json): + +```jsonc +{ + // Configure Paste Image to insert a LaTeX graphic when pasting an image. + "pasteImage.insertPattern": "\"\\\\begin{center}\\n\\t\\t\\\\includegraphics[width=\\\\linewidth]{${imageSyntaxPrefix}${imageFilePath}${imageSyntaxSuffix}}\\n\\t\\\\end{center}\"", + // Configure Paste Image to save images to the root images/ directory. + "pasteImage.path": "${currentFileDir}/images", + // When pasting an image, show a prompt to confirm the image path. + "pasteImage.showFilePathConfirmInputBox": true, +} +``` + +### Trailing Spaces + +[Trailing Spaces](https://marketplace.visualstudio.com/items?itemName=shardulm94.trailing-spaces) +has simply been configured to only automatically trim trailing whitespace from +modified lines, to prevent it from causing unnecessary churn when opening large +documents: + +```json +{ + "trailing-spaces.deleteModifiedLinesOnly": true +} +``` + +### Code Spell Checker + +[Code Spell Checker](https://marketplace.visualstudio.com/items?itemName=streetsidesoftware.code-spell-checker) +has been configured to use `en-GB` by default: + +```json +{ + "cSpell.language": "en-GB", +} +``` + +You can easily change this to your preferred locale through the extension +settings. + +### Markdown All in One + +[Markdown All in One](https://marketplace.visualstudio.com/items?itemName=yzhang.markdown-all-in-one) +is a great quality-of-life extension when maintaining Markdown documents. In +this case it's simply configured to only generate Table of Contents (ToC) +entries for levels 2 to 6, as I find it more useful than having the document +heading displayed in the ToC: + +```json +{ + "markdown.extension.toc.levels": "2..6", +} +``` + +### Editor Settings + +I've also added a couple of settings to the workspace for the editor itself: + +```jsonc +{ + // Use independent color pools for each bracket type to improve readability. + "editor.bracketPairColorization.independentColorPoolPerBracketType": true, + // Display vertical rulers at columns 80 and 100 to help maintain line length. + "editor.rulers": [ + 80, + 100 + ], + // Wrap text at the specified word wrap column for better display formatting. + "editor.wordWrap": "wordWrapColumn", +} +``` + +These are just visual features within the editor, but I particularly like the +rulers as I prefer to keep all documents to a line length of 80 characters where +possible. ## Conventional Commits @@ -33,6 +181,11 @@ This section won't go into much detail about how to structure a [Conventional Commit](https://www.conventionalcommits.org/en/v1.0.0/), and assumes some level of familiarity with the standard. +> [!IMPORTANT] +> Any changes to the [types](#types) section in this document **must** be +> reflected in the [git-cliff config](./cliff.toml) file, to ensure that they +> show up in the changelogs. + ### Breaking Changes Breaking changes (preferably always marked with at least a `!` for visibility) @@ -52,7 +205,7 @@ or re-worked. The `feat` and `fix` types are defined in the [conventional commit specification](https://www.conventionalcommits.org/en/v1.0.0/), -and are mandatory. +and are mandatory. - `feat`: Adding a new feature. In the context of a version-controlled document, this could indicate a new section being added to the document, or a large @@ -74,7 +227,6 @@ Additionally, the following types are suggested by - `style`: In the context of a version-controlled document could indicate changes to the presentation of the document rather than changes to the contents (i.e. changes to the font or the border size). -- `test`: Changes to code / commit linter configuration files and scripts. ### Scopes @@ -87,6 +239,21 @@ to the area of the repository that a commit changes. The following scopes are defined for this repository: -- `release`: Changes to the CI system the affect release builds. +- `release`: Changes in preparation for release, i.e. version bumps. - `config`: Changes to configuration files used by the CI system. - `figures`: Addition or changes to figures included in the document. + +## Document Revision History + +The LaTeX document contains a section for the revision history. Although a +`CHANGELOG` will be generated based off of the commit history when the document +is released, it can often be beneficial to keep a revision summary within the +document itself, so that it can be tracked even when printed. + +This revision history **must** be manually edited in +[./front_matter/document_revision.tex](./front_matter/document_revision.tex), +using initials defined in [./preamble/authors.tex](./preamble/authors.tex). This +must be done as the last commit before each release, and the user should add a +short summary of the revision. + +This should be done using a `chore(release):` commit. diff --git a/README.md b/README.md index d97602b..9ac31be 100644 --- a/README.md +++ b/README.md @@ -23,8 +23,15 @@ document. ## Contents - [Template Structure](#template-structure) +- [Release Strategy](#release-strategy) +- [Consuming This Template](#consuming-this-template) +- [IDE](#ide) - [Conventional Commits](#conventional-commits) - [Repository Configuration Recommendations](#repository-configuration-recommendations) +- [`git-cliff` Configuration](#git-cliff-configuration) + - [Configure the Repo URL](#configure-the-repo-url) + - [Commit Parsers](#commit-parsers) +- [Workflow Configuration](#workflow-configuration) - [License](#license) - [What This Means For You](#what-this-means-for-you) @@ -32,12 +39,59 @@ document. ```text LaTeX_Template # Repo root. + ├─ .github/ # GitHub files i.e. workflows, templates, etc. + ├─ .vscode/ # VSCode shared workspace files. + ├─ build/ # Build output dir for LaTeX Workshop. + ├─ front_matter/ # .tex files defining the front matter. + ├─ images/ # Image files used in figures. + ├─ preamble/ # .tex files defining the preamble contents. + ├─ sections/ # .tex files defining the main sections. + ├─ .gitignore # .gitignore file. + ├─ appendices.tex # Appendices definitions. + ├─ cliff.toml # git-cliff configuration file. ├─ CONTRIBUTING.md # Contribution guidelines. ├─ LICENSE # MIT License for the template. - ├─ README.md # Main template README (You are here!). - └─ main.tex # Main entry point for the .tex document. + ├─ main.tex # Main entry point for the .tex document. + └─ README.md # Main template README (You are here!). ``` +All directories that should be modified by contributors contain their own +`README.md` files. + +## Release Strategy + +The workflows within this repo are set up to create a release whenever any +changes are pushed to `main`. The document version will be automatically bumped +based on the conventional commits, and releases and changelogs will +automatically be published to GitHub. + +## Consuming This Template + +> [!TIP] +> Remove this section after consuming this template and configuring your repo. + +After creating a GitHub repo based on this template, there are a few things that +you should configure to ensure that the workflows work correctly, and that the +conventional commit configuration is correct for your document. These are all +described in other sections, but are all linked here for convenience: + + +- [Repo Configuration](#repository-configuration-recommendations) +- [Define Conventional Commit Types](./CONTRIBUTING.md#types) +- [Define Conventional Commit Scopes](./CONTRIBUTING.md#scopes) +- [`git-cliff` Configuration](#git-cliff-configuration) +- [Workflow Configuration](#workflow-configuration) +- [Review the LICENSE](#license) + +## IDE + +This template is designed around the use of +[VSCode](https://code.visualstudio.com/) as an IDE since it is freely available +and relatively easy to use. + +To configure [VSCode](https://code.visualstudio.com/) for use with LaTeX, see +the [VSCode Setup section of CONTRIBUTING.md](./CONTRIBUTING.md#vscode-setup). + ## Conventional Commits This template assumes the use of @@ -86,6 +140,76 @@ repository as follows: - Enable release immunity to ensure old versions of the document cannot be updated. +## `git-cliff` Configuration + +> [!TIP] +> Remove this section after consuming this template and configuring your repo. + +The [`git-cliff` configuration file](./cliff.toml) has a few **required** +modifications to ensure that it is set up to work for your repo, rather than the +template. These are listed below, but you may wish to make other changes to that +file to suit your versioning strategy. + +### Configure the Repo URL + +The `` URL is specified in the `commit_preprocessors`, and is used to +generate links to issues in the changelog. Ensure that you update the `` +definition in the `postprocessors` section so that the links are generated with +the correct URL: + +```toml +postprocessors = [ + # Replace the placeholder with a URL. + { pattern = '', replace = "https://github.com/YourName/YourRepo" }, +] +``` + +### Commit Parsers + +The commit parsers group commits within each release into named "sections". +Ensure that these sections match the types you define in your +[CONTRIBUTING.md document](./CONTRIBUTING.md#types). For example: + +```toml +commit_parsers = [ + { message = "^feat", group = "🚀 Features" }, + { message = "^fix", group = "🐛 Fixes" }, + { message = "^docs", group = "📚 Documentation" }, + { message = "^ci", group = "🛠️ CI/CD" }, + { message = "^style", group = "🎨 Styling" }, + { message = "^chore\\(release\\)", skip = true }, + { message = "^chore", group = "⚙️ Miscellaneous Tasks" }, + { message = "^revert", group = "◀️ Revert" }, + { message = ".*", group = "💼 Other" }, +] +``` + +## Workflow Configuration + +> [!TIP] +> Remove this section after consuming this template and configuring your repo. + +By default, [build-release.yml](./.github/workflows/build-release.yml) will use +the repo name as the name of the document. If you wish to change this, edit the +following line of [build-release.yml](./.github/workflows/build-release.yml): + +```yaml +DOCUMENT_BASE_NAME: ${{ github.event.repository.name }} +``` + +[fast-forward.yml](./.github/workflows/fast-forward.yml) and +[pull-request.yml](./.github/workflows/pull-request.yml) are optional workflows +that allow you to perform fast-forward merges in GitHub. If you don't require +this, then you can safely delete them. + +If you wish to use them, the +[fast-forward.yml](./.github/workflows/fast-forward.yml) workflow requires you +to delete a line from the workflow, or create a +[personal access token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens). + +For more information, see +[the workflow README.md](./.github/workflows/README.md#fast-forward). + ## License The contents of this repository, including the basic LaTeX template, GitHub diff --git a/appendices.tex b/appendices.tex new file mode 100644 index 0000000..620734b --- /dev/null +++ b/appendices.tex @@ -0,0 +1,12 @@ +% SPDX-License-Identifier: MIT +% Copyright (c) 2025 Nathaniel Struselis +% +% Define how the appendices are displayed. + +\begin{appendices} + % Appendices section for tables and figures throughout the document. + \section{Tables and Figures} + % Split tables and figures into separate subsections within the appendix. + \listoftables + \listoffigures +\end{appendices} diff --git a/cliff.toml b/cliff.toml new file mode 100644 index 0000000..4b6abf7 --- /dev/null +++ b/cliff.toml @@ -0,0 +1,94 @@ +# git-cliff ~ configuration file +# https://git-cliff.org/docs/configuration + + +[changelog] +# A Tera template to be rendered for each release in the changelog. +# See https://keats.github.io/tera/docs/#introduction +body = """ +{%- if version -%} + ## [{{ version | trim_start_matches(pat="v") }}] - {{ timestamp | date(format="%Y-%m-%d") }} +{%- else -%} + ## [unreleased] +{%- endif %} + +{% for group, commits in commits | group_by(attribute="group") -%} + ### {{ group | striptags | trim | upper_first }} + + {% for commit in commits -%} + - {% if commit.scope %}*({{ commit.scope }})* {% endif -%} + {%- if commit.breaking %}[**breaking**] {% endif -%} + {{ commit.message | upper_first }} + {%- if commit.remote.username %} by @{{ commit.remote.username }}{%- endif -%} + {%- if commit.remote.pr_number %} in #{{ commit.remote.pr_number }}{%- endif %} + {% endfor %} +{% endfor -%} +{%- if github.contributors | filter(attribute="is_first_time", value=true) -%} + ## New Contributors + + {% for contributor in github.contributors | filter(attribute="is_first_time", value=true) -%} + - @{{ contributor.username }} made their first contribution + {%- if contributor.pr_number %} in #{{ contributor.pr_number }}{%- endif %} + {% endfor -%} +{%- endif -%} +""" +# Remove leading and trailing whitespaces from the changelog's body. +trim = true +# Render body even when there are no releases to process. +render_always = true +# An array of regex based postprocessors to modify the changelog. +postprocessors = [ + # Replace the placeholder with a URL. + { pattern = '', replace = "https://github.com/NathanielJS1541/LaTeX_Template" }, +] + +[git] +# Parse commits according to the conventional commits specification. +# See https://www.conventionalcommits.org +conventional_commits = true +# Require all commits to be conventional. +# This is required by the lint-commits.yml GitHub Action workflow. +require_conventional = true +# An array of regex based parsers to modify commit messages prior to further processing. +commit_preprocessors = [ + # Replace issue numbers with link templates to be updated in `changelog.postprocessors`. + { pattern = '#([0-9]+)', replace = "[#${1}](/issues/${1})"}, + # Check spelling of the commit message using https://github.com/crate-ci/typos. + # If the spelling is incorrect, it will be fixed automatically. + #{ pattern = '.*', replace_command = 'typos --write-changes -' }, +] +# Prevent commits that are breaking from being excluded by commit parsers. +protect_breaking_commits = true +# An array of regex based parsers for extracting data from the commit message. +# Assigns commits to groups. +# Optionally sets the commit's scope and can decide to exclude commits from +# further processing. +# +# Note that any changes here should be reflected in the CONTRIBUTING.md +# document. +commit_parsers = [ + { message = "^feat", group = "🚀 Features" }, + { message = "^fix", group = "🐛 Fixes" }, + { message = "^docs", group = "📚 Documentation" }, + { message = "^ci", group = "🛠️ CI/CD" }, + { message = "^style", group = "🎨 Styling" }, + { message = "^chore\\(release\\)", skip = true }, + { message = "^chore", group = "⚙️ Miscellaneous Tasks" }, + { message = "^revert", group = "◀️ Revert" }, + { message = ".*", group = "💼 Other" }, +] +# Exclude commits that are not matched by any commit parser. +filter_commits = false +# An array of link parsers for extracting external references, and turning them into URLs, using regex. +link_parsers = [] +# Include only the tags that belong to the current branch. +use_branch_tags = false +# Order releases topologically instead of chronologically. +topo_order = false +# Order releases topologically instead of chronologically. +topo_order_commits = true +# Order of commits in each group/release within the changelog. +# Allowed values: newest, oldest +sort_commits = "oldest" +# Process submodules commits +recurse_submodules = false diff --git a/front_matter/README.md b/front_matter/README.md new file mode 100644 index 0000000..4c7313d --- /dev/null +++ b/front_matter/README.md @@ -0,0 +1,22 @@ +# Front Matter Files + +This directory contains any files used to define or generate the front matter of +[main.tex](../main.tex). The front matter includes the title, abstract, revision +history, and table of contents. The functions of the different files are +included in the [file descriptions section](#file-descriptions). + +## File Descriptions + +- [document_revision.tex](./document_revision.tex) contains the revision history + table. + - The revision history table defines the authors of the document and the + contents of the date field. Both of these are displayed as part of the title + page in [front_matter.tex](./front_matter.tex). To display the author's full + names, they should be included in [authors.tex](../preamble/authors.tex). +- [front_matter.tex](./front_matter.tex) contains the definitions all of the + front matter displayed before the main document contents. + - The title page is generated first. + - The abstract is displayed directly beneath the title. + - The [document_revision.tex](./document_revision.tex) is displayed underneath + the abstract. + - The table of contents is generated on a new page. diff --git a/front_matter/document_revision.tex b/front_matter/document_revision.tex new file mode 100644 index 0000000..09e291c --- /dev/null +++ b/front_matter/document_revision.tex @@ -0,0 +1,18 @@ +% SPDX-License-Identifier: MIT +% Copyright (c) 2025 Nathaniel Struselis +% +% Document Revision Tracking. + +% Decrement the table number before the version history table is generated, as +% it increments this counter but does not display a caption. This just makes the +% rest of the document captions start at 1 which looks neater. +\addtocounter{table}{-1} + +% Version history table. +\begin{versionhistory} + % To add new names to the version history table, add a macro to + % preamble/authors.tex to link the initials here to a name. Without doing + % this, only the initials will appear for the document authors. + % Example entry for NS in preamble/authors.tex: + \vhEntry{0.1.0}{2025/10/15}{NS}{Initial template version} +\end{versionhistory} diff --git a/front_matter/front_matter.tex b/front_matter/front_matter.tex new file mode 100644 index 0000000..b709f5d --- /dev/null +++ b/front_matter/front_matter.tex @@ -0,0 +1,23 @@ +% SPDX-License-Identifier: MIT +% Copyright (c) 2025 Nathaniel Struselis +% +% Define the appearance and structure of the front matter for the start of the +% document. + +% Generate the title. +\maketitle + +% Document abstract. This will appear directly beneath the title. +\begin{abstract} +This is an extensible LaTeX document template which can be used as a generic +starting point for a version-controlled document. +\end{abstract} + +% Document revision. In an article, this will appear on the same page as the +% title, underneath the abstract. +\input{front_matter/document_revision} + +% Generate the table of contents on a new page. Without \clearpage, this will +% appear on the same page as the title. +\clearpage +\tableofcontents diff --git a/images/01_example_image.png b/images/01_example_image.png new file mode 100644 index 0000000..dfa9728 Binary files /dev/null and b/images/01_example_image.png differ diff --git a/images/README.md b/images/README.md new file mode 100644 index 0000000..0eb58b1 --- /dev/null +++ b/images/README.md @@ -0,0 +1,9 @@ +# Images + +This directory contains all images used throughout the document. These images +can be used for both figures and as part of the fancy header. + +It is recommended to name them in such a way that they are grouped by section, +for example prefixing images with the same number as the +[sections](../sections/), so section 1 images are all prefixed with `01_`. This +ensures they will all be grouped together and therefore easier to find. diff --git a/main.tex b/main.tex new file mode 100644 index 0000000..c3eb29f --- /dev/null +++ b/main.tex @@ -0,0 +1,154 @@ +% SPDX-License-Identifier: MIT +% Copyright (c) 2025 Nathaniel Struselis +% +% Basic LaTeX Template Document. + +% Specify the document class and options. +% Document Classes: +% - article: Suitable for shorter documents such as journal articles, short +% reports, and essays. It does not support chapters. +% - report: Ideal for longer documents like theses, dissertations, and technical +% reports. It supports chapters and sections. +% - book: Used for books and other lengthy documents. It includes support for +% chapters, sections, and front matter (e.g., title page, dedication). +% - letter: Designed for writing letters. It provides a simple layout for +% correspondence. +% - beamer: Used for creating presentations. It offers a variety of slide +% layouts and themes. +% Class Options: +% - 10pt, 11pt, 12pt: Sets the font size of the document. The default is 10pt. +% - a4paper, letterpaper, etc.: Specifies the paper size. Note that in this +% case, the geometry package is used to set the paper size. +% - draft: Enables draft mode, which speeds up compilation by not loading images +% and highlighting overfull boxes. +% - onecolumn, twocolumn: Sets the number of columns in the document. +% - fleqn: Aligns equations to the left instead of centering them. +% - leqno: Places equation numbers on the left side instead of the right. +% - landscape: Changes the document layout to landscape orientation. +% - oneside, twoside: Configures how the document prints. +% - titlepage, notitlepage: Determines whether a separate title page is created. +% - openright, openany: Controls whether chapters start on the right-hand page +% (openright) or any page (openany). +% - british: Use British language conventions and spelling. This is best in +% conjunction with the babel package. +\documentclass[british,12pt]{article} + +% ------------------------------ Package Includes ------------------------------ + +% geometry package to adjust the size of the margin around the page. +% The paper size is specified here instead of in the document class. +\usepackage[a4paper, left=2cm, right=2cm, top=2.5cm, bottom=3cm]{geometry} +% babel package for better language and regional rules support. +% To change the region, change this and the document class accordingly. +\usepackage[british]{babel} +% vhistory package to create a revision history table. Specify that it should be +% added to the Table of Contents. +\usepackage[tocentry]{vhistory} +% xcolor package to provide driver-independent access to colours. +\usepackage{xcolor} +% hyperref package to create and manage the formatting of hyperlinks. +\usepackage{hyperref} +% caption package provides better captioning for tables etc. +\usepackage{caption} +% The appendix package provides more customizable appendices. +% Options: +% - toc: Adds a header (e.g., 'Appendices') to the Table of Contents (ToC) +% before listing the appendices. +% - titletoc: Includes the appendix titles in the ToC. +% - title: Adds a title (e.g., 'Appendices') at the beginning of the appendices +% section. +% - page: Inserts a title page for the appendices. +% - header: Adds a header to each appendix page. +\usepackage[toc, titletoc, title, page, header]{appendix} +% Use T1 font encoding using a wider range of characters than the default OT1 +% encoding. +\usepackage[T1]{fontenc} +% inputenc to specify the encoding of input files as UTF-8. +\usepackage[utf8]{inputenc} +% ulem allows adding underlines within the document. +\usepackage{ulem} +% titling package to allow access to the title, author and date throughout the +% document. Usually they are reset after \maketitle. +\usepackage{titling} +% lastpage package to get the page number of the last page. +\usepackage{lastpage} +% graphicx package to add images to the document with \includegraphics. +\usepackage{graphicx} +% fancyhdr to add custom headers and footers to the document. +\usepackage{fancyhdr} +% amsmath package provides advanced maths environments and symbols. +\usepackage{amsmath} +% float package improves control over figure/table placement. +\usepackage{float} +% FiraSans package to change the font to Fira Sans. Set it as the default font +% for the whole document. +\usepackage[sfdefault]{FiraSans} +% FiraMono package to change the monospace font to Fira Mono, and set it as the +% default monospace font. +\usepackage{FiraMono} +% Alternatively, comment out the above lines and uncomment the following line to +% use the opensans package to change the font to Open Sans, and set it as the +% default for the whole document. +%\usepackage[default]{opensans} + +% ------------------------------------------------------------------------------ + +% -------------------------- Package Configurations ---------------------------- + +% Package configuration. +% Configure the caption package: +% Add 10pt of spacing above and below table captions. +\captionsetup[table]{aboveskip=10pt, belowskip=10pt} + +% Disable hyperlink colours within the document to make printed documents easier +% to read. +\hypersetup{ + % Open all bookmarks in a PDF viewer by default. + bookmarksopen=true, + % Include section numbers in the bookmarks. + bookmarksnumbered=true, + % Remove borders around links in the PDF. + pdfborder={0 0 0} +} + +% Configure the fancyhdr package with the custom header and footer format. +\input{preamble/fancyhdr} + +% Macros defining the author names and initials. +\input{preamble/authors} + +% ------------------------------------------------------------------------------ + +% ------------------------------- Title Commands ------------------------------- + +% Storing commands to generate the title with \maketitle. +% Do not manually add the author name here! Add the initials to +% preamble/authors.tex and add an entry to preamble/document_revision.tex. This +% will automatically add the author names. This will also populate the date +% field automatically. +\title{LaTeX Template Document} +\author{\vhListAllAuthorsLong} +\date{Version \vhCurrentVersion\ from \vhCurrentDate} + +% ------------------------------------------------------------------------------ + +% ----------------------------- Document Contents ------------------------------ + +% Enough preamble... Time for the document! +\begin{document} + +% Front matter pages, including title, revision history, and table of contents, +% glossary etc. +\include{front_matter/front_matter} + +% Main document sections. +\include{sections/00_introduction} +\include{sections/01_example_section} +\include{sections/02_conclusion} + +% Appendices. This can be removed if not required for the document. +\include{appendices} + +\end{document} + +% ------------------------------------------------------------------------------ diff --git a/preamble/README.md b/preamble/README.md new file mode 100644 index 0000000..7386c37 --- /dev/null +++ b/preamble/README.md @@ -0,0 +1,18 @@ +# Preamble Files + +This directory contains any files that are included in the preamble of +[main.tex](../main.tex). The functions of the different files are included in +the [file descriptions section](#file-descriptions). + +## File Descriptions + +- [authors.tex](./authors.tex) contains the command definitions that translate + the initials, used in the `vhistory` table in + [front_matter/document_revision.tex](../front_matter/document_revision.tex), + into the full name listed in the authors section of the document. Without a + definition for each set of initials here, the initials for the author will be + displayed instead. +- [fancyhdr.tex](./fancyhdr.tex) contains the definitions for the header and + footer of the document. There are example comments within the file to add a + logo or other image in the top left or right of the document, although other + modifications are trivial. diff --git a/preamble/authors.tex b/preamble/authors.tex new file mode 100644 index 0000000..2eb67df --- /dev/null +++ b/preamble/authors.tex @@ -0,0 +1,8 @@ +% SPDX-License-Identifier: MIT +% Copyright (c) 2025 Nathaniel Struselis +% +% Macros used to translate initials into full names. This is used by the +% vhistory package. The commands should be in the following format: +% \newcommand{\INITIALS}{Full Name} +% For example: +\newcommand{\NS}{Nathaniel Struselis} diff --git a/preamble/fancyhdr.tex b/preamble/fancyhdr.tex new file mode 100644 index 0000000..4fb0560 --- /dev/null +++ b/preamble/fancyhdr.tex @@ -0,0 +1,31 @@ +% SPDX-License-Identifier: MIT +% Copyright (c) 2025 Nathaniel Struselis +% +% Fancy Header and Footer Configuration. + +% Use the page style defined by fancyhdr. Note that this will only take effect +% on pages after this file is included. +\pagestyle{fancy} + +% Clear all existing header and footer fields. +\fancyhf{} + +% Left header containing an image or logo, if required. +%\fancyhead[L]{\includegraphics[height=1cm]{./path/to/left_image.png}} +% Center header containing the document title. +\fancyhead[C]{\thetitle} +% Right header containing an image or logo, if required. +%\fancyhead[R]{\includegraphics[height=1cm]{./path/to/right_image.png}} + +% Left footer containing the document author(s) according to +% document_revision.tex. +\fancyfoot[L]{\theauthor} +% Center footer containing the date field. For this template, the default is the +% version number and the date in the form "Version XX.XX from YYYY/MM/DD". +\fancyfoot[C]{\thedate} +% Right footer with page number in the form "Page X of Y". Note the use of +% \pageref* instead of \pageref, to not create a link to the last page. +\fancyfoot[R]{Page \thepage\ of \pageref*{LastPage}} + +% Adjust the height of the header to fit the images. +\setlength{\headheight}{1.2cm} diff --git a/sections/00_introduction.tex b/sections/00_introduction.tex new file mode 100644 index 0000000..79fc795 --- /dev/null +++ b/sections/00_introduction.tex @@ -0,0 +1,10 @@ +% SPDX-License-Identifier: MIT +% Copyright (c) 2025 Nathaniel Struselis +% +% Introduction to the document. This can be removed if not required. + +\section{Introduction} + +This document should provide a brief showcase of the different features of this +LaTeX template. This should allow easy evaluation of the template and its +features. diff --git a/sections/01_example_section.tex b/sections/01_example_section.tex new file mode 100644 index 0000000..e882acb --- /dev/null +++ b/sections/01_example_section.tex @@ -0,0 +1,49 @@ +% SPDX-License-Identifier: MIT +% Copyright (c) 2025 Nathaniel Struselis +% +% Example section to demonstrate the document template. + +\section{Example Section} + +\subsection{Text} + +This is an example section to demonstrate text. + +\subsection{Equations} + +An example equation can be seen in equation~\ref{eq:energy}. + +\begin{equation} + E = mc^2 + \label{eq:energy} +\end{equation} + +\subsection{Figures} + +Figure~\ref{fig:example_image} shows an example image. + +\begin{figure}[H] + \centering + \includegraphics[width=0.5\textwidth]{images/01_example_image.png} + \caption{An example image} + \label{fig:example_image} +\end{figure} + +\subsection{Tables} + +An example table can be seen in Table~\ref{tab:example_table}. + +\begin{table}[H] + \centering + \caption{An example table} + \label{tab:example_table} + \begin{tabular}{|c|c|c|} + \hline + Column 1 & Column 2 & Column 3 \\ + \hline + A & B & C \\ + 1 & 2 & 3 \\ + X & Y & Z \\ + \hline + \end{tabular} +\end{table} diff --git a/sections/02_conclusion.tex b/sections/02_conclusion.tex new file mode 100644 index 0000000..008989f --- /dev/null +++ b/sections/02_conclusion.tex @@ -0,0 +1,10 @@ +% SPDX-License-Identifier: MIT +% Copyright (c) 2025 Nathaniel Struselis +% +% Conclusion to the document. This can be removed if not required. The number in +% the filename should be adjusted to ensure this is the last section. + +\section{Conclusion} + +In short, LaTeX is great! Hopefully this template helps you get started with +your own LaTeX documents. diff --git a/sections/README.md b/sections/README.md new file mode 100644 index 0000000..260bfff --- /dev/null +++ b/sections/README.md @@ -0,0 +1,12 @@ +# Document Sections + +To make larger documents easier to edit and maintain, it is generally a good +practice to split the document contents into separate files for each section, +and include them all in a [main.tex](../main.tex) file. This directory contains +all of the individual document sections, which are included in +[main.tex](../main.tex). + +For most document classes, splitting it into separate sections is a sensible +choice. However, for longer document classes such as a `report` or `book`, it +would be better to split the document into its chapters. In this case, simply +rename this directory to chapters to keep it easy to follow.