Skip to content

chore: release 0.1.11 #18

chore: release 0.1.11

chore: release 0.1.11 #18

Workflow file for this run

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}"