diff --git a/.github/workflows/create-release-artifacts.yml b/.github/workflows/create-release-artifacts.yml new file mode 100644 index 000000000..5fe7ccfdd --- /dev/null +++ b/.github/workflows/create-release-artifacts.yml @@ -0,0 +1,145 @@ + +name: Create release artifacts +on: + workflow_dispatch: + # running this when PR opens we'll do in prep-release manually, see that file for more details + push: + branches: + - 'release/**' + workflow_run: + workflows: [Create a new release] + types: + - completed + +jobs: + pypi: + runs-on: ubuntu-latest + outputs: + url: ${{ steps.upload-pypi-release-artifacts.outputs.artifact-url }} + if: ${{ github.event_name == 'push' || github.event.workflow_run.conclusion == 'success' }} + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - uses: actions/setup-python@v5 + name: Install Python + with: + python-version: '3.11' + + - name: generate env + run: | + pip install tomli flit twine + + - name: Build artifacts + run: | + git clean -xdf + git restore -SW . + flit build + python -m twine check dist/* + + - name: Publish package to TestPyPI + uses: pypa/gh-action-pypi-publish@v1.9.0 + with: + user: __token__ + password: ${{ secrets.PYPI_TEST_TOKEN }} + repository-url: https://test.pypi.org/legacy/ + verbose: true + skip-existing: true + + - uses: actions/upload-artifact@v4 + id: upload-pypi-release-artifacts + with: + name: pypi-release-artifacts + path: dist + docs: + runs-on: ubuntu-latest + outputs: + url: ${{ steps.upload-docs-release-artifacts.outputs.artifact-url }} + if: ${{ github.event_name == 'push' || github.event.workflow_run.conclusion == 'success' }} + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - uses: prefix-dev/setup-pixi@v0.8.1 + with: + pixi-version: "v0.21.1" + environments: full-py311 + + - name: Generate docs + run: | + pixi run --locked -e full-py311 html + + - uses: actions/upload-artifact@v4 + id: upload-docs-release-artifacts + with: + name: docs-release-artifacts + path: docs/_build + + + docker: + runs-on: ubuntu-latest + outputs: + url: ${{ steps.upload-docker-release-artifacts.outputs.artifact-url }} + if: ${{ github.event_name == 'push' || github.event.workflow_run.conclusion == 'success' }} + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to Docker Hub to check credentials + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Build and export + uses: docker/build-push-action@v6 + with: + outputs: type=docker,dest=/tmp/hydromt-docker-image.tar + tags: hydromt + + - name: Run Tests + run: | + docker load --input /tmp/hydromt-docker-image.tar + docker run --env NUMBA_DISABLE_JIT=1 --rm hydromt + + - name: Test Binder integration with repo2docker + run: | + pip install jupyter-repo2docker + repo2docker . echo 'success!' + + + - name: Upload artifact + uses: actions/upload-artifact@v4 + id: upload-docker-release-artifacts + with: + name: hydromt-docker-image + path: /tmp/hydromt-docker-image.tar + + notify: + needs: + - pypi + - docs + - docker + runs-on: ubuntu-24.04 + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Add comment to PR + env: + GH_TOKEN: ${{ github.token }} + pypi_url: ${{needs.pypi.outputs.url}} + docker_url: ${{needs.docker.outputs.url}} + docs_url: ${{needs.docs.outputs.url}} + run: | + echo "The new release artifacts have been generated and tested. You can download and inspect them if you want by using the links below: " > comment.txt + echo " - pypi: $pypi_url" >> comment.txt + echo " - docker: $docker_url" >> comment.txt + echo " - docs: $docs_url" >> comment.txt + export PR_ID=$(gh pr list --state "open" --author "app/github-actions" --search "release" --json "number" --jq '. | first | .number') + + gh pr comment $PR_ID --body-file comment.txt diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 632be315f..b6450bc1e 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -32,8 +32,8 @@ jobs: runs-on: ubuntu-latest steps: - name: checkout code - uses: actions/checkout@v3 - - uses: prefix-dev/setup-pixi@v0.6.0 + uses: actions/checkout@v4 + - uses: prefix-dev/setup-pixi@v0.8.1 with: pixi-version: "v0.21.1" environments: full-py311 @@ -49,13 +49,13 @@ jobs: pixi run --locked -e full-py311 sphinx-build ./docs ./docs/_build -b dummy -W - name: Generate docs - if: ${{ github.event_name != 'pull_request' && !github.event.act }} + if: ${{ github.event_name != 'pull_request' }} run: | pixi run --locked -e full-py311 html echo "DOC_VERSION=$(pixi run --locked -e full-py311 python -c 'from hydromt import __version__ as v; print("dev" if "dev" in v else "v"+v.replace(".dev",""))')" >> $GITHUB_ENV - name: Upload to GitHub Pages - if: ${{ github.event_name != 'pull_request' && !github.event.act }} + if: ${{ github.event_name != 'pull_request' }} uses: peaceiris/actions-gh-pages@v3.9.3 with: github_token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/finish-release.yml b/.github/workflows/finish-release.yml new file mode 100644 index 000000000..186371464 --- /dev/null +++ b/.github/workflows/finish-release.yml @@ -0,0 +1,128 @@ + +name: Finalise a new release + +on: + pull_request: + types: + - closed + branches: + - 'release/**' + +jobs: + publish-docker: + if: github.event.pull_request.merged == true + name: Finalise docker (${{ matrix.flavour }}) release + runs-on: ubuntu-24.04 # latest LTS release + strategy: + fail-fast: false + matrix: + flavour: ['min','slim','full'] + concurrency: + group: NEW_RELEASE_DOCKER + cancel-in-progress: false # don't abort while we might be creating a PR or something + steps: + - uses: actions/checkout@v4 + name: Checkout code + + - uses: actions/download-artifact@v4 + with: + name: hydromt-docker-image + + - name: Login to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Build and push ${{ matrix.flavour }} image + uses: docker/build-push-action@v6 + with: + context: . + target: ${{ matrix.flavour }} + push: true + tags: deltares/hydromt:${{ env.version }}-${{ matrix.flavour }} + + - name: Build and push latest image + if: matrix.flavour == 'slim' + uses: docker/build-push-action@v6 + with: + context: . + target: ${{ matrix.flavour }} + push: true + tags: deltares/hydromt:${{ env.version }}, deltares/hydromt:latest + + publish-pypi: + runs-on: ubuntu-latest + if: github.event.pull_request.merged == true + steps: + - uses: actions/download-artifact@v4 + with: + name: pypi-release-artifacts + path: dist + - name: Publish package to PyPI + uses: pypa/gh-action-pypi-publish@v1.9.0 + with: + user: __token__ + password: ${{ secrets.PYPI_TOKEN }} + verbose: true + + publish-docs: + runs-on: ubuntu-latest + if: github.event.pull_request.merged == true + steps: + - uses: actions/download-artifact@v4 + with: + name: docs-release-artifacts + path: docs/_build + - name: Upload to GitHub Pages + uses: peaceiris/actions-gh-pages@v4.0.0 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_dir: ./docs/_build/html + exclude_assets: .buildinfo,_sources/*,_examples/*.ipynb + destination_dir: ./${{ env.DOC_VERSION }} + keep_files: false + full_commit_message: Deploy Release ${{ env.DOC_VERSION }} docs to GitHub Pages + + + gh-release: + needs: + - publish-docker + - publish-pypi + - publish-docs + runs-on: ubuntu-latest + env: + GH_TOKEN: ${{ github.token }} + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Finalise PR + run: | + git pull + git checkout main + export RELEASE_VERSION=$(grep "version" hydromt/__init__.py | cut -d= -f 2 | tr -d "\" ") + if [ -z "$RELEASE_VERSION" ]; then + echo "could not determine release version" + echo "detection result: $RELEASE_VERSION" + exit 1 # somthing went very wrong + fi + ## seting up git + git config user.name "GitHub Actions Bot" + git config user.email "<>" + git tag "v$RELEASE_VERSION" + # post release stuff so we don't forget + sed -i "s/v$RELEASE_VERSION/Unreleased\n==========\n\nNew\n---\n\nChanged\n-------\n\nFixed\n-----\n\nDeprecated\n----------\n\nv$RELEASE_VERSION/" docs/changelog.rst + sed -i 's/__version__.*=.*"\(.*\)".*/__version__ = "\1.dev0"/' hydromt/__init__.py + + git add hydromt/__init__.py docs/changelog.rst + git commit -m "Post release v$RELEASE_VERSION" + awk ' + BEGIN { capture = 0; } + # Match the first header and start capturing + /^v[0-9]+\.[0-9]+\.[0-9]+.*$/ { if (capture == 0) { capture = 1; } else { exit; } } + # Capture lines between headers + capture { print; } + ' docs/changelog.rst > release_notes.rst + git push + git push origin tag "v$RELEASE_VERSION" + gh release create "v$RELEASE_VERSION" -F release_notes.rst -t "v$RELEASE_VERSION" diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml index e8272ec5e..686970a08 100644 --- a/.github/workflows/linting.yml +++ b/.github/workflows/linting.yml @@ -10,6 +10,6 @@ jobs: pre-commit: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - uses: actions/setup-python@v3 + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 - uses: pre-commit/action@v3.0.0 diff --git a/.github/workflows/migration-guide.yml b/.github/workflows/migration-guide.yml deleted file mode 100644 index 6b848d3f8..000000000 --- a/.github/workflows/migration-guide.yml +++ /dev/null @@ -1,28 +0,0 @@ - -name: Migration guide is updated - -on: - pull_request: - branches: - - v1 - paths: - - tests/* - - hydromt/* - - -jobs: - build: - defaults: - run: - shell: bash -l {0} - name: Migration guide is updated - runs-on: ubuntu-latest - steps: - - - uses: actions/checkout@v4 - - name: check migration guide is updated - run: | - git diff --name-status v1 | grep migrating - - name: check api.rst is updated - run: | - git diff --name-status v1 | grep "api.rst" diff --git a/.github/workflows/pixi_auto_update.yml b/.github/workflows/pixi_auto_update.yml index d14f53097..cebcc2949 100644 --- a/.github/workflows/pixi_auto_update.yml +++ b/.github/workflows/pixi_auto_update.yml @@ -14,7 +14,7 @@ jobs: - uses: actions/checkout@v4 with: ssh-key: ${{ secrets.SSH_PRIVATE_KEY }} - - uses: prefix-dev/setup-pixi@v0.6.0 + - uses: prefix-dev/setup-pixi@v0.8.1 with: pixi-version: "v0.21.1" cache: false diff --git a/.github/workflows/prep-release.yml b/.github/workflows/prep-release.yml new file mode 100644 index 000000000..1a87a6e3f --- /dev/null +++ b/.github/workflows/prep-release.yml @@ -0,0 +1,138 @@ +name: Create a new release + +on: + workflow_dispatch: + inputs: + bump: + type: choice + options: + - patch + - minor + - major + default: minor + description: "Is this a Major, Minor, or Patch release?" +jobs: + build: + defaults: + run: + shell: bash -l {0} + name: Setup release PR + runs-on: ubuntu-24.04 # latest LTS release + concurrency: + group: NEW_RELEASE + cancel-in-progress: false # don't abort while we might be creating a PR or something + steps: + + - uses: actions/checkout@v4 + + - name: check there are no pre-existing release PRs + run: | + export EXISTING_RELEASE_PR_NUMBER=$(gh pr list --search "release" --json "number") + if [ $(echo $EXISTING_RELEASE_PR_NUMBER | jq '.|length') -gt 0]; then + gh pr comment $EXISTING_RELEASE_PR_NUMBER --body "$username It looks like you tried to start a new release but this one is already started. Please either finish or close this one before continuing"; + exit 1 + fi + env: + username: ${{ github.actor }} + + - name: setup release PR + env: + GH_TOKEN: ${{ github.token }} + BUMP_KIND: ${{ inputs.bump }} + run: | + + set -e + # check if there already is a release PR open + # parsing of current version + export CURRENT_VERSION=$(grep "version" hydromt/__init__.py | cut -d= -f 2 | tr -d "\" ") + export CURRENT_MAJOR=$(echo $CURRENT_VERSION | cut -d'.' -f 1) + export CURRENT_MINOR=$(echo $CURRENT_VERSION | cut -d'.' -f 2) + export CURRENT_PATHCH=$(echo $CURRENT_VERSION | cut -d'.' -f 3) + + BUMP=$BUMP_KIND + + ## calculate new release number + case $BUMP in + + "patch") + export NEW_VERSION="$CURRENT_MAJOR.$CURRENT_MINOR.$((CURRENT_PATHCH + 1))" + ;; + + "minor") + export NEW_VERSION="$CURRENT_MAJOR.$(($CURRENT_MINOR + 1)).0" + ;; + + "major") + export NEW_VERSION="$((CURRENT_MAJOR + 1)).0.0" + ;; + + *) + echo "invalid bump: $BUMP" + exit 1 + ;; + esac + + ## seting up git + git config user.name "GitHub Actions Bot" + git config user.email "<>" + + ## create release branch + git pull # make sure git doesn't reject our push becasue of unknown refs + git checkout -b "release/v$NEW_VERSION" + + # update version in python file + sed -i "s/.*__version__.*/__version__ = \"$NEW_VERSION\"/" hydromt/__init__.py + + export NEW_CHANGELOG_HEADER="v$NEW_VERSION ($(date -I))" + export NEW_HEADER_UNDERLINE=$(printf '=%.0s' $(seq 1 $(echo $NEW_CHANGELOG_HEADER | awk '{print length}'))) + + # update chagnelog with new header + sed -i "/Unreleased/{s/Unreleased/$NEW_CHANGELOG_HEADER/;n;s/=*/$NEW_HEADER_UNDERLINE/}" docs/changelog.rst + + # update switcher.json while maintianing the correct order with some black jq incantations. I'll try and explain below + cat docs/_static/switcher.json | jq "map(select(.version != \"latest\")) | . + [{\"name\":\"v$NEW_VERSION\",\"version\":\"$NEW_VERSION\",\"url\":\"https://deltares.github.io/hydromt/v$NEW_VERSION/\"}] | sort_by(.version|split(\".\")|map(tonumber)) | . + [{\"name\":\"latest\",\"version\":\"latest\",\"url\":\"https://deltares.github.io/hydromt/latest/\"}]" >tmp.json + + # map(select(.version != \"latest\")) + # removes the "latest" entry, since we'll need to sort numerically by number in a later step + + #| . + + # take the result of the previous operation and add the following array to it + + # [{\"name\":\"v$NEW_VERSION\",\"version\":\"$NEW_VERSION\",\"url\":\"https://deltares.github.io/hydromt/v$NEW_VERSION/\"}] + # an array with the new entry we want to add + + # sort_by(.version|split(\".\")|map(tonumber)) + # take the array, split the version field by the "." char and make numbers out of the components. then sort the whole array by these numbers + # this is why we had to remove the latest field earlier, + # otherwise the number conversion would fail here. + + #| . + [{\"name\":\"latest\",\"version\":\"latest\",\"url\":\"https://deltares.github.io/hydromt/latest\"}] + # add the latest field back in at the end + + # avoid race conditions by using a tmp file + mv tmp.json docs/_static/switcher.json + + git add . + git commit -m "prepare for release v$NEW_VERSION" + git push --set-upstream origin "release/v$NEW_VERSION" + + # gh cli should return the url of the pr it just created. we'll store that so we can access it later + export PR_URL=$( gh pr create -B "main" -H "release/v$NEW_VERSION" -t "Release v$NEW_VERSION" -b "Hi there! This is an automated PR made for your release. If everything has gone well, all tests should now be running. Please check that the PR is as you would like it to be, and feel free to push any changes to this branch before merging. Once you're happy with the state of the PR, someone just needs to approve it, and I'll take care of the rest!" ) + gh co "release/v$NEW_VERSION" + + # not fetched by default + git fetch --tags + export LAST_RELEASE=$(git tag | head -n 1) + export PYPROJ_DIFF=$(git diff "$LAST_RELEASE" -- pyproject.toml) + + if [[ -z $PYPROJ_DIFF ]]; then + gh pr comment "$PR_URL" --body "I've detected the latest tag was \`$LAST_RELEASE\`. No dependency or project config changes have been made since then. You should be able to release to conda without updating the receipt." + else + echo "I've detected the latest tag was \`$LAST_RELEASE\`. Here are the changes made to the \`pyproject.toml\` since then:" > comment.txt + echo $'\n\n```diff\n' >> comment.txt + echo "$PYPROJ_DIFF" >> comment.txt + echo $'\n\n```\n' >> comment.txt + echo "(you might have to update the receipt to update to reflect these changes when releasing to conda)" + gh pr comment "$PR_URL" --body-file comment.txt + + fi diff --git a/.github/workflows/publish-docker.yml b/.github/workflows/publish-docker.yml deleted file mode 100644 index 319c282f6..000000000 --- a/.github/workflows/publish-docker.yml +++ /dev/null @@ -1,76 +0,0 @@ ---- -name: Build and publish HydroMT to DockerHub - -on: - release: - types: - - published - - workflow_dispatch: - inputs: - publish: - description: 'Actually push images' - required: true - type: boolean - default: false - version: - description: 'The version to publish' - required: true - type: string - - -jobs: - publish-docker-image: - strategy: - fail-fast: false - matrix: - flavour: ['min','slim','full'] - name: ${{ matrix.flavour }} - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v3 - - - name: Set up QEMU - uses: docker/setup-qemu-action@v2 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 - - - name: Setup variables - run: | - if [ "${{ github.event_name }}" == "release" ]; then - echo "should_publish=true" >> $GITHUB_ENV - echo "version=${{ github.event.release.tag_name }}" >> $GITHUB_ENV - elif [ "${{ github.event_name }}" == "workflow_dispatch" ]; then - echo "version=${{ github.event.inputs.version }}" >> $GITHUB_ENV - echo "should_publish=${{ github.event.inputs.publish }}" >> $GITHUB_ENV - fi - shell: bash - - - name: Login to Docker Hub - uses: docker/login-action@v2 - with: - username: ${{ secrets.TEST_DOCKERHUB_USERNAME }} - password: ${{ secrets.TEST_DOCKERHUB_TOKEN }} - - - name: Build and push ${{ matrix.flavour }} image - uses: docker/build-push-action@v4 - with: - context: . - target: ${{ matrix.flavour }} # - push: ${{ env.should_publish }} - tags: deltares/hydromt:${{ env.version }}-${{ matrix.flavour }} - build-args: | - PIXIENV=${{ matrix.flavour }}-py311 - - - name: Build and push latest image - if: matrix.flavour == 'slim' - uses: docker/build-push-action@v4 - with: - context: . - target: ${{ matrix.flavour }} # - push: ${{ env.should_publish }} - tags: deltares/hydromt:${{ env.version }}, deltares/hydromt:latest - build-args: | - PIXIENV=${{ matrix.flavour }}-py311 diff --git a/.github/workflows/publish-pypi.yml b/.github/workflows/publish-pypi.yml deleted file mode 100644 index 6e5291ad2..000000000 --- a/.github/workflows/publish-pypi.yml +++ /dev/null @@ -1,105 +0,0 @@ ---- -name: Build and Upload HydroMT to PyPI - -on: - release: - types: - - published - push: - tags: - - v* - workflow_dispatch: - - -jobs: - build-artifacts: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - - uses: actions/setup-python@v4 - name: Install Python - with: - python-version: '3.10' - - - name: generate env - run: | - pip install tomli flit twine - - - name: Build artifacts - run: | - python -m pip install --upgrade pip - python -m pip install flit wheel twine - git clean -xdf - git restore -SW . - flit build - python -m twine check dist/* - - - - uses: actions/upload-artifact@v3 - with: - name: releases - path: dist - - test-built-dist: - needs: build-artifacts - runs-on: ubuntu-latest - defaults: - run: - shell: bash -l {0} - steps: - - uses: actions/checkout@v3 - - - uses: actions/download-artifact@v3 - with: - name: releases - path: dist - - name: List contents of built dist - run: | - ls -ltrh - ls -ltrh dist - - - uses: actions/setup-python@v4 - with: - python-version: '3.10' - - - name: Verify the built dist/wheel is valid - run: | - python -m pip install dist/hydromt*.whl - hydromt --models - - upload-to-test-pypi: - needs: test-built-dist - if: github.event_name == 'push' - runs-on: ubuntu-latest - steps: - - uses: actions/download-artifact@v3 - with: - name: releases - path: dist - - name: Publish package to TestPyPI - uses: pypa/gh-action-pypi-publish@v1.5.1 - with: - user: __token__ - password: ${{ secrets.PYPI_TEST_TOKEN }} - repository_url: https://test.pypi.org/legacy/ - verbose: true - skip_existing: true - - upload-to-pypi: - needs: test-built-dist - if: ${{ github.event_name == 'release' && !github.event.act }} - runs-on: ubuntu-latest - steps: - - uses: actions/download-artifact@v3 - with: - name: releases - path: dist - - name: Publish package to PyPI - uses: pypa/gh-action-pypi-publish@v1.5.1 - with: - user: __token__ - password: ${{ secrets.PYPI_TOKEN }} - verbose: true diff --git a/.github/workflows/test-docker.yml b/.github/workflows/test-docker.yml index 7df357d68..e45bac91f 100644 --- a/.github/workflows/test-docker.yml +++ b/.github/workflows/test-docker.yml @@ -24,16 +24,16 @@ jobs: timeout-minutes: 30 steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Set up QEMU - uses: docker/setup-qemu-action@v2 + uses: docker/setup-qemu-action@v3 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 + uses: docker/setup-buildx-action@v3 - name: Build and test - uses: docker/build-push-action@v4 + uses: docker/build-push-action@v6 with: context: . target: full diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index cc7f69a28..f31f0bf55 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -48,7 +48,7 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: prefix-dev/setup-pixi@v0.6.0 + - uses: prefix-dev/setup-pixi@v0.8.1 with: pixi-version: "v0.21.1" environments: full-py${{ matrix.python-version }} @@ -56,17 +56,7 @@ jobs: run: | pixi run --locked -e full-py${{ matrix.python-version }} install-hydromt - # Enable tmate debugging of manually-triggered workflows if the input option was provided - - name: Setup tmate session - uses: mxschmitt/action-tmate@v3 - if: ${{ github.event_name == 'workflow_dispatch' && inputs.debug_enabled }} - - name: Test run: | export NUMBA_DISABLE_JIT=1 pixi run --locked -e full-py${{ matrix.python-version }} test-cov - - # enable for CI debugging - # - name: Setup tmate session - # if: ${{ failure() }} - # uses: mxschmitt/action-tmate@v3 diff --git a/.github/workflows/tests_pip.yml b/.github/workflows/tests_pip.yml index f1af95023..33cdaf8f4 100644 --- a/.github/workflows/tests_pip.yml +++ b/.github/workflows/tests_pip.yml @@ -27,12 +27,9 @@ jobs: fail-fast: false runs-on: ubuntu-latest timeout-minutes: 30 - # concurrency: - # group: ${{ github.workflow }}-${{ matrix.python-version }}-${{ github.ref }} - # cancel-in-progress: true steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: actions/setup-python@v4 id: py310 diff --git a/docs/changelog.rst b/docs/changelog.rst index 1fd4d5306..2187ffe90 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -11,6 +11,7 @@ Unreleased New --- +- Further automate release mechanism. (#1019) Changed ------- diff --git a/docs/dev/contributing.rst b/docs/dev/contributing.rst index 523bc87a8..569442eff 100644 --- a/docs/dev/contributing.rst +++ b/docs/dev/contributing.rst @@ -422,18 +422,11 @@ A single test: Creating a release ------------------ -1. Create a new branch with the name "release/" where is the version number, e.g. v0.7.0 -2. Bump the version number (without "v"!) in the __init__.py, check and update the docs/changelog.rst file and add a short summary to the changelog for this version. - Check if all dependencies in the toml are up to date. Commit all changes -3. Create a new documentation version in the `docs/switcher.json` that has the same structure as the other version entries. Please make sure the list stays sorted as this represents the ordering of the menu. -4. Create a tag using `git tag `, e.g. git tag v0.7.0 -5. Push your changes to github. To include the tag do `git push origin `. This should trigger a test release to test.pypi.org -6. If all tests and the test release have succeeded, merge de branch to main. -7. Create a new release on github under https://github.com/Deltares/hydromt/releases. - Use the "generate release notes" button and copy the content of the changelog for this version on top of the release notes. This should trigger the release to PyPi. -8. The new PyPi package will trigger a new PR to the `HydroMT feedstock repos of conda-forge `_. - Check if all dependencies are up to date and modify the PR if necessary. Merge the PR to release the new version on conda-forge. - -.. NOTE:: - - In the next PR that get's merged into main, the version numbers in __init__.py and the changelog should be changed to the next release with ".dev" postfix. +1. Go to the `actions` tab on Github, select `Create a release` from the actions listen to the left, then use the `run workflow` button to start the release process. You will be asked whether it will be a `major`, `minor` or `patch` release. Choose the appropriate action. +2. The action you just run will open a new PR for you with a new branch named `release/v`. (the `NEW_VERSION` will be calculated for you based on which kind of release you selected.) In the new PR, the changelog, hydromt version and sphinx `switcher.json` will be updated for you. Any changes you made to the `pyproject.toml` since the last release will be posted as a comment in the PR. You will need these during the Conda-forge release if there are any. +3. Every commit to this new branch will trigger the creation (and testing) of release artifacts. In our case those are: Documentation, the PyPi package and docker image (the conda release happens separately). After the artifacts are created, they will be uploaded to the repository's internal artifact cache. A bot will post links to these created artifacts in the PR which you can use to download and locally inspect them. +4. When you are happy with the release in the PR, you can simply merge it. We suggest naming the commit something like "Release v" +5. After the PR is merged, a action should start (though it will not show up under the PR itself) that will publish the latest artifacts created to their respective platform. After this, a bot will add a final commit to the `main` branch, setting the hydromt version back to a dev version, and adding new headers to the `docs/changelog.rst` for unreleased features. It will also create a tag and a github release for you automatically. The release is now done as far as this repo is concerned. +6. The newly published PyPi package will trigger a new PR to the `HydroMT feedstock repos of conda-forge `_. + Here you can use the comment posted to the release PR to see if the `meta.yml` needs to be updated. Merge the PR to release the new version on conda-forge. +7. celebrate the new release!