diff --git a/.github/pr_labeler.yaml b/.github/pr_labeler.yaml
new file mode 100644
index 000000000..ab722839f
--- /dev/null
+++ b/.github/pr_labeler.yaml
@@ -0,0 +1,25 @@
+# https://github.com/actions/labeler
+breaking:
+- head-branch: ['breaking', 'BREAKING']
+bug:
+- head-branch: ['fix', 'FIX', 'bug', 'BUG']
+feature:
+- head-branch: ['feat', 'FEAT']
+documentation:
+- changed-files:
+ - any-glob-to-any-file:
+ - docs/**
+ - images/**
+ - README.md
+ - CHANGELOG.md
+ - CONTRIBUTING.md
+enhancement:
+- head-branch: ['enhance', 'improve', 'IMPR', 'DJEP']
+- changed-files:
+ - any-glob-to-any-file:
+ - '**'
+ - '!docs/**'
+ - '!images/**'
+ - '!README.md'
+ - '!CHANGELOG.md'
+ - '!CONTRIBUTING.md'
diff --git a/.github/release_drafter.yaml b/.github/release_drafter.yaml
new file mode 100644
index 000000000..b1602fa7d
--- /dev/null
+++ b/.github/release_drafter.yaml
@@ -0,0 +1,35 @@
+version-resolver:
+ major:
+ labels:
+ - 'breaking'
+ minor:
+ labels:
+ - 'feature'
+ patch:
+ labels:
+ - 'documentation'
+ - 'enhancement'
+ - 'bug'
+name-template: '$RESOLVED_VERSION'
+tag-template: 'v$RESOLVED_VERSION'
+categories:
+ - title: '💥 Breaking Changes'
+ labels:
+ - 'breaking'
+ - title: '🚀 Features'
+ labels:
+ - 'feature'
+ - title: '⚡️ Enhancements'
+ labels:
+ - 'enhancement'
+ - title: '🐛 Bug Fixes'
+ labels:
+ - 'bug'
+ - title: '📝 Documentation'
+ label: 'documentation'
+change-template: '- $TITLE(#$NUMBER)@$AUTHOR'
+change-title-escapes: '\<*_&' # You can add # and @ to disable mentions, and add ` to disable code blocks.
+template: |
+ $CHANGES
+
+ **Full Changelog**: https://github.com/$OWNER/$REPOSITORY/compare/$PREVIOUS_TAG...v$RESOLVED_VERSION
\ No newline at end of file
diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml
index f434d63d7..5f2b103cb 100644
--- a/.github/workflows/docs.yaml
+++ b/.github/workflows/docs.yaml
@@ -1,7 +1,10 @@
-name: Manual docs release
+name: Docs release
on:
+ # manually trigger
workflow_dispatch:
+ # been called by other workflows
workflow_call:
+
jobs:
publish-docs:
runs-on: ubuntu-latest
diff --git a/.github/workflows/draft_release.yaml b/.github/workflows/draft_release.yaml
new file mode 100644
index 000000000..e617aa0e8
--- /dev/null
+++ b/.github/workflows/draft_release.yaml
@@ -0,0 +1,31 @@
+name: Manual Draft Release
+on:
+ workflow_dispatch:
+ inputs:
+ testpypi:
+ description: 'Release to TestPyPI then skip following'
+ default: 'false'
+ type: choice
+ options:
+ - 'true'
+ - 'false'
+jobs:
+ build-release:
+ permissions:
+ # write permission is required to create a github release
+ contents: write
+ # write permission is required for autolabeler
+ # otherwise, read permission is required at least
+ pull-requests: read
+ runs-on: ubuntu-latest
+ steps:
+ # Drafts your next Release notes as Pull Requests are merged into "master"
+ - name: Draft release notes
+ id: create_gh_release
+ uses: release-drafter/release-drafter@v6
+ with:
+ config-name: release_drafter.yaml
+ disable-autolabeler: true
+ name: ${{ github.event.inputs.testpypi == 'true' && 'Test $RESOLVED_VERSION' || 'Release $RESOLVED_VERSION' }}
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.github/workflows/label_prs.yaml b/.github/workflows/label_prs.yaml
new file mode 100644
index 000000000..9797a956f
--- /dev/null
+++ b/.github/workflows/label_prs.yaml
@@ -0,0 +1,18 @@
+# https://github.com/actions/labeler
+name: "Pull Request Labeler"
+on:
+- pull_request_target
+
+jobs:
+ labeler:
+ permissions:
+ contents: read
+ pull-requests: write
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/labeler@v5
+ with:
+ repo-token: ${{ secrets.GITHUB_TOKEN }}
+ configuration-path: .github/pr_labeler.yaml
+ sync-labels: true
+ dot: true
\ No newline at end of file
diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml
index 1b012f1f9..62468a983 100644
--- a/.github/workflows/lint.yaml
+++ b/.github/workflows/lint.yaml
@@ -1,4 +1,4 @@
-name: Test
+name: Lint
on:
push:
branches:
diff --git a/.github/workflows/post_draft_release_published.yaml b/.github/workflows/post_draft_release_published.yaml
new file mode 100644
index 000000000..3daac2f5d
--- /dev/null
+++ b/.github/workflows/post_draft_release_published.yaml
@@ -0,0 +1,154 @@
+name: Post Draft Release Published
+
+on:
+ # Once draft release is released, trigger the docs release
+ release:
+ types:
+ ## pre-release and stable release
+ #- published
+ ## stable release only
+ - released
+run-name: Post ${{ github.event.release.name }}
+
+jobs:
+ call-publish-docs:
+ uses: ./.github/workflows/docs.yaml
+ pypi-release:
+ permissions:
+ # write permission is required to update version.py
+ contents: write
+ pull-requests: write
+ # Use the oldest supported version to build, just in case there are issues
+ # for our case, this doesn't matter that much, since the build is for 3.x
+ strategy:
+ matrix:
+ include:
+ - py_ver: "3.9"
+ runs-on: ubuntu-latest
+ env:
+ PY_VER: ${{matrix.py_ver}}
+ TWINE_USERNAME: ${{secrets.twine_username}}
+ TWINE_PASSWORD: ${{secrets.twine_password}}
+ TWINE_TEST_USERNAME: ${{secrets.twine_test_username}}
+ TWINE_TEST_PASSWORD: ${{secrets.twine_test_password}}
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+ with:
+ token: ${{ secrets.GITHUB_TOKEN }}
+ # new release needs the updated version.py
+ - name: Update version.py
+ run: |
+ VERSION=$(echo "${{ github.event.release.name }}" | grep -oP '\d+\.\d+\.\d+')
+ sed -i "s/^__version__ = .*/__version__ = \"$VERSION\"/" datajoint/version.py
+ cat datajoint/version.py
+ # Commit the changes
+ BRANCH_NAME="update-version-$VERSION"
+ git switch -c $BRANCH_NAME
+ git config --global user.name "github-actions"
+ git config --global user.email "github-actions@github.com"
+ git add datajoint/version.py
+ git commit -m "Update version.py to $VERSION"
+ echo "BRANCH_NAME=$BRANCH_NAME" >> $GITHUB_ENV
+ - name: Update README.md badge
+ run: |
+ # commits since the last release
+ NEW_HREF="https://github.com/datajoint/datajoint-python/compare/${{ github.event.release.tag_name }}...master"
+ NEW_SRC="https://img.shields.io/github/commits-since/datajoint/datajoint-python/${{ github.event.release.tag_name }}?color=red"
+ # Update href in the tag
+ sed -i 's|\(]*href="\)[^"]*\(".*\)|\1'"$NEW_HREF"'\2|' README.md
+ # Update src in the
tag
+ sed -i 's|\(
]*src="\)[^"]*\(".*\)|\1'"$NEW_SRC"'\2|' README.md
+ git add README.md
+ git commit -m "Update README.md badge to ${{ github.event.release.tag_name }}"
+ - name: Set up Python ${{matrix.py_ver}}
+ uses: actions/setup-python@v5
+ with:
+ python-version: ${{matrix.py_ver}}
+ # Merging build and release steps just for the simplicity,
+ # since datajoint-python doesn't have platform specific dependencies or binaries,
+ # and the build process is fairly fast, so removed upload/download artifacts
+ - name: Build package
+ id: build
+ run: |
+ python -m pip install build
+ python -m build .
+ echo "DJ_WHEEL_PATH=$(ls dist/datajoint-*.whl)" >> $GITHUB_ENV
+ echo "DJ_SDIST_PATH=$(ls dist/datajoint-*.tar.gz)" >> $GITHUB_ENV
+ echo "NEW_VERSION=${{github.event.release.resolved_version}}" >> $GITHUB_ENV
+ - name: Publish package
+ id: publish
+ env:
+ RELEASE_NAME: ${{ github.event.release.name }}
+ run: |
+ export HOST_UID=$(id -u)
+ if [[ "$RELEASE_NAME" =~ ^Test ]]; then
+ LATEST_PYPI=$(curl -s https://test.pypi.org/pypi/datajoint/json | jq -r '.info.version')
+ echo "TEST_PYPI=true" >> $GITHUB_ENV
+ export TWINE_REPOSITORY="testpypi"
+ export TWINE_USERNAME=${TWINE_TEST_USERNAME}
+ export TWINE_PASSWORD=${TWINE_TEST_PASSWORD}
+ else
+ LATEST_PYPI=$(curl -s https://pypi.org/pypi/datajoint/json | jq -r '.info.version')
+ echo "TEST_PYPI=false" >> $GITHUB_ENV
+ export TWINE_REPOSITORY="pypi"
+ fi
+ # Check if the new version is different from the latest on PyPI, avoid re-uploading error
+ if [ "$NEW_VERSION" != "$LATEST_PYPI" ]; then
+ docker compose run --build --quiet-pull \
+ -e TWINE_USERNAME=${TWINE_USERNAME} \
+ -e TWINE_PASSWORD=${TWINE_PASSWORD} \
+ -e TWINE_REPOSITORY=${TWINE_REPOSITORY} \
+ app sh -c "pip install twine && python -m twine upload dist/*"
+ else
+ echo "::warning::Latest version $LATEST_PYPI on $TWINE_REPOSITORY is the new version $NEW_VERSION"
+ fi
+ # Upload package as release assets
+ - name: Upload pip wheel asset to release
+ uses: actions/upload-release-asset@v1
+ env:
+ GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
+ with:
+ upload_url: ${{github.event.release.upload_url}}
+ asset_path: ${{env.DJ_WHEEL_PATH}}
+ asset_name: pip-datajoint-${{ github.event.release.tag_name }}.whl
+ asset_content_type: application/zip
+ - name: Upload pip sdist asset to release
+ uses: actions/upload-release-asset@v1
+ env:
+ GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
+ with:
+ upload_url: ${{github.event.release.upload_url}}
+ asset_path: ${{env.DJ_SDIST_PATH}}
+ asset_name: pip-datajoint-${{ github.event.release.tag_name }}.tar.gz
+ asset_content_type: application/gzip
+ - name: Create Pull Request
+ env:
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ run: |
+ git push origin ${{ env.BRANCH_NAME }}
+ gh pr create \
+ --title "[github-actions]Update version.py to ${{ github.event.release.name }}" \
+ --body "This PR updates \`version.py\` to match the latest release: ${{ github.event.release.name }}" \
+ --base master \
+ --head ${{ env.BRANCH_NAME }} \
+ --reviewer dimitri-yatsenko,yambottle,ttngu207
+ - name: Post release notification to Slack
+ if: ${{ env.TEST_PYPI == 'false' }}
+ uses: slackapi/slack-github-action@v2.0.0
+ with:
+ webhook: ${{ secrets.SLACK_WEBHOOK_URL }}
+ webhook-type: incoming-webhook
+ payload: |
+ {
+ "text": "*New Release Published!* :tada: \n*Repository:* ${{ github.repository }}\n*Version:* ${{ github.event.release.tag_name }}\n*URL:* ${{ github.event.release.html_url }}",
+ "blocks": [
+ {
+ "type": "section",
+ "text": {
+ "type": "mrkdwn",
+ "text": "*New Release Published!* :tada:\n*Repository:* ${{ github.repository }}\n*Version:* ${{ github.event.release.tag_name }}\n*URL:* <${{ github.event.release.html_url }}|View Release>"
+ }
+ }
+ ]
+ }
diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml
deleted file mode 100644
index ae848c310..000000000
--- a/.github/workflows/release.yaml
+++ /dev/null
@@ -1,127 +0,0 @@
-name: Release
-on:
- workflow_dispatch:
- inputs:
- testpypi:
- description: 'Release to TestPyPI then skip following'
- default: 'false'
- type: choice
- options:
- - 'true'
- - 'false'
-jobs:
- build-release:
- runs-on: ubuntu-latest
- # Use the oldest supported version to build, just in case there are issues
- # for our case, this doesn't matter that much, since the build is for 3.x
- strategy:
- matrix:
- include:
- - py_ver: "3.9"
- env:
- PY_VER: ${{matrix.py_ver}}
- TWINE_USERNAME: ${{secrets.twine_username}}
- TWINE_PASSWORD: ${{secrets.twine_password}}
- TWINE_TEST_USERNAME: ${{secrets.twine_test_username}}
- TWINE_TEST_PASSWORD: ${{secrets.twine_test_password}}
- TESTPYPI: ${{ github.event.inputs.testpypi }}
- steps:
- - uses: actions/checkout@v4
- - name: Set up Python ${{matrix.py_ver}}
- uses: actions/setup-python@v5
- with:
- python-version: ${{matrix.py_ver}}
- # Merging build and release steps just for the simplicity,
- # since datajoint-python doesn't have platform specific dependencies or binaries,
- # and the build process is fairly fast, so removed upload/download artifacts
- - name: Build package
- run: |
- python -m pip install build
- python -m build .
- echo "DJ_WHEEL_PATH=$(ls dist/datajoint-*.whl)" >> $GITHUB_ENV
- echo "DJ_SDIST_PATH=$(ls dist/datajoint-*.tar.gz)" >> $GITHUB_ENV
- - name: Publish package
- run: |
- export HOST_UID=$(id -u)
- if [ "$TESTPYPI" == "true" ]; then
- export TWINE_REPOSITORY="testpypi"
- export TWINE_USERNAME=${TWINE_TEST_USERNAME}
- export TWINE_PASSWORD=${TWINE_TEST_PASSWORD}
- else
- export TWINE_REPOSITORY="pypi"
- fi
- docker compose run --build --quiet-pull \
- -e TWINE_USERNAME=${TWINE_USERNAME} \
- -e TWINE_PASSWORD=${TWINE_PASSWORD} \
- -e TWINE_REPOSITORY=${TWINE_REPOSITORY} \
- app sh -c "pip install twine && python -m twine upload dist/*"
- - name: Login to DockerHub
- if: ${{ github.event.inputs.testpypi == 'false' }}
- uses: docker/login-action@v3
- with:
- username: ${{secrets.docker_username}}
- password: ${{secrets.docker_password}}
- - name: Publish image
- if: ${{ github.event.inputs.testpypi == 'false' }}
- run: |
- IMAGE=$(docker images --filter "reference=datajoint/datajoint*" --format "{{.Repository}}")
- TAG=$(docker images --filter "reference=datajoint/datajoint*" --format "{{.Tag}}")
- docker push "${IMAGE}:${TAG}"
- docker tag "${IMAGE}:${TAG}" "${IMAGE}:${TAG}-${GITHUB_SHA:0:7}"
- docker push "${IMAGE}:${TAG}-${GITHUB_SHA:0:7}"
- [ "$PY_VER" == "3.9" ] && [ "$DISTRO" == "debian" ] \
- && docker tag "${IMAGE}:${TAG}" "${IMAGE}:latest" \
- && docker push "${IMAGE}:latest" \
- || echo "skipping 'latest' tag..."
- # Make sure all above release targets are done first, then make a GH release
- - name: Make release notes
- if: ${{ github.event.inputs.testpypi == 'false' }}
- run: |
- DJ_VERSION=$(grep -oP '\d+\.\d+\.\d+' datajoint/version.py)
- RELEASE_BODY=$(python -c \
- 'print(open("./CHANGELOG.md").read().split("\n\n")[1].split("\n", 1)[1])' \
- )
- echo "DJ_VERSION=${DJ_VERSION}" >> $GITHUB_ENV
- echo "RELEASE_BODY<> $GITHUB_ENV
- echo "$RELEASE_BODY" >> $GITHUB_ENV
- echo "EOF" >> $GITHUB_ENV
- - name: Create GH release
- if: ${{ github.event.inputs.testpypi == 'false' }}
- id: create_gh_release
- uses: actions/create-release@v1
- env:
- GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
- with:
- tag_name: ${{env.DJ_VERSION}}
- release_name: Release ${{env.DJ_VERSION}}
- body: ${{env.RELEASE_BODY}}
- prerelease: false
- draft: false
- # Upload package as release assets
- - name: Upload pip wheel asset to release
- if: ${{ github.event.inputs.testpypi == 'false' }}
- uses: actions/upload-release-asset@v1
- env:
- GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
- with:
- upload_url: ${{steps.create_gh_release.outputs.upload_url}}
- asset_path: ${{env.DJ_WHEEL_PATH}}
- asset_name: pip-datajoint-${{env.DJ_VERSION}}.whl
- asset_content_type: application/zip
- - name: Upload pip sdist asset to release
- if: ${{ github.event.inputs.testpypi == 'false' }}
- uses: actions/upload-release-asset@v1
- env:
- GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
- with:
- upload_url: ${{steps.create_gh_release.outputs.upload_url}}
- asset_path: ${{env.DJ_SDIST_PATH}}
- asset_name: pip-datajoint-${{env.DJ_VERSION}}.tar.gz
- asset_content_type: application/gzip
- # only release docs when a release is published
- call-publish-docs:
- if: ${{ github.event.inputs.testpypi == 'false' }}
- needs: build-release
- runs-on: ubuntu-latest
- steps:
- - uses: ./.github/workflows/docs.yaml
diff --git a/README.md b/README.md
index 3d3efe6e3..5fe32cb9c 100644
--- a/README.md
+++ b/README.md
@@ -30,16 +30,32 @@
| Since Release |
-
-
+
+
|
| Test Status |
-
-
+
+
+
+ |
+
+
+ | Release Status |
+
+
+
+
+ |
+
+
+ | Doc Status |
+
+
+
|
diff --git a/datajoint/version.py b/datajoint/version.py
index cc1d88710..c980ad0d0 100644
--- a/datajoint/version.py
+++ b/datajoint/version.py
@@ -1,3 +1,6 @@
-__version__ = "0.14.4"
+# version bump auto managed by Github Actions:
+# label_prs.yaml(prep), release.yaml(bump), post_release.yaml(edit)
+# manually set this version will be eventually overwritten by the above actions
+__version__ = "0.14.3"
assert len(__version__) <= 10 # The log table limits version to the 10 characters