chore: release 0.1.11 #18
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: Release | |
| 'on': | |
| push: | |
| tags: | |
| - 'v*' | |
| workflow_dispatch: | |
| inputs: | |
| tag: | |
| description: Release tag, for example v0.1.0 | |
| required: true | |
| type: string | |
| permissions: | |
| contents: write | |
| concurrency: | |
| group: release-${{ github.workflow }}-${{ github.ref_name || inputs.tag }} | |
| cancel-in-progress: false | |
| jobs: | |
| prepare: | |
| runs-on: ubuntu-latest | |
| outputs: | |
| tag: ${{ steps.meta.outputs.tag }} | |
| version: ${{ steps.meta.outputs.version }} | |
| is_prerelease: ${{ steps.meta.outputs.is_prerelease }} | |
| checkout_ref: ${{ steps.meta.outputs.checkout_ref }} | |
| commit_sha: ${{ steps.meta.outputs.commit_sha }} | |
| steps: | |
| - name: Check out repository | |
| uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| - name: Set up Python | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: '3.12' | |
| - name: Resolve release metadata | |
| id: meta | |
| env: | |
| INPUT_TAG: ${{ github.event.inputs.tag }} | |
| run: | | |
| set -euo pipefail | |
| if [ "${GITHUB_EVENT_NAME}" = "workflow_dispatch" ]; then | |
| TAG="${INPUT_TAG}" | |
| if git rev-parse -q --verify "refs/tags/${TAG}" >/dev/null; then | |
| CHECKOUT_REF="refs/tags/${TAG}" | |
| else | |
| CHECKOUT_REF="${GITHUB_SHA}" | |
| fi | |
| else | |
| TAG="${GITHUB_REF_NAME}" | |
| CHECKOUT_REF="${GITHUB_REF}" | |
| fi | |
| echo "${TAG}" | grep -Eq '^v[0-9]+\.[0-9]+\.[0-9]+([-.][0-9A-Za-z.-]+)?$' || { | |
| echo "invalid tag: ${TAG}" >&2 | |
| exit 1 | |
| } | |
| VERSION="${TAG#v}" | |
| PYPROJECT_VERSION="$( | |
| git show "${CHECKOUT_REF}:pyproject.toml" | | |
| python -c 'import sys, tomllib; print(tomllib.load(sys.stdin.buffer)["project"]["version"])' | |
| )" | |
| [ "${VERSION}" = "${PYPROJECT_VERSION}" ] || { | |
| echo "tag version ${VERSION} does not match pyproject version ${PYPROJECT_VERSION}" >&2 | |
| exit 1 | |
| } | |
| if [ "${GITHUB_EVENT_NAME}" = "workflow_dispatch" ] && ! git rev-parse -q --verify "refs/tags/${TAG}" >/dev/null; then | |
| git config user.name "github-actions[bot]" | |
| git config user.email "41898282+github-actions[bot]@users.noreply.github.com" | |
| git tag -a "${TAG}" "${GITHUB_SHA}" -m "Release ${TAG}" | |
| git push origin "refs/tags/${TAG}" | |
| CHECKOUT_REF="refs/tags/${TAG}" | |
| fi | |
| if printf '%s' "${VERSION}" | grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+$'; then | |
| IS_PRERELEASE=false | |
| else | |
| IS_PRERELEASE=true | |
| fi | |
| { | |
| echo "tag=${TAG}" | |
| echo "version=${VERSION}" | |
| echo "is_prerelease=${IS_PRERELEASE}" | |
| echo "checkout_ref=${CHECKOUT_REF}" | |
| echo "commit_sha=$(git rev-list -n 1 "${CHECKOUT_REF}")" | |
| } >> "${GITHUB_OUTPUT}" | |
| verify: | |
| runs-on: ubuntu-latest | |
| needs: prepare | |
| steps: | |
| - name: Check out repository | |
| uses: actions/checkout@v6 | |
| with: | |
| ref: ${{ needs.prepare.outputs.checkout_ref }} | |
| fetch-depth: 0 | |
| - name: Set up Python | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: '3.12' | |
| cache: pip | |
| - name: Install dependencies | |
| run: | | |
| python -m pip install --upgrade pip | |
| python -m pip install -e '.[dev]' | |
| - name: Lint | |
| run: ruff check . | |
| - name: Format check | |
| run: ruff format --check . | |
| - name: Run tests | |
| run: python -m pytest -q | |
| - name: Build package | |
| run: python -m build | |
| release: | |
| needs: [prepare, verify] | |
| strategy: | |
| fail-fast: false | |
| max-parallel: 1 | |
| matrix: | |
| include: | |
| - runner: ubuntu-latest | |
| target_os: linux | |
| target_arch: amd64 | |
| archive_format: tar.gz | |
| - runner: macos-latest | |
| target_os: darwin | |
| target_arch: arm64 | |
| archive_format: tar.gz | |
| - runner: macos-15-intel | |
| target_os: darwin | |
| target_arch: amd64 | |
| archive_format: tar.gz | |
| - runner: windows-latest | |
| target_os: windows | |
| target_arch: amd64 | |
| archive_format: zip | |
| runs-on: ${{ matrix.runner }} | |
| defaults: | |
| run: | |
| shell: bash | |
| env: | |
| TAG: ${{ needs.prepare.outputs.tag }} | |
| VERSION: ${{ needs.prepare.outputs.version }} | |
| steps: | |
| - name: Check out repository | |
| uses: actions/checkout@v6 | |
| with: | |
| ref: ${{ needs.prepare.outputs.checkout_ref }} | |
| fetch-depth: 0 | |
| - name: Set up Python | |
| if: ${{ matrix.target_os != 'linux' }} | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: '3.12' | |
| cache: pip | |
| - name: Install dependencies | |
| if: ${{ matrix.target_os != 'linux' }} | |
| run: | | |
| python -m pip install --upgrade pip | |
| python -m pip install -e '.[dev]' | |
| - name: Build native binary | |
| if: ${{ matrix.target_os != 'linux' }} | |
| run: | | |
| python -m PyInstaller atlassian.spec --clean --noconfirm | |
| python - <<'PY' | |
| import subprocess | |
| import sys | |
| from pathlib import Path | |
| executable = Path("dist") / "atlassian" / ( | |
| "atlassian.exe" if sys.platform == "win32" else "atlassian" | |
| ) | |
| subprocess.run([str(executable), "--help"], check=True, stdout=subprocess.DEVNULL) | |
| PY | |
| - name: Build Linux binary | |
| if: ${{ matrix.target_os == 'linux' }} | |
| run: | | |
| docker run --rm \ | |
| --platform linux/amd64 \ | |
| -e GITHUB_WORKSPACE=/workspace \ | |
| -v "${GITHUB_WORKSPACE}:/workspace" \ | |
| -w /workspace \ | |
| python:3.12-bullseye \ | |
| /bin/bash /workspace/.github/scripts/build-linux-compatible.sh | |
| - name: Package archive | |
| id: package | |
| run: | | |
| python .github/scripts/package_release_archive.py \ | |
| --version "${VERSION}" \ | |
| --target-os "${{ matrix.target_os }}" \ | |
| --target-arch "${{ matrix.target_arch }}" \ | |
| --archive-format "${{ matrix.archive_format }}" | |
| - name: Generate release notes | |
| run: python .github/scripts/generate_release_notes.py "${TAG}" release-notes.md | |
| - name: Upload platform archive | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| token: ${{ secrets.RELEASE_TOKEN || github.token }} | |
| tag_name: ${{ needs.prepare.outputs.tag }} | |
| target_commitish: ${{ needs.prepare.outputs.commit_sha }} | |
| prerelease: ${{ needs.prepare.outputs.is_prerelease == 'true' }} | |
| body_path: release-notes.md | |
| overwrite_files: true | |
| files: ${{ steps.package.outputs.archive_name }} | |
| checksums: | |
| needs: [prepare, release] | |
| runs-on: ubuntu-latest | |
| env: | |
| TAG: ${{ needs.prepare.outputs.tag }} | |
| steps: | |
| - name: Check out repository | |
| uses: actions/checkout@v6 | |
| with: | |
| ref: ${{ needs.prepare.outputs.checkout_ref }} | |
| fetch-depth: 0 | |
| - name: Generate release notes | |
| run: python .github/scripts/generate_release_notes.py "${TAG}" release-notes.md | |
| - name: Build release checksums | |
| env: | |
| GH_TOKEN: ${{ secrets.RELEASE_TOKEN || github.token }} | |
| run: | | |
| set -euo pipefail | |
| mkdir -p release-assets | |
| gh release download "${TAG}" --repo "${GITHUB_REPOSITORY}" --pattern 'atlassian-cli_*.tar.gz' --dir release-assets | |
| gh release download "${TAG}" --repo "${GITHUB_REPOSITORY}" --pattern 'atlassian-cli_*.zip' --dir release-assets | |
| cd release-assets | |
| sha256sum atlassian-cli_* > checksums.txt | |
| - name: Upload checksums | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| token: ${{ secrets.RELEASE_TOKEN || github.token }} | |
| tag_name: ${{ needs.prepare.outputs.tag }} | |
| body_path: release-notes.md | |
| overwrite_files: true | |
| files: release-assets/checksums.txt | |
| notify: | |
| needs: [prepare, checksums] | |
| if: ${{ always() && needs.prepare.result == 'success' && needs.checksums.result == 'success' }} | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Notify WeCom release | |
| env: | |
| GH_TOKEN: ${{ secrets.RELEASE_TOKEN || github.token }} | |
| WECHAT_WEBHOOK_URL: ${{ secrets.WECHAT_WEBHOOK_URL }} | |
| TAG: ${{ needs.prepare.outputs.tag }} | |
| VERSION: ${{ needs.prepare.outputs.version }} | |
| REPOSITORY: ${{ github.repository }} | |
| RELEASE_URL: https://github.com/${{ github.repository }}/releases/tag/${{ needs.prepare.outputs.tag }} | |
| run: | | |
| set -euo pipefail | |
| if [ -z "${WECHAT_WEBHOOK_URL}" ]; then | |
| echo "WECHAT_WEBHOOK_URL secret is required for release notifications" >&2 | |
| exit 1 | |
| fi | |
| gh release view "${TAG}" \ | |
| --repo "${REPOSITORY}" \ | |
| --json body \ | |
| --jq '.body // ""' > release-notes.txt | |
| python - <<'PY' > wecom-payload.json | |
| import json | |
| import os | |
| release_notes = open("release-notes.txt", encoding="utf-8").read().strip() | |
| if len(release_notes) > 1800: | |
| release_notes = f"{release_notes[:1800]}\n...(truncated)" | |
| content = "\n".join( | |
| [ | |
| f"{os.environ['REPOSITORY']} {os.environ['TAG']} published.", | |
| f"Version: {os.environ['VERSION']}", | |
| f"Release: {os.environ['RELEASE_URL']}", | |
| "", | |
| "Release notes:", | |
| release_notes or "(empty)", | |
| ] | |
| ) | |
| print( | |
| json.dumps( | |
| { | |
| "msgtype": "text", | |
| "text": { | |
| "content": content, | |
| }, | |
| }, | |
| ensure_ascii=False, | |
| ) | |
| ) | |
| PY | |
| curl -fsS \ | |
| -X POST \ | |
| -H 'Content-Type: application/json' \ | |
| --data @wecom-payload.json \ | |
| "${WECHAT_WEBHOOK_URL}" |