Skip to content

Commit 0b8b976

Browse files
committed
feat: setup action to use clinder
1 parent c2a9590 commit 0b8b976

8 files changed

Lines changed: 176 additions & 433 deletions

File tree

.github/workflows/build-book.yaml

Lines changed: 43 additions & 232 deletions
Original file line numberDiff line numberDiff line change
@@ -2,92 +2,6 @@ name: build-book
22

33
on:
44
workflow_call:
5-
inputs:
6-
environment_name:
7-
description: 'Name of conda environment to activate (NO LONGER USED)'
8-
required: false
9-
default: 'cookbook-dev'
10-
type: string
11-
environment_file:
12-
description: 'Name of conda environment file'
13-
required: false
14-
default: 'environment.yml'
15-
type: string
16-
path_to_notebooks:
17-
description: 'Location of the JupyterBook source relative to repo root'
18-
required: false
19-
default: '.'
20-
type: string
21-
artifact_name:
22-
description: 'The name to assign to the built book artifact.'
23-
required: false
24-
default: 'book-zip'
25-
type: string
26-
build_command:
27-
description: 'The linux command to build the book or site.'
28-
required: false
29-
default: 'myst build --execute --html'
30-
type: string
31-
output_path:
32-
description: 'Path to the built html content relative to `path_to_notebooks`'
33-
required: false
34-
default: '_build/html'
35-
type: string
36-
build_from_code_artifact:
37-
description: 'Should we try to build from a previously uploaded code artifact?'
38-
required: false
39-
default: 'false'
40-
type: string
41-
code_artifact_name:
42-
description: 'Name of zipped artifact passed in, instead of checking out the repository.'
43-
required: false
44-
default: 'code-zip'
45-
type: string
46-
workflow:
47-
description: 'Identify the workflow that produced the artifact'
48-
required: false
49-
default: trigger-book-build.yaml
50-
type: string
51-
workflow_conclusion:
52-
description: 'Workflow conclusion (options: "failure", "success", "neutral", "cancelled", "skipped", "timed_out", "action_required") or status (options: "completed", "in_progress", "queued") to search for. Use the empty string ("") to ignore status or conclusion in the search.'
53-
required: false
54-
default: success
55-
type: string
56-
base_url:
57-
description: 'Determines where the website is served from, including CSS & JS assets (needed for MyST)'
58-
required: false
59-
default: '/${{ github.event.repository.name }}'
60-
type: string
61-
62-
secrets:
63-
PRIVATE_KEY:
64-
description: 'Google analytics key needed for metrics page on portal site'
65-
required: false
66-
PRIVATE_KEY_ID:
67-
description: 'Google analytics key id needed for metrics page on portal site'
68-
required: false
69-
ARM_USERNAME:
70-
description: 'Username for the ARM Data Discovery portal (https://adc.arm.gov/armlive/)'
71-
required: false
72-
ARM_PASSWORD:
73-
description: 'Password for the ARM Data Discovery portal (https://adc.arm.gov/armlive/)'
74-
required: false
75-
AQS_USERNAME:
76-
description: 'Username for the AQS Data Portal'
77-
required: false
78-
AQS_KEY:
79-
description: 'Key for the AQS Data Portal'
80-
required: false
81-
EARTHDATA_USERNAME:
82-
description: 'NASA Earthdata API Username'
83-
required: false
84-
EARTHDATA_PASSWORD:
85-
description: 'NASA Earthdata API Password'
86-
required: false
87-
88-
env:
89-
# the BASE_URL environment variable needs to be set if building with myst
90-
BASE_URL: ${{ inputs.base_url }}
915

926
jobs:
937
build:
@@ -96,172 +10,69 @@ jobs:
9610
run:
9711
shell: bash -leo pipefail {0}
9812
steps:
99-
- name: Checkout the code from the repo
100-
if: inputs.build_from_code_artifact == 'false'
101-
uses: actions/checkout@v6
102-
103-
# The next two steps should replicated checking out the code
104-
- name: Download code artifact
105-
id: get_code_artifact
106-
if: inputs.build_from_code_artifact == 'true'
107-
uses: dawidd6/action-download-artifact@v14
108-
with:
109-
github_token: ${{ secrets.GITHUB_TOKEN }}
110-
workflow: ${{ inputs.workflow }}
111-
run_id: ${{ github.event.workflow_run.id }}
112-
name: ${{ inputs.code_artifact_name }}
113-
workflow_conclusion: ${{ inputs.workflow_conclusion }}
114-
115-
- name: Unzip the code
116-
if: inputs.build_from_code_artifact == 'true'
117-
run: |
118-
unzip pr_code.zip
119-
rm -f pr_code.zip
120-
121-
- name: Get GitHub environment variables
122-
id: get-env
123-
uses: FranzDiebold/github-env-vars-action@v2
124-
125-
- name: Check for config file
126-
id: check_config
127-
uses: andstor/file-existence-action@v3
128-
with:
129-
files: "${{ inputs.path_to_notebooks }}/_config.yml"
130-
131-
- name: Parse config file
132-
id: parse_config
133-
if: steps.check_config.outputs.files_exists == 'true'
134-
uses: CumulusDS/get-yaml-paths-action@v1.0.2
135-
with:
136-
file: ${{ inputs.path_to_notebooks }}/_config.yml
137-
execute_notebooks: execute.execute_notebooks
138-
binderhub_url: sphinx.config.html_theme_options.launch_buttons.binderhub_url
139-
timeout: execute.timeout
140-
141-
- name: Echo values from config file
142-
if: steps.check_config.outputs.files_exists == 'true'
143-
run: |
144-
echo ${{ steps.parse_config.outputs.execute_notebooks }}
145-
echo ${{ steps.parse_config.outputs.binderhub_url }}
146-
echo ${{ steps.parse_config.outputs.timeout }}
147-
13+
- uses: actions/checkout@v6
14814
- name: Test for environment change
14915
id: env_change
15016
uses: tj-actions/changed-files@v47
15117
with:
152-
files: ${{ inputs.environment_file }}
18+
files: environment.yml
15319

