-
Notifications
You must be signed in to change notification settings - Fork 2
365 lines (342 loc) · 13.5 KB
/
Copy pathcd.yml
File metadata and controls
365 lines (342 loc) · 13.5 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
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
name: CD
on:
push:
tags:
- 'moppy-v*'
workflow_dispatch:
inputs:
version:
description: 'Version to update to (e.g. 2.3.0a9)'
required: false
type: string
jobs:
pypi:
name: build and deploy to PyPI
runs-on: ubuntu-latest
permissions:
id-token: write
outputs:
# Output the version for downstream jobs
version: ${{ steps.get-version.outputs.version }}
steps:
- name: Checkout source
uses: actions/checkout@v7.0.0
with:
submodules: recursive
- name: Set up Python 3.11
uses: actions/setup-python@v6
with:
python-version: 3.11
- name: Install build dependencies
run: python -m pip install build twine
- name: Build distributions
shell: bash -l {0}
run: |
git clean -xdf
pyproject-build
- name: Verify submodule content in distributions
shell: bash -l {0}
run: |
set -euo pipefail
SDIST=$(ls dist/*.tar.gz | head -1)
WHEEL=$(ls dist/*.whl | head -1)
echo "Verifying submodule content in:"
echo " sdist: ${SDIST}"
echo " wheel: ${WHEEL}"
vocab_dirs=(
"CMIP6_CVs"
"CMIP6Plus_CVs"
"cmip7-cmor-tables"
"mip_cmor_tables"
)
for d in "${vocab_dirs[@]}"; do
sdist_count=$(tar -tzf "${SDIST}" | grep -c "access_moppy/vocabularies/${d}/" || true)
wheel_count=$(unzip -l "${WHEEL}" | grep -c "access_moppy/vocabularies/${d}/" || true)
echo "${d}: sdist=${sdist_count}, wheel=${wheel_count}"
if [[ "${sdist_count}" -eq 0 || "${wheel_count}" -eq 0 ]]; then
echo "ERROR: missing ${d} content in built distributions"
exit 1
fi
done
- name: Get version for artifact naming
id: get-version
run: |
VERSION=$(python -c "import versioneer; print(versioneer.get_version())")
VERSION=${VERSION#v}
echo "version=${VERSION}" >> $GITHUB_OUTPUT
echo "Building version: ${VERSION}"
- name: Upload build artifacts
uses: actions/upload-artifact@v7.0.1
with:
name: python-package-distributions-${{ steps.get-version.outputs.version }}
path: dist/
retention-days: 7
- name: Publish package to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
skip-existing: true
conda:
name: build and deploy to conda
needs: pypi
runs-on: ubuntu-latest
# This job uses artifacts from the PyPI job instead of waiting for PyPI propagation
# This makes the build more reliable and faster
steps:
- name: Checkout source
uses: actions/checkout@v7.0.0
with:
submodules: recursive
- name: Download build artifacts from PyPI job
uses: actions/download-artifact@v8
with:
name: python-package-distributions-${{ needs.pypi.outputs.version }}
path: dist/
- name: Verify artifacts
run: |
echo "Downloaded artifacts:"
ls -la dist/
echo "Checking for wheel and sdist files..."
WHEEL=$(ls dist/*.whl 2>/dev/null | head -1)
SDIST=$(ls dist/*.tar.gz 2>/dev/null | head -1)
if [[ -n "$WHEEL" && -n "$SDIST" ]]; then
echo "✅ Both wheel and sdist found in artifacts!"
echo "Wheel: $(basename $WHEEL)"
echo "Sdist: $(basename $SDIST)"
else
echo "❌ Missing wheel or sdist in artifacts"
exit 1
fi
- name: Prepare conda recipe for local build
run: |
echo "Preparing conda recipe to use local source..."
# Create a temporary conda recipe directory to avoid modifying tracked files
mkdir -p .conda-temp
cp -r .conda/* .conda-temp/
cat > .conda-temp/meta.yaml << 'EOF'
{% set data = load_setup_py_data(setup_file='../setup.py', from_recipe_dir=True) %}
{% set version = data.get('version') %}
package:
name: access-moppy-suite
version: "{{ version }}"
source:
path: ../
build:
noarch: python
number: 0
requirements:
host:
- python
- pip
- versioneer
outputs:
- name: access-moppy
build:
noarch: python
script: build_access_moppy.sh
requirements:
host:
- python
- pip
- versioneer
run:
- python >=3.11,<3.14
- numpy
- pandas
- xarray
- netcdf4
- cftime
- dask
- distributed >=2024.0.0
- pyyaml
- tqdm
- requests
- parsl
- jinja2
about:
home: https://github.com/ACCESS-NRI/ACCESS-MOPPy
summary: A Python package for CMORisation of ACCESS model output
license: Apache-2.0
license_file: LICENCE.txt
doc_url: https://access-moppy.readthedocs.io/
dev_url: https://github.com/ACCESS-NRI/ACCESS-MOPPy
- name: access-moppy-esmval
build:
noarch: python
requirements:
run:
- {{ pin_subpackage('access-moppy', exact=True) }}
- esmvalcore >=2.14
about:
home: https://github.com/ACCESS-NRI/ACCESS-MOPPy
summary: ACCESS-MOPPy with ESMValTool integration support
license: Apache-2.0
license_file: LICENCE.txt
doc_url: https://access-moppy.readthedocs.io/
dev_url: https://github.com/ACCESS-NRI/ACCESS-MOPPy
about:
home: https://github.com/ACCESS-NRI/ACCESS-MOPPy
summary: A Python package for CMORisation of ACCESS model output
license: Apache-2.0
license_file: LICENCE.txt
doc_url: https://access-moppy.readthedocs.io/
dev_url: https://github.com/ACCESS-NRI/ACCESS-MOPPy
extra:
recipe-maintainers:
- ACCESS-NRI
EOF
chmod +x .conda-temp/build_access_moppy.sh
echo "Created temporary conda recipe to use local source (path: ../)"
- name: Setup conda environment
uses: conda-incubator/setup-miniconda@v4
with:
miniconda-version: "latest"
python-version: 3.11
auto-update-conda: false
auto-activate-base: true
show-channel-urls: true
- name: Install conda-build tools into base
shell: bash -l {0}
run: conda install -n base -c conda-forge conda-build conda-verify anaconda-client -y
- name: Build conda package
shell: bash -l {0}
run: |
mkdir -p /tmp/conda-output
conda build .conda-temp --no-anaconda-upload --output-folder /tmp/conda-output
echo "Built packages:"
find /tmp/conda-output -type f \( -name "*.conda" -o -name "*.tar.bz2" \)
- name: Upload conda package
shell: bash -l {0}
env:
ANACONDA_API_TOKEN: ${{ secrets.anaconda_token }}
run: |
mapfile -t packages < <(find /tmp/conda-output -type f \( -name "*.conda" -o -name "*.tar.bz2" \))
if [[ ${#packages[@]} -eq 0 ]]; then
echo "❌ No conda packages found to upload"
exit 1
fi
echo "Uploading ${#packages[@]} package(s) to anaconda..."
for package in "${packages[@]}"; do
echo "Uploading: $package"
conda run -n base anaconda upload --user accessnri --label main "$package"
done
echo "✅ All conda packages uploaded successfully"
echo "Version built: ${{ needs.pypi.outputs.version }}"
update_analysis3:
name: Update ACCESS-MOPPy on Analysis3 Conda Environment
needs: [pypi, conda]
runs-on: ubuntu-latest
permissions:
contents: read
env:
ORG: ACCESS-NRI
TARGET_REPO: ACCESS-Analysis-Conda
TARGET_BRANCH: main
ANALYSIS3_DIR: environments/analysis3
PIXI_TOML: environments/analysis3/pixi.toml
PACKAGE: access-moppy-esmval
CHANNEL: accessnri
RELEASE_TAG: ${{ github.ref_name }}
INPUT_VERSION: ${{ github.event.inputs.version }}
GH_TOKEN: ${{ secrets.GH_ANALYSIS3_DEPLOY }}
steps:
- name: Derive version string
id: ver
run: |
if [ -n "${INPUT_VERSION}" ]; then
ver="${INPUT_VERSION}"
elif [ -n "${{ needs.pypi.outputs.version }}" ]; then
# Use version from PyPI job output (more reliable)
ver="${{ needs.pypi.outputs.version }}"
else
# Fallback to parsing tag
tag="${RELEASE_TAG}"
ver="${tag#moppy-}"
ver="${ver#v}"
fi
echo "version=$ver" >> $GITHUB_OUTPUT
echo "Using version: $ver"
- name: Install tooling (jq, gh)
run: |
sudo apt-get update -y
sudo apt-get install -y jq python3-pip
if ! command -v gh >/dev/null; then
curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg |
sudo dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg
sudo chmod go+r /usr/share/keyrings/githubcli-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" |
sudo tee /etc/apt/sources.list.d/github-cli.list >/dev/null
sudo apt-get update -y && sudo apt-get install -y gh
fi
- name: Setup pixi
uses: prefix-dev/setup-pixi@v0.9.6
with:
pixi-version: latest
- name: Wait for conda package to appear in channel
env:
VERSION: ${{ steps.ver.outputs.version }}
run: |
echo "Waiting for ${CHANNEL}::${PACKAGE}==${VERSION} to appear…"
for i in $(seq 1 30); do
if curl -fsSL "https://api.anaconda.org/package/${CHANNEL}/${PACKAGE}" |
jq -e --arg v "$VERSION" '.files[] | select(.version == $v) | .version' >/dev/null; then
echo "Found ${PACKAGE} ${VERSION} in channel ${CHANNEL}."
exit 0
fi
echo "Not yet available. Retry $i/30…"
sleep 60
done
echo "Timed out waiting for ${CHANNEL}::${PACKAGE}==${VERSION}."
exit 1
- name: Clone Repo B
run: |
git clone "https://x-access-token:${GH_TOKEN}@github.com/${ORG}/${TARGET_REPO}.git"
cd "${TARGET_REPO}"
git config user.name "access-bot"
git config user.email "access-bot@users.noreply.github.com"
- name: Create branch and update Analysis3 environment files
id: edit
working-directory: ${{ env.TARGET_REPO }}
env:
VERSION: ${{ steps.ver.outputs.version }}
run: |
BRANCH="update/access-moppy-${VERSION}"
git fetch origin "${TARGET_BRANCH}"
if git ls-remote --exit-code --heads origin "$BRANCH" >/dev/null; then
git checkout -B "$BRANCH" "origin/$BRANCH"
else
git checkout -b "$BRANCH" "origin/${TARGET_BRANCH}"
fi
if ! grep -q '^access-moppy-esmval[[:space:]]*=' "${PIXI_TOML}"; then
echo "ERROR: Could not find access-moppy-esmval dependency in ${PIXI_TOML}" >&2
exit 1
fi
sed -i -E 's|^(access-moppy-esmval[[:space:]]*=[[:space:]]*\{[[:space:]]*version[[:space:]]*=[[:space:]]*")[^"]+(".*)$|\1=='"${VERSION}"'\2|' "${PIXI_TOML}"
pushd "${ANALYSIS3_DIR}"
pixi lock
pixi run rebuild-env
rm -f environment.yml.bak
popd
git add "${ANALYSIS3_DIR}/pixi.toml" "${ANALYSIS3_DIR}/pixi.lock" "${ANALYSIS3_DIR}/solved.json" "${ANALYSIS3_DIR}/environment.yml"
if git diff --cached --quiet; then
echo "changed=false" >> $GITHUB_OUTPUT
echo "No changes to commit."
else
git commit -m "analysis3: bump access-moppy to ${VERSION}"
git push -u origin "$BRANCH"
echo "changed=true" >> $GITHUB_OUTPUT
echo "$BRANCH" > ../branch.txt
- name: Create PR (idempotent)
if: steps.edit.outputs.changed == 'true'
working-directory: ${{ env.TARGET_REPO }}
env:
VERSION: ${{ steps.ver.outputs.version }}
run: |
BRANCH="$(cat ../branch.txt)"
if ! gh pr view "$BRANCH" --json number >/dev/null 2>&1; then
gh pr create \
--base "${TARGET_BRANCH}" \
--head "${BRANCH}" \
--title "Bump access-moppy to ${VERSION} in analysis3 env" \
--body "Updates ${PIXI_TOML} and regenerates ${ANALYSIS3_DIR}/pixi.lock, ${ANALYSIS3_DIR}/solved.json, and ${ANALYSIS3_DIR}/environment.yml for access-moppy ${VERSION}."
fi
gh pr view "${BRANCH}" --json number -q .number > ../pr_number.txt