Skip to content

Commit c09f568

Browse files
authored
Merge pull request #2809 from samsrabin/update-docs-builder-2
Update docs infrastructure
2 parents b4009f0 + c99bfb6 commit c09f568

34 files changed

+1170
-78
lines changed
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
# Based on https://docs.github.com/en/packages/managing-github-packages-using-github-actions-workflows/publishing-and-installing-a-package-with-github-actions#publishing-a-package-using-an-action (last accessed 2025-05-09)
2+
name: Build and publish ctsm-docs Docker image
3+
4+
on:
5+
# Run this whenever something gets pushed to master
6+
push:
7+
branches: ['master']
8+
paths:
9+
- 'doc/ctsm-docs_container/Dockerfile'
10+
- 'doc/ctsm-docs_container/requirements.txt'
11+
12+
# Run this whenever it's manually called
13+
workflow_dispatch:
14+
15+
jobs:
16+
# This first job checks that the container can be built, and that we can use it to build the docs without error.
17+
build-image-and-test-docs:
18+
name: Build image and test docs
19+
uses: ./.github/workflows/docker-image-common.yml
20+
secrets: inherit
21+
22+
# This second job actually builds and publishes the container.
23+
push-and-attest:
24+
name: Publish and attest
25+
runs-on: ubuntu-latest
26+
27+
# Wait to run this job until after build-image-and-test-docs. If that job fails, something might be wrong with the container, so don't try this one. (It might also have failed because of something wrong with doc-builder or the documentation.)
28+
needs: build-image-and-test-docs
29+
30+
# Variables output by the build-image-and-test-docs job.
31+
env:
32+
REGISTRY: ${{ needs.build-image-and-test-docs.outputs.REGISTRY }}
33+
IMAGE_NAME: ${{ needs.build-image-and-test-docs.outputs.IMAGE_NAME }}
34+
IMAGE_TAG: ${{ needs.build-image-and-test-docs.outputs.image_tag }}
35+
36+
# Sets the permissions granted to the `GITHUB_TOKEN` for the actions in this job.
37+
permissions:
38+
contents: read
39+
packages: write
40+
attestations: write
41+
id-token: write
42+
43+
steps:
44+
- name: Checkout repository
45+
uses: actions/checkout@v4
46+
47+
# Uses the `docker/login-action` action to log in to the Container registry using the account and password that will publish the packages. Once published, the packages are scoped to the account defined here.
48+
- name: Log in to the Container registry
49+
uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1
50+
with:
51+
registry: ${{ env.REGISTRY }}
52+
username: ${{ github.actor }}
53+
password: ${{ secrets.GITHUB_TOKEN }}
54+
55+
# This step sets up Docker Buildx, which is needed for the multi-platform build in the next step
56+
# https://docs.docker.com/build/ci/github-actions/multi-platform/
57+
# v3.1.0
58+
- name: Set up Docker Buildx
59+
uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2
60+
61+
# This step uses the `docker/build-push-action` action to build the image, based on the ctsm-docs `Dockerfile`.
62+
# It uses the `context` parameter to define the build's context as the set of files located in the specified path. For more information, see [Usage](https://github.com/docker/build-push-action#usage) in the README of the `docker/build-push-action` repository.
63+
# It uses the `tags` and `labels` parameters to tag and label the image with the output from the "meta" step.
64+
# v6.15.0
65+
- name: Push Docker image
66+
id: push
67+
uses: docker/build-push-action@471d1dc4e07e5cdedd4c2171150001c434f0b7a4
68+
with:
69+
context: doc/ctsm-docs_container
70+
platforms: linux/amd64,linux/arm64
71+
push: true
72+
load: false
73+
tags: ${{ env.IMAGE_TAG }}
74+
labels: ""
75+
76+
# This step generates an artifact attestation for the image, which is an unforgeable statement about where and how it was built. It increases supply chain security for people who consume the image. For more information, see [Using artifact attestations to establish provenance for builds](/actions/security-guides/using-artifact-attestations-to-establish-provenance-for-builds).
77+
- name: Generate artifact attestation
78+
uses: actions/attest-build-provenance@v2
79+
with:
80+
subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
81+
subject-digest: ${{ steps.push.outputs.digest }}
82+
push-to-registry: true
83+
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Modified from https://docs.github.com/en/packages/managing-github-packages-using-github-actions-workflows/publishing-and-installing-a-package-with-github-actions#publishing-a-package-using-an-action (last accessed 2025-05-09)
2+
name: Test building ctsm-docs Docker image and using it to build the docs
3+
4+
# Configures this workflow to run every time a change in the Docker container setup is pushed to the master branch
5+
on:
6+
push:
7+
paths:
8+
- 'doc/ctsm-docs_container/**'
9+
- '.github/workflows/docker-image-ctsm-docs-build.yml'
10+
- '.github/workflows/docker-image-build-common.yml'
11+
12+
pull_request:
13+
paths:
14+
- 'doc/ctsm-docs_container/**'
15+
- '.github/workflows/docker-image-ctsm-docs-build.yml'
16+
- '.github/workflows/docker-image-build-common.yml'
17+
18+
workflow_dispatch:
19+
20+
# There is a single job in this workflow. It's configured to run on the latest available version of Ubuntu.
21+
jobs:
22+
build-image-and-test-docs:
23+
name: Build image and test docs
24+
uses: ./.github/workflows/docker-image-common.yml
25+
secrets: inherit
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
name: Workflow used by docker-image workflows
2+
3+
on:
4+
workflow_call:
5+
outputs:
6+
REGISTRY:
7+
description: "Container registry"
8+
value: ${{ jobs.build-image-and-test-docs.outputs.REGISTRY }}
9+
IMAGE_NAME:
10+
description: "Docker image name"
11+
value: ${{ jobs.build-image-and-test-docs.outputs.IMAGE_NAME }}
12+
image_tag:
13+
description: "First image tag"
14+
value: ${{ jobs.build-image-and-test-docs.outputs.image_tag }}
15+
16+
# Defines two custom environment variables for the workflow. These are used for the Container registry domain, and a name for the Docker image that this workflow builds.
17+
env:
18+
REGISTRY: ghcr.io
19+
IMAGE_NAME: ${{ github.repository }}/ctsm-docs
20+
21+
# There is a single job in this workflow. It's configured to run on the latest available version of Ubuntu.
22+
jobs:
23+
build-image-and-test-docs:
24+
runs-on: ubuntu-latest
25+
# Variables that might be needed by the calling workflow
26+
outputs:
27+
REGISTRY: ${{ env.REGISTRY }}
28+
IMAGE_NAME: ${{ env.IMAGE_NAME }}
29+
image_tag: ${{ steps.set-image-tag.outputs.IMAGE_TAG }}
30+
# Sets the permissions granted to the `GITHUB_TOKEN` for the actions in this job.
31+
permissions:
32+
contents: read
33+
packages: write
34+
attestations: write
35+
id-token: write
36+
37+
steps:
38+
39+
- name: Checkout repository
40+
uses: actions/checkout@v4
41+
42+
# Uses the `docker/login-action` action to log in to the Container registry using the account and password that will publish the packages. Once published, the packages are scoped to the account defined here.
43+
- name: Log in to the Container registry
44+
uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1
45+
with:
46+
registry: ${{ env.REGISTRY }}
47+
username: ${{ github.actor }}
48+
password: ${{ secrets.GITHUB_TOKEN }}
49+
50+
# This step uses [docker/metadata-action](https://github.com/docker/metadata-action#about) to extract tags and labels that will be applied to the specified image. The `id` "meta" allows the output of this step to be referenced in a subsequent step. The `images` value provides the base name for the tags and labels.
51+
- name: Extract metadata (tags, labels) for Docker
52+
id: meta
53+
uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7
54+
with:
55+
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
56+
57+
# This step uses the `docker/build-push-action` action to build the image, based on the ctsm-docs `Dockerfile`.
58+
# It uses the `context` parameter to define the build's context as the set of files located in the specified path. For more information, see [Usage](https://github.com/docker/build-push-action#usage) in the README of the `docker/build-push-action` repository.
59+
# It uses the `tags` and `labels` parameters to tag and label the image with the output from the "meta" step.
60+
# v6.15.0
61+
- name: Build Docker image
62+
id: build-image
63+
uses: docker/build-push-action@471d1dc4e07e5cdedd4c2171150001c434f0b7a4
64+
with:
65+
context: doc/ctsm-docs_container
66+
push: false
67+
load: true
68+
tags: ${{ steps.meta.outputs.tags }}
69+
labels: ${{ steps.meta.outputs.labels }}
70+
71+
# Try building our docs using the new container
72+
- name: Checkout doc-builder external
73+
run: |
74+
bin/git-fleximod update doc-builder
75+
- name: Set image tag for docs build
76+
id: set-image-tag
77+
run: |
78+
echo "IMAGE_TAG=$(echo '${{ steps.meta.outputs.tags }}' | cut -d',' -f1)" >> $GITHUB_ENV
79+
echo "IMAGE_TAG=$(echo '${{ steps.meta.outputs.tags }}' | cut -d',' -f1)" >> $GITHUB_OUTPUT
80+
- name: Build docs using container
81+
id: build-docs
82+
run: |
83+
cd doc && ./build_docs -b ${PWD}/_build -c -d -i $IMAGE_TAG

