Skip to content

Commit 2710953

Browse files
committed
Automatically run setup steps based on environment kinds
1 parent 9afedf9 commit 2710953

3 files changed

Lines changed: 197 additions & 11 deletions

File tree

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ A GitHub Action to run a Calkit project's pipeline and optionally save results
77

88
The example workflow below shows how to run a Calkit project, saving results.
99
Note the permissions, concurrency, and checkout options.
10+
The action detects required environment kinds from `calkit.yaml` and sets up
11+
needed tooling (for example Calkit via `uv`, Julia, Pixi, Conda, R, MATLAB,
12+
and Docker Buildx) before running.
1013

1114
<!-- Do not edit the snippet below since it is automatically populated -->
1215
<!-- snippet:example.yml:start -->
@@ -44,10 +47,7 @@ jobs:
4447
run: |
4548
git config user.name github-actions[bot]
4649
git config user.email 41898282+github-actions[bot]@users.noreply.github.com
47-
- name: Setup uv
48-
uses: astral-sh/setup-uv@v5
49-
- name: Install Calkit
50-
run: uv tool install calkit-python
50+
# Calkit automatically runs necessary setup actions based on environments
5151
- name: Run Calkit
5252
uses: calkit/run-action@v2
5353
```

action.yml

Lines changed: 192 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ inputs:
1010
description: Whether or not to save (commit and push) results to Git and DVC remotes.
1111
default: "true"
1212
dvc_token:
13-
description: DVC token for pushing results. If not provided, will be obtained
13+
description:
14+
DVC token for pushing results. If not provided, will be obtained
1415
via GitHub OIDC.
1516
required: false
1617
pull_dvc:
@@ -29,17 +30,201 @@ outputs: {}
2930
runs:
3031
using: composite
3132
steps:
33+
- name: Detect setup requirements
34+
id: detect
35+
shell: bash
36+
run: |
37+
set -euo pipefail
38+
39+
has_kind() {
40+
local kind="$1"
41+
grep -Eiq "^[[:space:]]*kind:[[:space:]]*[\"']?${kind}([\"']?[[:space:]#]|$)" calkit.yaml
42+
}
43+
44+
if command -v calkit >/dev/null 2>&1; then
45+
calkit_missing=false
46+
else
47+
calkit_missing=true
48+
fi
49+
echo "calkit_missing=${calkit_missing}" >> "$GITHUB_OUTPUT"
50+
51+
if command -v uv >/dev/null 2>&1; then
52+
uv_missing=false
53+
else
54+
uv_missing=true
55+
fi
56+
echo "uv_missing=${uv_missing}" >> "$GITHUB_OUTPUT"
57+
58+
if command -v python >/dev/null 2>&1 || command -v python3 >/dev/null 2>&1; then
59+
python_missing=false
60+
else
61+
python_missing=true
62+
fi
63+
64+
if command -v conda >/dev/null 2>&1; then
65+
conda_missing=false
66+
else
67+
conda_missing=true
68+
fi
69+
70+
if command -v pixi >/dev/null 2>&1; then
71+
pixi_missing=false
72+
else
73+
pixi_missing=true
74+
fi
75+
76+
if command -v julia >/dev/null 2>&1; then
77+
julia_missing=false
78+
else
79+
julia_missing=true
80+
fi
81+
82+
if command -v Rscript >/dev/null 2>&1 || command -v R >/dev/null 2>&1; then
83+
r_missing=false
84+
else
85+
r_missing=true
86+
fi
87+
88+
if command -v matlab >/dev/null 2>&1; then
89+
matlab_missing=false
90+
else
91+
matlab_missing=true
92+
fi
93+
94+
if command -v docker >/dev/null 2>&1 && docker buildx version >/dev/null 2>&1; then
95+
docker_buildx_missing=false
96+
else
97+
docker_buildx_missing=true
98+
fi
99+
100+
needs_python=false
101+
needs_conda=false
102+
needs_pixi=false
103+
needs_julia=false
104+
needs_r=false
105+
needs_matlab=false
106+
needs_docker=false
107+
unsupported_kinds=""
108+
109+
if [ -f calkit.yaml ]; then
110+
if has_kind "uv-venv" || has_kind "venv"; then
111+
if [ "$python_missing" = true ]; then
112+
needs_python=true
113+
fi
114+
fi
115+
if has_kind "conda"; then
116+
if [ "$conda_missing" = true ]; then
117+
needs_conda=true
118+
fi
119+
if [ "$python_missing" = true ]; then
120+
needs_python=true
121+
fi
122+
fi
123+
if has_kind "pixi"; then
124+
if [ "$pixi_missing" = true ]; then
125+
needs_pixi=true
126+
fi
127+
fi
128+
if has_kind "julia"; then
129+
if [ "$julia_missing" = true ]; then
130+
needs_julia=true
131+
fi
132+
fi
133+
if has_kind "renv"; then
134+
if [ "$r_missing" = true ]; then
135+
needs_r=true
136+
fi
137+
fi
138+
if has_kind "matlab"; then
139+
if [ "$matlab_missing" = true ]; then
140+
needs_matlab=true
141+
fi
142+
fi
143+
if has_kind "docker"; then
144+
if [ "$docker_buildx_missing" = true ]; then
145+
needs_docker=true
146+
fi
147+
fi
148+
149+
# These kinds do not have a direct setup action in this composite action.
150+
if has_kind "ssh"; then unsupported_kinds="${unsupported_kinds}ssh,"; fi
151+
if has_kind "slurm"; then unsupported_kinds="${unsupported_kinds}slurm,"; fi
152+
unsupported_kinds="${unsupported_kinds%,}"
153+
fi
154+
155+
echo "needs_python=${needs_python}" >> "$GITHUB_OUTPUT"
156+
echo "needs_conda=${needs_conda}" >> "$GITHUB_OUTPUT"
157+
echo "needs_pixi=${needs_pixi}" >> "$GITHUB_OUTPUT"
158+
echo "needs_julia=${needs_julia}" >> "$GITHUB_OUTPUT"
159+
echo "needs_r=${needs_r}" >> "$GITHUB_OUTPUT"
160+
echo "needs_matlab=${needs_matlab}" >> "$GITHUB_OUTPUT"
161+
echo "needs_docker=${needs_docker}" >> "$GITHUB_OUTPUT"
162+
echo "unsupported_kinds=${unsupported_kinds}" >> "$GITHUB_OUTPUT"
163+
164+
- name: Setup uv
165+
if: ${{ steps.detect.outputs.calkit_missing == 'true' && steps.detect.outputs.uv_missing == 'true' }}
166+
uses: astral-sh/setup-uv@v5
167+
168+
- name: Install Calkit
169+
if: ${{ steps.detect.outputs.calkit_missing == 'true' }}
170+
shell: bash
171+
run: |
172+
uv tool install calkit-python
173+
echo "$HOME/.local/bin" >> "$GITHUB_PATH"
174+
175+
- name: Setup Python
176+
if: ${{ steps.detect.outputs.needs_python == 'true' }}
177+
uses: actions/setup-python@v5
178+
with:
179+
python-version: "3.x"
180+
181+
- name: Setup Miniconda
182+
if: ${{ steps.detect.outputs.needs_conda == 'true' }}
183+
uses: conda-incubator/setup-miniconda@v3
184+
with:
185+
auto-activate-base: true
186+
187+
- name: Setup Pixi
188+
if: ${{ steps.detect.outputs.needs_pixi == 'true' }}
189+
uses: prefix-dev/setup-pixi@v0
190+
191+
- name: Setup Julia
192+
if: ${{ steps.detect.outputs.needs_julia == 'true' }}
193+
uses: julia-actions/setup-julia@v2
194+
with:
195+
version: "1"
196+
197+
- name: Setup R
198+
if: ${{ steps.detect.outputs.needs_r == 'true' }}
199+
uses: r-lib/actions/setup-r@v2
200+
201+
- name: Setup MATLAB
202+
if: ${{ steps.detect.outputs.needs_matlab == 'true' }}
203+
uses: matlab-actions/setup-matlab@v2
204+
205+
- name: Setup Docker Buildx
206+
if: ${{ steps.detect.outputs.needs_docker == 'true' }}
207+
uses: docker/setup-buildx-action@v3
208+
209+
- name: Report unsupported environment kinds
210+
if: ${{ steps.detect.outputs.unsupported_kinds != '' }}
211+
shell: bash
212+
run: |
213+
echo "::notice::Detected environment kinds without explicit setup action: ${{ steps.detect.outputs.unsupported_kinds }}"
214+
32215
- name: Restore DVC cache for current branch
33216
if: ${{ inputs.cache_dvc == 'true' }}
34217
id: cache-dvc-restore
35218
uses: actions/cache/restore@v5
36219
with:
37220
path: .dvc/cache
38-
key: ${{ runner.os }}-dvc-cache-${{ github.head_ref || github.ref_name }}-${{
221+
key:
222+
${{ runner.os }}-dvc-cache-${{ github.head_ref || github.ref_name }}-${{
39223
github.sha }}
40224
restore-keys: |
41225
${{ runner.os }}-dvc-cache-${{ github.head_ref || github.ref_name }}-
42226
${{ runner.os }}-dvc-cache-${{ github.event.repository.default_branch }}-
227+
43228
- name: Get GitHub OIDC token
44229
if: ${{ !inputs.dvc_token && (inputs.save == 'true' || inputs.pull_dvc ==
45230
'true') }}
@@ -53,6 +238,7 @@ runs:
53238
fi
54239
echo "::add-mask::$OIDC_TOKEN"
55240
echo "oidc-token=$OIDC_TOKEN" >> $GITHUB_OUTPUT
241+
56242
- name: Exchange OIDC token for Calkit token
57243
if: ${{ !inputs.dvc_token && (inputs.save == 'true' || inputs.pull_dvc ==
58244
'true') }}
@@ -68,6 +254,7 @@ runs:
68254
fi
69255
echo "::add-mask::$CALKIT_TOKEN"
70256
echo "calkit-token=$CALKIT_TOKEN" >> $GITHUB_OUTPUT
257+
71258
- run: calkit config remote-auth
72259
if: ${{ inputs.save == 'true' || inputs.pull_dvc == 'true' }}
73260
shell: bash
@@ -86,11 +273,13 @@ runs:
86273
env:
87274
CALKIT_TOKEN: ${{ inputs.dvc_token || steps.get-calkit-token.outputs.calkit-token }}
88275
CALKIT_DVC_TOKEN: ${{ inputs.dvc_token || steps.get-calkit-token.outputs.calkit-token }}
276+
89277
- name: Save DVC cache
90278
if: ${{ inputs.cache_dvc == 'true' }}
91279
id: cache-dvc-save
92280
uses: actions/cache/save@v5
93281
with:
94282
path: .dvc/cache
95-
key: ${{ runner.os }}-dvc-cache-${{ github.head_ref || github.ref_name }}-${{
283+
key:
284+
${{ runner.os }}-dvc-cache-${{ github.head_ref || github.ref_name }}-${{
96285
github.sha }}

example.yml

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,6 @@ jobs:
3131
run: |
3232
git config user.name github-actions[bot]
3333
git config user.email 41898282+github-actions[bot]@users.noreply.github.com
34-
- name: Setup uv
35-
uses: astral-sh/setup-uv@v5
36-
- name: Install Calkit
37-
run: uv tool install calkit-python
34+
# Calkit automatically runs necessary setup actions based on environments
3835
- name: Run Calkit
3936
uses: calkit/run-action@v2

0 commit comments

Comments
 (0)