-
Notifications
You must be signed in to change notification settings - Fork 10
181 lines (162 loc) · 7.25 KB
/
Copy pathsemantic-release.yml
File metadata and controls
181 lines (162 loc) · 7.25 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
179
180
181
name: Semantic Release
on:
workflow_run:
workflows: ["TestPyPI Publishing"]
types: [completed]
branches: [main]
workflow_dispatch:
inputs:
commit:
description: 'Commit hash (for historical releases)'
required: false
type: string
version:
description: 'Version (for historical releases)'
required: false
type: string
force_level:
description: 'Force a specific bump level (auto = commit analysis)'
required: false
default: 'auto'
type: choice
options:
- auto
- major
- minor
- patch
- prerelease
permissions:
contents: write
packages: write
concurrency:
group: "semantic-release"
cancel-in-progress: false
jobs:
preview:
name: Preview next version
runs-on: ubuntu-latest
timeout-minutes: 20
permissions:
contents: write
packages: write
id-token: write
# Only release from main: guard workflow_dispatch against feature-branch runs.
# No release: commit-message filter — python-semantic-release does not emit
# such commits, so the gate would be dead; the release-approval environment
# on the release job is the human gate.
if: |
(github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main') ||
(github.event_name == 'workflow_run' && github.event.workflow_run.conclusion == 'success')
steps:
- name: Checkout code
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}
- name: Setup UV
uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2
- name: Install dependencies
# ORB_SKIP_UI_BUILD: preview only needs python-semantic-release, not the
# SPA bundle; bun is not installed here and the build hook would hang.
env:
ORB_SKIP_UI_BUILD: "1"
run: uv sync
- name: Compute next version (dry run)
id: next_version
run: |
FORCE_FLAG=${{ (inputs.force_level != '' && inputs.force_level != 'auto') && format('--{0}', inputs.force_level) || '' }}
NEXT=$(uv run semantic-release version --print $FORCE_FLAG 2>/dev/null || echo "no-release")
echo "next_version=$NEXT" >> "$GITHUB_OUTPUT"
{
echo "## Semantic Release Preview"
echo ""
echo "Next version: **$NEXT**"
} >> "$GITHUB_STEP_SUMMARY"
release:
name: Semantic Release
runs-on: ubuntu-latest
timeout-minutes: 30
needs: [preview]
environment: release-approval
permissions:
contents: write
packages: write
id-token: write # required by python-semantic-release (GitHub App token)
steps:
- name: Checkout code
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
fetch-depth: 0
# The composite below mints the App token and resets the remote
# URL to authenticate as the ORB CICD App. If actions/checkout
# also persists the default GITHUB_TOKEN as an extraheader git
# config entry, that header beats the URL-embedded token at push
# time and the request lands as github-actions[bot] - which is
# not in the main branch protection bypass list and is rejected
# with GH006. Skip the persistence so the composite's remote
# URL is the sole credential source.
persist-credentials: false
- name: ORB CICD App token
id: cicd
uses: ./.github/actions/orb-cicd-app-token
with:
client-id: ${{ secrets.GH_APP_CLIENT_ID }}
private-key: ${{ secrets.GH_APP_PRIVATE_KEY }}
- name: Setup UV
uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2
- name: Setup Bun (for UI static bundle)
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2
with:
bun-version: "1.2.15" # pinned; update intentionally to avoid surprise breakage
# Build the SPA bundle HERE, on the host, where Setup Bun put bun on PATH.
# This must run on the host — NOT via the setup.py build hook — because the
# next step (Python Semantic Release) runs `make semantic-release-build`
# (python -m build) INSIDE a Docker container that has no bun/uv/curl. With
# the bundle already at src/orb/ui/_static/, the in-container build hook
# sees it present and skips the build, so `python -m build` succeeds.
# build_ui.sh uses an ephemeral venv under $TMPDIR (auto-removed), so no
# host .venv is left to break the container's mounted-workspace interpreter.
- name: Build UI static bundle (host — bun is unavailable in the release container)
run: make ui-build
- name: Python Semantic Release
id: release
uses: python-semantic-release/python-semantic-release@39dd2052f2ce8282a5d932c31d58a2ca06d2550e # v10.6.1
with:
github_token: ${{ steps.cicd.outputs.token }}
git_committer_name: ${{ steps.cicd.outputs.committer-name }}
git_committer_email: ${{ steps.cicd.outputs.committer-email }}
force: ${{ inputs.force_level != 'auto' && inputs.force_level || '' }}
- name: Publish to GitHub Release Assets
uses: python-semantic-release/publish-action@5a5718ce47b892ef699f2972dae122297771d641 # v10.6.1
if: steps.release.outputs.released == 'true'
with:
github_token: ${{ steps.cicd.outputs.token }}
tag: ${{ steps.release.outputs.tag }}
# Provenance attestation is intentionally NOT done here. The single
# canonical attestation path runs in prod-release.yml (github-assets job),
# which attests the exact wheel artifact that prod-pypi publishes and
# uploads the .intoto.jsonl to the release. A second attest call here
# would describe a different build invocation over the same files and
# upload a conflicting .intoto.jsonl asset — dual clobbered asset (H3).
- name: Install ORB
if: steps.release.outputs.released == 'true'
# This step only boots the server to export the OpenAPI spec, so it needs
# the runtime `all` extra (api + providers + ui) but NOT the ci/dev test
# tooling. --no-dev drops the default `dev` group; without it uv would
# reject `all` (which now includes `ui`) via the ui↔dev conflict.
# ORB_SKIP_UI_BUILD so building the wheel here doesn't invoke the
# (bun-less) SPA build hook.
env:
ORB_SKIP_UI_BUILD: "1"
run: uv sync --extra all --no-dev
- name: Export OpenAPI spec for Go SDK
if: steps.release.outputs.released == 'true'
run: uv run make sdk-go-export-spec
- name: Update Go SDK version
if: steps.release.outputs.released == 'true'
env:
GIT_AUTHOR_NAME: ${{ steps.cicd.outputs.committer-name }}
GIT_AUTHOR_EMAIL: ${{ steps.cicd.outputs.committer-email }}
GIT_COMMITTER_NAME: ${{ steps.cicd.outputs.committer-name }}
GIT_COMMITTER_EMAIL: ${{ steps.cicd.outputs.committer-email }}
run: uv run make sdk-go-update-version VERSION=${{ steps.release.outputs.version }}