.github/workflows/docs-common.yml

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
name: Jobs shared by docs workflows
2+
3+
on:
4+
workflow_call:
5+
inputs:
6+
use_conda:
7+
required: false
8+
type: boolean
9+
default: false
10+
conda_env_file:
11+
required: false
12+
type: string
13+
default: ""
14+
conda_env_name:
15+
required: false
16+
type: string
17+
default: ""
18+
secrets: {}
19+
20+
jobs:
21+
build-docs:
22+
runs-on: ubuntu-latest
23+
steps:
24+
- uses: actions/checkout@v4
25+
with:
26+
fetch-depth: 0
27+
lfs: true
28+
29+
- name: Checkout doc-builder external
30+
run: |
31+
bin/git-fleximod update doc-builder
32+
33+
# Do this if not using conda
34+
# Based on https://github.com/actions/cache/blob/main/examples.md#python---pip
35+
- name: Install python
36+
if: ${{ ! inputs.use_conda }}
37+
uses: actions/setup-python@v2
38+
with:
39+
python-version: '3.13.2' # needs to be coordinated with version in python/conda_env_ctsm_py.txt
40+
- name: Cache pip
41+
if: ${{ ! inputs.use_conda }}
42+
uses: actions/cache@v3
43+
with:
44+
path: ~/.cache/pip
45+
key: ${{ runner.os }}-pip-${{ hashFiles('doc/ctsm-docs_container/requirements.txt') }}
46+
restore-keys: |
47+
${{ runner.os }}-pip-
48+
- name: Install Python requirements
49+
if: ${{ ! inputs.use_conda }}
50+
run: |
51+
pip install -r doc/ctsm-docs_container/requirements.txt
52+
53+
# Do this if using conda
54+
- name: Set up conda environment
55+
if: ${{ inputs.use_conda }}
56+
uses: conda-incubator/setup-miniconda@v3
57+
with:
58+
activate-environment: ${{ inputs.conda_env_name }}
59+
environment-file: ${{ inputs.conda_env_file }}
60+
channels: conda-forge
61+
auto-activate-base: false
62+
63+
- name: Build Sphinx docs with makefile
64+
run: |
65+
if ${{ inputs.use_conda }}; then
66+
conda run -n ${{ inputs.conda_env_name }} make SPHINXOPTS="-W --keep-going" BUILDDIR=${PWD}/_build -C doc/ html
67+
else
68+
make SPHINXOPTS="-W --keep-going" BUILDDIR=${PWD}/_build -C doc/ html
69+
fi
70+
71+
- name: Build Sphinx docs with doc-builder
72+
if: success() || failure()
73+
run: |
74+
if ${{ inputs.use_conda }}; then
75+
cd doc && conda run -n ${{ inputs.conda_env_name }} ./build_docs -b ${PWD}/_build -c
76+
else
77+
cd doc && ./build_docs -b ${PWD}/_build -c
78+
fi
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
title: Scheduled ctsm_pylib docs build test failed
3+
assignees: samsrabin
4+
labels: bug, next
5+
---
6+
{{ date }}: A failure occurred during the most recent run of the `test-build-docs-ctsm_pylib` job in `.github/workflows/docs-ctsm_pylib.yml`.
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
name: Test building docs with ctsm_pylib
2+
3+
on:
4+
push:
5+
paths:
6+
- 'python/conda_env_ctsm_py.txt'
7+
8+
pull_request:
9+
paths:
10+
- 'python/conda_env_ctsm_py.txt'
11+
12+
schedule:
13+
# 8 am every Monday UTC
14+
- cron: '0 8 * * 1'
15+
16+
workflow_dispatch:
17+
18+
permissions:
19+
contents: read
20+
jobs:
21+
test-build-docs-ctsm_pylib:
22+
if: ${{ always() }}
23+
name: With ctsm_pylib
24+
uses: ./.github/workflows/docs-common.yml
25+
with:
26+
use_conda: true
27+
conda_env_file: python/conda_env_ctsm_py.yml
28+
conda_env_name: ctsm_pylib
29+
30+
# File an issue if the docs build failed during a scheduled run
31+
file-issue-on-failure:
32+
if: |
33+
failure() &&
34+
github.event_name == 'schedule'
35+
needs: test-build-docs-ctsm_pylib
36+
runs-on: ubuntu-latest
37+
steps:
38+
- uses: actions/checkout@v3
39+
40+
- name: Create issue
41+
uses: JasonEtco/create-an-issue@1b14a70e4d8dc185e5cc76d3bec9eab20257b2c5
42+
env:
43+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
44+
with:
45+
filename: .github/workflows/docs-ctsm_pylib.issue_template.md
46+
update_existing: true
47+
search_existing: open
48+
49+

