-
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathaction.yml
More file actions
216 lines (199 loc) · 9.61 KB
/
Copy pathaction.yml
File metadata and controls
216 lines (199 loc) · 9.61 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
name: 'Setup Environment'
description: 'Flexible environment setup - auto-detects container or installs Conda and LaTeX'
author: 'QuantEcon'
inputs:
python-version:
description: 'Python version to use (ignored in container mode)'
required: false
default: '3.13'
environment:
description: 'Path to environment.yml for full environment (non-container builds)'
required: false
default: 'environment.yml'
environment-update:
description: 'Path to delta environment.yml for container builds (empty = use pre-installed packages only)'
required: false
default: ''
environment-name:
description: 'Conda environment name (must match name in environment.yml)'
required: false
default: 'quantecon'
cache-version:
description: 'Cache version for manual invalidation of the standard-mode Conda env cache (bump to force a rebuild). No effect in container mode, which uses the pre-installed environment and has no Conda cache.'
required: false
default: 'v1'
install-latex:
description: 'Whether to install LaTeX packages (auto-disabled in container mode)'
required: false
default: 'false'
latex-requirements-file:
description: 'Path to latex-requirements.txt file listing packages to install'
required: false
default: 'latex-requirements.txt'
outputs:
container-mode:
description: 'Whether running in container mode'
value: ${{ steps.detect-container.outputs.container-mode }}
conda-cache-hit:
description: 'Whether conda cache was hit (standard mode only, always false in container mode)'
value: ${{ steps.conda-cache.outputs.cache-hit }}
runs:
using: "composite"
steps:
# Detect if running inside QuantEcon container
- name: Detect container environment
id: detect-container
shell: bash
run: |
if [ -f "/etc/quantecon-container" ]; then
echo "🐳 Running inside QuantEcon container"
echo "container-mode=true" >> $GITHUB_OUTPUT
cat /etc/quantecon-container
else
echo "📦 Running on standard runner (non-container mode)"
echo "container-mode=false" >> $GITHUB_OUTPUT
fi
# ============================================================
# CONTAINER MODE: Only install delta packages from environment.yml
# Note: Conda environment caching is disabled in container mode because
# the Conda env lives outside the workspace mount, so actions/cache
# cannot persist it. Other host-mounted paths (e.g., pip cache) may
# still be cached.
# See: https://github.com/QuantEcon/actions/issues/18
# ============================================================
- name: Update environment (container mode)
if: steps.detect-container.outputs.container-mode == 'true' && inputs.environment-update != ''
shell: bash
run: |
echo "::group::Environment Update (Container Mode)"
echo "📦 Action: Installing delta packages from ${{ inputs.environment-update }}"
if [ -f "${{ inputs.environment-update }}" ]; then
echo "Running: conda env update -f ${{ inputs.environment-update }}"
conda env update -f ${{ inputs.environment-update }}
echo "✅ Environment updated successfully"
else
echo "::error::Environment update file not found: ${{ inputs.environment-update }}"
exit 1
fi
echo "::endgroup::"
- name: Skip environment update (container mode)
if: steps.detect-container.outputs.container-mode == 'true' && inputs.environment-update == ''
shell: bash
run: |
echo "::group::Environment Setup (Container Mode)"
echo "🐳 Action: Using pre-installed container packages"
echo "ℹ️ No environment-update file specified - skipping conda env update"
echo "✅ Ready to build (fastest path)"
echo "::endgroup::"
# ============================================================
# NON-CONTAINER MODE: Full installation (existing behavior)
# ============================================================
- name: Validate environment file (non-container mode)
if: steps.detect-container.outputs.container-mode == 'false'
shell: bash
run: |
if [ ! -f "${{ inputs.environment }}" ]; then
echo "::error::Environment file not found: ${{ inputs.environment }} (required in standard / non-container mode)"
exit 1
fi
- name: Setup Miniconda (non-container mode)
if: steps.detect-container.outputs.container-mode == 'false'
uses: conda-incubator/setup-miniconda@8ee1f361103df19b6f8c8655fd3967a8ecb162d5 # v4.0.1
with:
# No environment-file here: the env is restored from cache (hit) or
# created by the "Create/update environment" step below (miss), so a
# cache hit is not wastefully rebuilt. Uses the runner's pre-installed
# conda (kept current by auto-update-conda) so the cached env lives at
# a stable ${CONDA}/envs/<environment-name> path.
auto-update-conda: true
auto-activate-base: true
python-version: ${{ inputs.python-version }}
activate-environment: ${{ inputs.environment-name }}
# Cache the named env directory, NOT ${CONDA}/envs: the envs parent is
# root-owned on hosted runners, and tar cannot restore its mode/mtime as
# the runner user — the restore dies with "Cannot utime/chmod: Operation
# not permitted" and actions/cache reports a miss, so a cache rooted at
# envs/ can be saved but never restored. The env dir itself is created by
# (and owned by) the runner user, so it round-trips cleanly.
- name: Cache Conda environment (non-container mode)
if: steps.detect-container.outputs.container-mode == 'false'
uses: actions/cache@v6
id: conda-cache
with:
path: ${{ env.CONDA }}/envs/${{ inputs.environment-name }}
key: conda-${{ runner.os }}-${{ inputs.environment-name }}-py${{ inputs.python-version }}-${{ hashFiles(inputs.environment) }}-${{ inputs.cache-version }}
restore-keys: |
conda-${{ runner.os }}-${{ inputs.environment-name }}-py${{ inputs.python-version }}-${{ hashFiles(inputs.environment) }}-
conda-${{ runner.os }}-${{ inputs.environment-name }}-py${{ inputs.python-version }}-
- name: Create/update environment (non-container mode, no exact cache hit)
if: steps.detect-container.outputs.container-mode == 'false' && steps.conda-cache.outputs.cache-hit != 'true'
shell: bash -l {0}
# Runs on a true cache miss OR a restore-keys partial match (cache-hit is
# exact-only). --prune removes deps dropped from environment.yml when
# updating an older restored env.
run: conda env update -n ${{ inputs.environment-name }} -f ${{ inputs.environment }} --prune
- name: Install LaTeX packages (non-container mode)
if: steps.detect-container.outputs.container-mode == 'false' && inputs.install-latex == 'true'
shell: bash
run: |
if [ -f "${{ inputs.latex-requirements-file }}" ]; then
echo "Reading packages from ${{ inputs.latex-requirements-file }}"
PACKAGES=$(grep -v '^#' "${{ inputs.latex-requirements-file }}" | grep -v '^[[:space:]]*$' | tr '\n' ' ')
echo "Installing LaTeX packages: $PACKAGES"
sudo apt-get update
sudo apt-get install -y $PACKAGES
else
echo "::error::install-latex is true but no LaTeX requirements file was found at ${{ inputs.latex-requirements-file }}"
exit 1
fi
# ============================================================
# SUMMARY: Display environment info
# ============================================================
- name: Display Environment Info
# Use plain bash to avoid login shell PATH reset in containers
# (Ubuntu's /etc/profile can drop /opt/conda from PATH)
shell: bash
run: |
echo "::group::Environment Setup Summary"
if [ "${{ steps.detect-container.outputs.container-mode }}" == "true" ]; then
# Detect actual container image from marker file
if [ -f /etc/quantecon-container ]; then
CONTAINER_IMAGE=$(grep '^image=' /etc/quantecon-container | head -n 1 | cut -d'=' -f2-)
if [ -z "$CONTAINER_IMAGE" ]; then
CONTAINER_IMAGE="QuantEcon container"
fi
else
CONTAINER_IMAGE="QuantEcon container"
fi
echo "🐳 Mode: Container ($CONTAINER_IMAGE)"
echo " LaTeX: Pre-installed ✅"
echo " Python: Pre-installed ✅"
echo " Base packages: Pre-installed ✅"
if [ -n "${{ inputs.environment-update }}" ]; then
echo " Environment update: Applied from ${{ inputs.environment-update }}"
else
echo " Environment update: Skipped (using pre-installed packages)"
fi
else
echo "📦 Mode: Standard runner"
if [ "${{ steps.conda-cache.outputs.cache-hit }}" == "true" ]; then
echo " Conda: Restored from cache ✅ (saved ~5-6 minutes)"
else
echo " Conda: Installed fresh"
fi
if [ "${{ inputs.install-latex }}" == "true" ]; then
echo " LaTeX: Installed"
else
echo " LaTeX: Skipped"
fi
fi
echo "::endgroup::"
echo "::group::Python packages"
pip list 2>/dev/null || conda list
echo "::endgroup::"
echo "::group::LaTeX version"
pdflatex --version 2>/dev/null || echo "pdfLaTeX not in PATH"
echo "::endgroup::"
branding:
icon: 'package'
color: 'blue'