Optional import of data_request_api (#216) #376
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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@v6.0.2 | |
| 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: 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@v6 | |
| 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@v6.0.2 | |
| with: | |
| submodules: recursive | |
| - name: Download build artifacts from PyPI job | |
| uses: actions/download-artifact@v7 | |
| 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 | |
| version: "{{ version }}" | |
| source: | |
| path: ../ | |
| build: | |
| noarch: python | |
| number: 0 | |
| script: "{{ PYTHON }} -m pip install . -vv" | |
| requirements: | |
| host: | |
| - python | |
| - pip | |
| - versioneer | |
| run: | |
| - python >=3.11 | |
| - xarray | |
| - numpy | |
| - dask | |
| - pyyaml | |
| - cftime | |
| 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 | |
| echo "Created temporary conda recipe to use local source (path: ../)" | |
| - name: Setup conda environment | |
| uses: conda-incubator/setup-miniconda@v3 | |
| with: | |
| miniconda-version: "latest" | |
| python-version: 3.11 | |
| environment-file: .conda/environment.yml | |
| auto-update-conda: false | |
| auto-activate-base: false | |
| show-channel-urls: true | |
| - name: Build and upload the conda package | |
| uses: ACCESS-NRI/action-build-and-upload-conda-packages@d97711bc4445ba5c4de55f5a1bccbd4815286289 | |
| with: | |
| meta_yaml_dir: .conda-temp | |
| upload: true | |
| user: accessnri | |
| label: main | |
| token: ${{ secrets.anaconda_token }} | |
| - name: Verify conda package build | |
| run: | | |
| echo "Conda build completed successfully!" | |
| echo "Version built: ${{ needs.pypi.outputs.version }}" | |
| echo "✅ Conda package should now be available in the accessnri channel" | |
| 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 | |
| FILE_PATH: environments/analysis3/environment.yml | |
| PACKAGE: access-moppy | |
| 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, Python deps) | |
| 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 | |
| python3 -m pip install --upgrade pip | |
| python3 -m pip install ruamel.yaml | |
| - 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 environment.yml | |
| id: edit | |
| working-directory: ${{ env.TARGET_REPO }} | |
| env: | |
| VERSION: ${{ steps.ver.outputs.version }} | |
| run: | | |
| BRANCH="bump-${{ env.PACKAGE }}-${VERSION}" | |
| git fetch origin "${TARGET_BRANCH}" | |
| git checkout -b "$BRANCH" "origin/${TARGET_BRANCH}" | |
| python3 - <<'PY' | |
| from ruamel.yaml import YAML | |
| from ruamel.yaml.comments import CommentedSeq | |
| from pathlib import Path | |
| import os, sys | |
| path = Path("${{ env.FILE_PATH }}") | |
| version = os.environ["VERSION"] | |
| target = f"accessnri::access-moppy=={version}" | |
| yaml = YAML() | |
| yaml.preserve_quotes = True | |
| yaml.width = 4096 | |
| yaml.indent(mapping=2, sequence=2, offset=2) | |
| text = path.read_text(encoding="utf-8") | |
| data = yaml.load(text) | |
| deps = data.get("dependencies", CommentedSeq()) | |
| if not isinstance(deps, list): | |
| print("ERROR: dependencies is not a list", file=sys.stderr) | |
| sys.exit(1) | |
| replaced = False | |
| for i, d in enumerate(deps): | |
| if isinstance(d, str) and d.startswith("accessnri::access-moppy=="): | |
| if d != target: | |
| deps[i] = target | |
| replaced = True | |
| break | |
| if not replaced: | |
| deps.append(target) | |
| data["dependencies"] = deps | |
| with open(path, "w", encoding="utf-8") as f: | |
| yaml.dump(data, f) | |
| PY | |
| git add "${FILE_PATH}" | |
| 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)" | |
| gh pr create \ | |
| --base "${TARGET_BRANCH}" \ | |
| --head "${BRANCH}" \ | |
| --title "Bump access-moppy to ${VERSION} in analysis3 env" \ | |
| --body "Updates \`${FILE_PATH}\` to \`accessnri::access-moppy==${VERSION}\`." | |
| gh pr view "${BRANCH}" --json number -q .number > ../pr_number.txt |