.github/workflows/docs.yml

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
name: Test building docs when they're updated
2+
# Does not include a test of building docs with ctsm_pylib; that's in a different Workflow because we only want it to run when ctsm_pylib is updated.
3+
4+
on:
5+
push:
6+
paths:
7+
- 'doc/**'
8+
9+
pull_request:
10+
paths:
11+
- 'doc/**'
12+
13+
workflow_dispatch:
14+
15+
permissions:
16+
contents: read
17+
jobs:
18+
19+
test-build-docs:
20+
if: ${{ always() }}
21+
name: Without ctsm_pylib or container
22+
uses: ./.github/workflows/docs-common.yml
23+
with:
24+
use_conda: false
25+
26+
test-build-docs-container:
27+
if: ${{ always() }}
28+
name: With container from registry
29+
runs-on: ubuntu-latest
30+
steps:
31+
32+
- name: Checkout repository
33+
uses: actions/checkout@v4
34+
35+
- name: Checkout doc-builder external
36+
run: |
37+
bin/git-fleximod update doc-builder
38+
39+
- name: Build docs using container
40+
id: build-docs
41+
run: |
42+
cd doc && ./build_docs -b ${PWD}/_build -c -d

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,3 +110,7 @@ core.*
110110
*.log !run.log
111111
*.pyc
112112
Depends
113+
114+
# Docs build output
115+
_build*/
116+

.gitmodules

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ fxDONOTUSEurl = https://github.com/ESMCI/mpi-serial
124124
[submodule "doc-builder"]
125125
path = doc/doc-builder
126126
url = https://github.com/ESMCI/doc-builder
127-
fxtag = v1.0.8
127+
fxtag = v2.0.0
128128
fxrequired = ToplevelOptional
129129
# Standard Fork to compare to with "git fleximod test" to ensure personal forks aren't committed
130130
fxDONOTUSEurl = https://github.com/ESMCI/doc-builder

doc/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ help:
1717
# have configured this repository (via an .lfsconfig file at the top level) to NOT
1818
# automatically fetch any of the large files when cloning / fetching.
1919
fetch-images:
20-
git lfs install
20+
git lfs install --force
2121
git lfs pull --exclude="" --include=""
2222

2323
.PHONY: help fetch-images Makefile

0 commit comments

Comments
 (0)