15420
- name: Echo environment change test result
15521
run: |
15622
echo '(DEBUG) The value of steps.env_change.outputs.any_changed is:'
15723
echo ${{ steps.env_change.outputs.any_changed }}
158-
24+
15925
- name: Setup environment with micromamba
16026
uses: mamba-org/setup-micromamba@v2
16127
with:
162-
environment-file: ${{ inputs.environment_file }}
163-
164-
- name: Create book build environment
165-
if: |
166-
(inputs.use_cached_environment != 'true'
167-
|| steps.cache.outputs.cache-hit != 'true')
168-
&& steps.parse_config.outputs.execute_notebooks == 'binder'
169-
run: |
170-
conda install -c conda-forge jupyter-book pip
171-
conda install sphinx-pythia-theme
172-
pip install git+https://github.com/pangeo-gallery/binderbot.git
173-
conda list
174-
175-
- name: Get paths to notebook files
176-
if: |
177-
steps.parse_config.outputs.execute_notebooks == 'binder'
178-
# This will find ALL *.ipynb files in the repo
179-
# It would be better to cross-check this against the _toc.yml file
180-
# to avoid unneccesary execution of notebooks that aren't included in the book
181-
shell: python
182-
run: |
183-
import glob
184-
notebooks = glob.glob('**/*.ipynb', recursive=True)
185-
outfile = open("notebook_paths", "w")
186-
for path in notebooks:
187-
outfile.write(path + ' ')
188-
outfile.close() # Writing these out to a file because I can't figure out how to set an environment variable from a python script
28+
environment-file: environment.yml
29+
cache-environment: true
18930

190-
- name: Execute notebooks via binderbot using existing image
191-
if: |
192-
( steps.parse_config.outputs.execute_notebooks == 'binder'
193-
&& steps.env_change.outputs.any_changed != 'true' )
194-
env:
195-
ARM_USERNAME: ${{ secrets.ARM_USERNAME }}
196-
ARM_PASSWORD: ${{ secrets.ARM_PASSWORD }}
197-
AQS_USERNAME: ${{ secrets.AQS_USERNAME }}
198-
AQS_KEY: ${{ secrets.AQS_KEY }}
199-
EARTHDATA_USERNAME: ${{ secrets.EARTHDATA_USERNAME }}
200-
EARTHDATA_PASSWORD: ${{ secrets.EARTHDATA_PASSWORD }}
31+
- name: Check for myst.yml tags
32+
id: myst-tags
20133
run: |
202-
NOTEBOOKS=$(cat notebook_paths)
203-
echo 'Retrieved binder_url: ${{ steps.parse_config.outputs.binderhub_url }}'
204-
echo "We will now execute these notebooks: $NOTEBOOKS"
205-
echo "using the existing binder image from the main branch"
206-
python -m binderbot.cli --binder-url ${{ steps.parse_config.outputs.binderhub_url }} --repo ${{ github.repository }} --ref main --nb-timeout ${{ steps.parse_config.outputs.timeout }} $NOTEBOOKS --pass-env-var ARM_USERNAME --pass-env-var ARM_PASSWORD
34+
yq '.project.tags | filter(test("^cookbook:"))[] | sub("cookbook:(.*)","$1=1")' myst.yml | tee "$GITHUB_OUTPUT"
20735
208-
- name: Execute notebooks via binderbot using new image with latest environment
209-
if: |
210-
( steps.parse_config.outputs.execute_notebooks == 'binder'
211-
&& steps.env_change.outputs.any_changed == 'true' )
212-
env:
213-
ARM_USERNAME: ${{ secrets.ARM_USERNAME }}
214-
ARM_PASSWORD: ${{ secrets.ARM_PASSWORD }}
215-
AQS_USERNAME: ${{ secrets.AQS_USERNAME }}
216-
AQS_KEY: ${{ secrets.AQS_KEY }}
217-
EARTHDATA_USERNAME: ${{ secrets.EARTHDATA_USERNAME }}
218-
EARTHDATA_PASSWORD: ${{ secrets.EARTHDATA_PASSWORD }}
219-
run: |
220-
NOTEBOOKS=$(cat notebook_paths)
221-
echo 'Retrieved binder_url: ${{ steps.parse_config.outputs.binderhub_url }}'
222-
echo "We will now execute these notebooks: $NOTEBOOKS"
223-
echo "using the updated environment file in this branch to build a new image"
224-
python -m binderbot.cli --binder-url ${{ steps.parse_config.outputs.binderhub_url }} --repo ${{ github.actor }}/$CI_REPOSITORY_NAME --ref $CI_ACTION_REF_NAME --nb-timeout ${{ steps.parse_config.outputs.timeout }} $NOTEBOOKS --pass-env-var ARM_USERNAME --pass-env-var ARM_PASSWORD
36+
- name: Setup execution environment on a BinderHub
37+
if: steps.myst-tags.outputs.build-on-binder
38+
# This action sets up evironment variables for e.g. mystmd to recognise and use
39+
uses: 2i2c-org/clinder@action-v1
40+
with:
41+
hub-url: https://binder.projectpythia.org/
22542

