-
Notifications
You must be signed in to change notification settings - Fork 19
178 lines (159 loc) · 7.7 KB
/
Copy pathrelease.yml
File metadata and controls
178 lines (159 loc) · 7.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
name: Python uv Release
on:
push:
tags:
- "v*.*.*"
permissions:
contents: write
discussions: write # attach the release-linked repo Discussion (Announcements)
jobs:
release:
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v4
- name: Set up GraalVM CE Java 11
uses: graalvm/setup-graalvm@v1
with:
java-version: '21'
distribution: 'graalvm'
github-token: ${{ secrets.GITHUB_TOKEN }}
native-image-job-reports: 'true'
- name: Install jq
run: sudo apt-get update && sudo apt-get install -y jq
- name: Install uv
uses: astral-sh/setup-uv@v4
with:
enable-cache: true
- name: Set up Python
run: uv python install 3.11
- name: Install Python package dependencies
run: uv sync --all-groups --frozen
- name: Run Tests
id: test
continue-on-error: true
run: uv run make test
- name: Delete tag on failure
if: steps.test.conclusion == 'failure'
run: |
echo "Tests failed. Deleting tag ${GITHUB_REF#refs/tags/}..."
git push --delete origin ${GITHUB_REF#refs/tags/}
exit 1
- name: Inject the latest Code Analyzer JAR
run: |
# The release has multiple .jar assets (the versioned codeanalyzer-<v>.jar and an
# unversioned codeanalyzer.jar) — select only the versioned one so $CODE_ANALYZER_URL
# is a single URL.
CODE_ANALYZER_URL=$(curl -s https://api.github.com/repos/codellm-devkit/codeanalyzer-java/releases/latest | jq -r '.assets[] | select(.name | test("^codeanalyzer-[0-9].*\\.jar$")) | .browser_download_url')
echo "Downloading: $CODE_ANALYZER_URL"
wget -q "$CODE_ANALYZER_URL"
mkdir -p ${{ github.workspace }}/cldk/analysis/java/codeanalyzer/jar/
mv codeanalyzer-*.jar ${{ github.workspace }}/cldk/analysis/java/codeanalyzer/jar/
- name: Build Package
run: uv build
- name: Verify the codeanalyzer JAR is bundled
# Guard against the hatchling/.gitignore regression (issue #284): a jarless wheel
# installs fine but fails at runtime with "codeanalyzer jar not found". Fail the
# release here rather than publish a broken artifact to PyPI.
#
# The listing is captured before grepping: piping `tar tzf` (which decompresses the
# whole 32MB sdist) straight into `grep -q` lets grep close the pipe on first match,
# SIGPIPE-killing tar and — under `pipefail` — reporting a false "missing JAR".
run: |
set -euo pipefail
jar_re='codeanalyzer/jar/codeanalyzer-[0-9][^/]*\.jar$'
fail=0
for f in dist/*.whl dist/*.tar.gz; do
case "$f" in
*.whl) listing=$(unzip -l "$f") ;;
*.tar.gz) listing=$(tar tzf "$f") ;;
esac
if grep -qE "$jar_re" <<<"$listing"; then
echo " ✓ $f"
else
echo "::error::$f is missing the codeanalyzer JAR"
grep -i '\.jar' <<<"$listing" || echo " (no .jar entries at all)"
fail=1
fi
done
if [ "$fail" -ne 0 ]; then
echo "Refusing to publish a jarless release."; exit 1
fi
echo "codeanalyzer JAR present in wheel and sdist ✓"
- name: Extract release notes from CHANGELOG.md
id: notes
# Source the release body from the hand-written CHANGELOG.md section for this tag —
# deterministic and independent of PR labels — and refuse to publish/announce a blank
# body. The previous label-based changelog scraper emitted nothing for unlabeled PRs,
# which blanked the release and crashed the org announcement. See issue #289.
run: |
set -euo pipefail
version="${GITHUB_REF#refs/tags/}" # e.g. v1.4.4 — matches the "## [v1.4.4]" heading
notes=$(awk -v h="## [$version]" '
!seen && index($0, h) == 1 { seen = 1; next }
seen && index($0, "## [") == 1 { exit }
seen { print }
' CHANGELOG.md | sed '/./,$!d' | tac | sed '/./,$!d' | tac) # strip blank edges
if [ -z "$notes" ]; then
echo "::error::No CHANGELOG.md entry for $version — refusing to publish a blank release."
exit 1
fi
{
echo "notes<<__CHANGELOG_EOF__"
echo "$notes"
echo "__CHANGELOG_EOF__"
} >> "$GITHUB_OUTPUT"
echo "Release notes for $version:"; echo "$notes"
- name: Publish Release on GitHub
uses: softprops/action-gh-release@v2
with:
files: dist/*
body: ${{ steps.notes.outputs.notes }}
# Auto-open a repo-level Discussion linked to this release, seeded with
# the same notes. Requires Discussions enabled and this category to exist.
discussion_category_name: Announcements
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Mirror the release announcement into the ORG-level discussions, which are
# backed by codellm-devkit/.github. GITHUB_TOKEN can't write cross-repo, so
# this uses a PAT (ORG_DISCUSSIONS_TOKEN) with repo scope, and posts via the
# createDiscussion GraphQL mutation. The body (the CHANGELOG.md notes) is
# passed via env to avoid shell-injection, matching the repo-level post.
- name: Announce in org-level discussions (codellm-devkit/.github)
continue-on-error: true # a failed org post must not fail an otherwise-good release
env:
GH_TOKEN: ${{ secrets.ORG_DISCUSSIONS_TOKEN }}
BODY: ${{ steps.notes.outputs.notes }}
run: |
set -uo pipefail
VERSION="${GITHUB_REF#refs/tags/v}"
OWNER="codellm-devkit"; REPO=".github"; CATEGORY="Announcements"
# The mutation needs GraphQL node IDs, not names — resolve them first.
RESP=$(gh api graphql \
-f query='query($o:String!,$r:String!){repository(owner:$o,name:$r){id discussionCategories(first:25){nodes{id name}}}}' \
-f o="$OWNER" -f r="$REPO") \
|| { echo "::warning::org discussion lookup failed — skipping org announcement."; exit 0; }
REPO_ID=$(echo "$RESP" | jq -r '.data.repository.id')
CAT_ID=$(echo "$RESP" | jq -r --arg c "$CATEGORY" '.data.repository.discussionCategories.nodes[]|select(.name==$c)|.id')
if [[ -z "$REPO_ID" || "$REPO_ID" == "null" || -z "$CAT_ID" ]]; then
echo "::warning::could not resolve $OWNER/$REPO discussion category '$CATEGORY' — skipping org announcement."
exit 0
fi
gh api graphql \
-f query='mutation($rid:ID!,$cid:ID!,$t:String!,$b:String!){createDiscussion(input:{repositoryId:$rid,categoryId:$cid,title:$t,body:$b}){discussion{url}}}' \
-f rid="$REPO_ID" -f cid="$CAT_ID" \
-f t="python-sdk v$VERSION" \
-f b="$BODY"
- name: Publish package distributions to PyPI
run: uv publish --token ${{ secrets.PYPI_API_TOKEN }}
- name: Trigger docs API-reference update
# After a successful release, tell the docs repo to regenerate and PR the
# Python API reference against this tag. Requires a DOCS_DISPATCH_TOKEN
# secret: a PAT (or fine-grained token) with contents:write on
# codellm-devkit/docs. See docs-astro .github/workflows/update-api-docs.yml.
uses: peter-evans/repository-dispatch@v3
with:
token: ${{ secrets.DOCS_DISPATCH_TOKEN }}
repository: codellm-devkit/docs
event-type: sdk-release
client-payload: '{"ref": "${{ github.ref_name }}"}'