Notes on enginering leadership and software development.

Automating Swift Docc with Github Actions

Some languages have nice documentation tooling: Yardoc for Ruby, Pydoc for Python, Godoc for Go. Swift has DocC, and it can export docs as a static website, too.

This is part 2 of Generating Swift DocC archives guide. In this post, you'll take the Vue.js app that Swift DocC builds, host it on GitHub Pages, and write a GitHub Action to automatically rebuild and update your docs when the source code changes.

Setting up a GitHub Pages site for your documentation

On GitHub, go to your repository Settings → Pages, and set it to deploy from a branch. Select gh-pages branch, and /docs folder. If the gh-pages is not on the list of available branches — create it, and push it up.

$ git switch -c gh-pages
$ git push origin gh-pages
$ git switch -c gh-pages
$ git push origin gh-pages

Note: This guide assumes that you'll be hosting your docs on github.io, and your GitHub Pages site URL will look like ${username}.github.io/${repository}.

If you'd like to deploy DocC site to a custom domain — that'll work, too, but you will need to not set --hosting-base-path.

Manually deploying the documentation to GitHub Pages

For this example, I've forked out apple/swift-package-manager. The code examples below work on that repository.

# Assuming you're in the Swift project directory (in this case, swift-package-manager itself), 
# and that your `Package.swift` already has a dependency on swift-docc-plugin.
# Runnig this will get output a `./docs` directory containing the site that we need.
$ swift package --allow-writing-to-directory ./docs \
	generate-documentation --target PackageDescription \
    --output-path ./docs \
    --disable-indexing \
    --transform-for-static-hosting \
    --hosting-base-path swift-package-manager
 
# Make a new gh-pages branch
$ git switch -c gh-pages
$ git add ./docs
$ git commit -m "Swift DocC site in ./docs"
$ git push origin gh-pages
# Assuming you're in the Swift project directory (in this case, swift-package-manager itself), 
# and that your `Package.swift` already has a dependency on swift-docc-plugin.
# Runnig this will get output a `./docs` directory containing the site that we need.
$ swift package --allow-writing-to-directory ./docs \
	generate-documentation --target PackageDescription \
    --output-path ./docs \
    --disable-indexing \
    --transform-for-static-hosting \
    --hosting-base-path swift-package-manager
 
# Make a new gh-pages branch
$ git switch -c gh-pages
$ git add ./docs
$ git commit -m "Swift DocC site in ./docs"
$ git push origin gh-pages

It takes a few minutes to process, but when it's done, you'll get a webpage like this one.

Note: Swift DocC site is only available in a subdirectory for your particular target: /documentation/{targetName}. It would be great to have a root web page, but I don't yet know how to craft that.

So far, you've generated Swift DocC documentation, exported it as a static website, and shipped it to GitHub pages. Now let's automate it, so every time you push an update to your library, you get the updated documentation website for free.

Using a GitHub action to deploy documentation

Here's a workflow that will build DocC website, and push it to GitHub pages automatically:

name: Build Swift DocC and publish on GitHub Pages
 
on:
  push:
    # If you wanted to only trigger this flow on certain branches,
    # specify them here in 
    # branches: 
    # alternatively, you can trigger docs only on new tags pushed:
    # tags:
    #   - '*'
 
# `concurrency` specifices how this action is run. 
# Setting concurrency group makes it so that only one build process runs at a time.
concurrency:
  group: "pages"
  cancel-in-progress: false
 
env:
  # Build target specifies which target in your Swift Package to build documentation for.
  # To build all targets, remove this env variable, 
  # and remove --target arg in the building step below.
  BUILD_TARGET: PackageDescription
 
jobs:
  build:
    runs-on: ubuntu-latest
    
    steps:
    - name: Checkout
      uses: actions/checkout@v3
      with:
        fetch-depth: 0
 
    - name: Set up Swift environment
      uses: fwal/setup-swift@v1
      with:
        swift-version: '5.8'
 
    # Build the DocC website using swiftPM.
    - name: Build docs with SwiftPM
      run: |
        swift package --allow-writing-to-directory ./docs \
        generate-documentation --target ${BUILD_TARGET} \
        --output-path ./docs \
        --disable-indexing \
        --transform-for-static-hosting \
        --hosting-base-path swift-package-manager
 
    - name: Commit and push generated documentation
      run: |
        git config --local user.email "github-actions[bot]@users.noreply.github.com"
        git config --local user.name "github-actions[bot]"
        git switch gh-pages
        git add ./docs
        git commit -a -m "Generated Swift DocC"
        git push origin gh-pages
 
name: Build Swift DocC and publish on GitHub Pages
 
on:
  push:
    # If you wanted to only trigger this flow on certain branches,
    # specify them here in 
    # branches: 
    # alternatively, you can trigger docs only on new tags pushed:
    # tags:
    #   - '*'
 
# `concurrency` specifices how this action is run. 
# Setting concurrency group makes it so that only one build process runs at a time.
concurrency:
  group: "pages"
  cancel-in-progress: false
 
env:
  # Build target specifies which target in your Swift Package to build documentation for.
  # To build all targets, remove this env variable, 
  # and remove --target arg in the building step below.
  BUILD_TARGET: PackageDescription
 
jobs:
  build:
    runs-on: ubuntu-latest
    
    steps:
    - name: Checkout
      uses: actions/checkout@v3
      with:
        fetch-depth: 0
 
    - name: Set up Swift environment
      uses: fwal/setup-swift@v1
      with:
        swift-version: '5.8'
 
    # Build the DocC website using swiftPM.
    - name: Build docs with SwiftPM
      run: |
        swift package --allow-writing-to-directory ./docs \
        generate-documentation --target ${BUILD_TARGET} \
        --output-path ./docs \
        --disable-indexing \
        --transform-for-static-hosting \
        --hosting-base-path swift-package-manager
 
    - name: Commit and push generated documentation
      run: |
        git config --local user.email "github-actions[bot]@users.noreply.github.com"
        git config --local user.name "github-actions[bot]"
        git switch gh-pages
        git add ./docs
        git commit -a -m "Generated Swift DocC"
        git push origin gh-pages
 
⌘ ⌘ ⌘
Originally published on Jun 16th 2023.