226-
- name: Disable notebook execution during jupyterbook build
227-
if: |
228-
steps.parse_config.outputs.execute_notebooks == 'binder'
229-
shell: python
230-
run: |
231-
import yaml
232-
with open('${{ inputs.path_to_notebooks }}/_config.yml') as f:
233-
data = yaml.safe_load(f)
234-
data['execute']['execute_notebooks'] = 'off'
235-
with open('${{ inputs.path_to_notebooks }}/_config.yml', 'w') as f:
236-
yaml.dump(data, f)
43+
- name: Cache execution
44+
if: "!steps.myst-tags.outputs.build-on-binder"
45+
uses: actions/cache@v4
46+
with:
47+
path: ${{ inputs.path_to_notebooks }}/_build/execute
48+
key: ${{ runner.os }}-${{ hashFiles(env.ENV_FILE) }}-execution
23749

23850
- name: Build the book
239-
# Assumption is that if execute_notebooks != 'binder' then the _config.yml file must be set to execute notebooks during build
240-
env:
241-
PRIVATE_KEY: ${{ secrets.PRIVATE_KEY }}
242-
PRIVATE_KEY_ID: ${{ secrets.PRIVATE_KEY_ID }}
243-
ARM_USERNAME: ${{ secrets.ARM_USERNAME }}
244-
ARM_PASSWORD: ${{ secrets.ARM_PASSWORD }}
245-
AQS_USERNAME: ${{ secrets.AQS_USERNAME }}
246-
AQS_KEY: ${{ secrets.AQS_KEY }}
247-
EARTHDATA_USERNAME: ${{ secrets.EARTHDATA_USERNAME }}
248-
EARTHDATA_PASSWORD: ${{ secrets.EARTHDATA_PASSWORD }}
249-
SECRETS_VARS: ${{ toJson(secrets) }}
250-
run: |
251-
cd ${{ inputs.path_to_notebooks }}
252-
${{ inputs.build_command }}
253-
254-
- name: Zip the book
25551
run: |
256-
set -x
257-
set -e
258-
if [ -f book.zip ]; then
259-
rm -rf book.zip
52+
# Allow custom build command
53+
if [[ -x "build.sh" ]]; then
54+
./build.sh
55+
else
56+
myst build --execute --site --strict
26057
fi
261-
zip -r book.zip ${{ inputs.path_to_notebooks }}/${{ inputs.output_path }}
26258
263-
- name: Upload zipped book artifact
59+
- name: Upload zipped AST artifact
60+
id: site-artifact
26461
uses: actions/upload-artifact@v6
26562
with:
266-
name: ${{ inputs.artifact_name }}
267-
path: ./book.zip
63+
name: site
64+
path: _build/site/
65+
retention-days: 7
66+
67+
- name: Stash the artifact URL
68+
run: |
69+
# Use env for safer handling.
70+
echo "URL=${{ steps.site-artifact.outputs.artifact-url }}" >> "$GITHUB_ENV"
71+
- name: Display the preview URL
72+
run: |
73+
import urllib.parse, os;
74+
component = urllib.parse.quote_plus(os.environ['URL'])
75+
preview_url = f"https://hub.projectpythia.org/services/jupyterbook-pub/repo/{component}/"
76+
with open(os.environ["GITHUB_STEP_SUMMARY"], "a") as f:
77+
f.write(f"Preview this build at {preview_url}")
78+
shell: python {0}

.github/workflows/delete-preview.yaml

Lines changed: 0 additions & 24 deletions
This file was deleted.

0 commit comments

Comments
 (0)