Skip to content

Commit 3d62e92

Browse files
committed
chore(hosted-web): reconcile PR #252 live base
2 parents 81b44e4 + 55dbb50 commit 3d62e92

136 files changed

Lines changed: 10573 additions & 2326 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/release.yml

Lines changed: 35 additions & 189 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@ on:
1212
required: true
1313
default: false
1414
type: boolean
15+
reuse_existing_draft_assets:
16+
description: Promote an existing validated draft without rebuilding platform installers
17+
required: true
18+
default: false
19+
type: boolean
1520

1621
permissions:
1722
contents: write
@@ -27,6 +32,7 @@ env:
2732

2833
jobs:
2934
build:
35+
if: ${{ !inputs.reuse_existing_draft_assets }}
3036
runs-on: ubuntu-latest
3137
timeout-minutes: 30
3238

@@ -151,6 +157,7 @@ jobs:
151157
retention-days: 1
152158

153159
prepare-runtime:
160+
if: ${{ !inputs.reuse_existing_draft_assets }}
154161
runs-on: ubuntu-latest
155162
timeout-minutes: 90
156163

@@ -325,6 +332,7 @@ jobs:
325332
exit 1
326333
327334
prepare-terminal-platform-runtime:
335+
if: ${{ !inputs.reuse_existing_draft_assets }}
328336
runs-on: ubuntu-latest
329337
timeout-minutes: 90
330338

@@ -944,207 +952,45 @@ jobs:
944952
needs: [release-mac, release-win, release-linux]
945953
runs-on: ubuntu-latest
946954
timeout-minutes: 30
947-
if: ${{ github.event_name == 'workflow_dispatch' && inputs.publish_release }}
955+
if: ${{ github.event_name == 'workflow_dispatch' && inputs.publish_release && !inputs.reuse_existing_draft_assets }}
948956

949957
steps:
950-
- name: Checkout release guard
958+
- name: Checkout release promotion
951959
uses: actions/checkout@v6
952960
with:
953961
persist-credentials: false
954962

955-
- name: Upload stable download aliases
956-
env:
957-
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
958-
run: |
959-
set -euo pipefail
960-
VERSION="${RELEASE_TAG#v}"
961-
TAG="${RELEASE_TAG}"
962-
REPO="${GITHUB_REPOSITORY}"
963-
TMP_DIR="$(mktemp -d)"
964-
trap 'rm -rf "$TMP_DIR"' EXIT
965-
966-
declare -A STABLE_ALIASES=(
967-
["Agent.Teams.AI-arm64.dmg"]="Agent.Teams.AI-${VERSION}-arm64.dmg"
968-
["Agent.Teams.AI-x64.dmg"]="Agent.Teams.AI-${VERSION}-x64.dmg"
969-
["Agent.Teams.AI.Setup.exe"]="Agent.Teams.AI.Setup.${VERSION}.exe"
970-
["Agent.Teams.AI.AppImage"]="Agent.Teams.AI-${VERSION}.AppImage"
971-
["agent-teams-ai-amd64.deb"]="agent-teams-ai_${VERSION}_amd64.deb"
972-
["agent-teams-ai-x86_64.rpm"]="agent-teams-ai-${VERSION}.x86_64.rpm"
973-
["agent-teams-ai.pacman"]="agent-teams-ai-${VERSION}.pacman"
974-
)
975-
976-
declare -A LEGACY_STABLE_ALIASES=(
977-
["Claude-Agent-Teams-UI-arm64.dmg"]="Agent.Teams.AI-${VERSION}-arm64.dmg"
978-
["Claude-Agent-Teams-UI-x64.dmg"]="Agent.Teams.AI-${VERSION}-x64.dmg"
979-
["Claude-Agent-Teams-UI-Setup.exe"]="Agent.Teams.AI.Setup.${VERSION}.exe"
980-
["Claude-Agent-Teams-UI.AppImage"]="Agent.Teams.AI-${VERSION}.AppImage"
981-
["Claude-Agent-Teams-UI-amd64.deb"]="agent-teams-ai_${VERSION}_amd64.deb"
982-
["Claude-Agent-Teams-UI-x86_64.rpm"]="agent-teams-ai-${VERSION}.x86_64.rpm"
983-
["Claude-Agent-Teams-UI.pacman"]="agent-teams-ai-${VERSION}.pacman"
984-
)
985-
986-
declare -A LEGACY_UPDATER_ALIASES=(
987-
["Claude.Agent.Teams.UI-${VERSION}-arm64-mac.zip"]="Agent.Teams.AI-${VERSION}-arm64-mac.zip"
988-
["Claude.Agent.Teams.UI-${VERSION}-arm64.dmg"]="Agent.Teams.AI-${VERSION}-arm64.dmg"
989-
["Claude.Agent.Teams.UI-${VERSION}-mac.zip"]="Agent.Teams.AI-${VERSION}-x64-mac.zip"
990-
["Claude.Agent.Teams.UI-${VERSION}.dmg"]="Agent.Teams.AI-${VERSION}-x64.dmg"
991-
["Claude.Agent.Teams.UI.Setup.${VERSION}.exe"]="Agent.Teams.AI.Setup.${VERSION}.exe"
992-
["Claude.Agent.Teams.UI-${VERSION}.AppImage"]="Agent.Teams.AI-${VERSION}.AppImage"
993-
)
994-
995-
upload_aliases() {
996-
local label="$1"
997-
local -n aliases="$2"
998-
999-
for ALIAS_NAME in "${!aliases[@]}"; do
1000-
VERSIONED_NAME="${aliases[$ALIAS_NAME]}"
1001-
echo "Uploading ${label} alias: ${ALIAS_NAME} -> ${VERSIONED_NAME}"
1002-
download_once "${VERSIONED_NAME}"
1003-
cp "${TMP_DIR}/${VERSIONED_NAME}" "${TMP_DIR}/${ALIAS_NAME}"
1004-
upload_release_asset "${TMP_DIR}/${ALIAS_NAME}"
1005-
done
1006-
}
1007-
1008-
upload_release_asset() {
1009-
local path="$1"
1010-
timeout 300s gh release upload "${TAG}" "${path}" --repo "$REPO" --clobber || {
1011-
echo "Retrying upload for ${path}"
1012-
sleep 5
1013-
timeout 300s gh release upload "${TAG}" "${path}" --repo "$REPO" --clobber
1014-
}
1015-
}
1016-
1017-
download_once() {
1018-
local name="$1"
1019-
if [[ -f "${TMP_DIR}/${name}" ]]; then
1020-
return
1021-
fi
1022-
gh release download "${TAG}" \
1023-
--repo "$REPO" \
1024-
--pattern "${name}" \
1025-
--dir "$TMP_DIR" \
1026-
--clobber
1027-
}
1028-
1029-
upload_aliases "stable" STABLE_ALIASES
1030-
upload_aliases "legacy stable" LEGACY_STABLE_ALIASES
1031-
upload_aliases "legacy updater" LEGACY_UPDATER_ALIASES
1032-
1033-
- name: Publish canonical updater metadata
1034-
env:
1035-
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
1036-
run: |
1037-
set -euo pipefail
1038-
VERSION="${RELEASE_TAG#v}"
1039-
TAG="${RELEASE_TAG}"
1040-
REPO="${GITHUB_REPOSITORY}"
1041-
RELEASE_DATE="$(date -u +"%Y-%m-%dT%H:%M:%S.000Z")"
1042-
TMP_DIR="$(mktemp -d)"
1043-
cd "$TMP_DIR"
1044-
1045-
sha512_base64() {
1046-
openssl dgst -sha512 -binary "$1" | openssl base64 -A
1047-
}
1048-
1049-
file_size() {
1050-
wc -c < "$1" | tr -d '[:space:]'
1051-
}
1052-
1053-
download_asset() {
1054-
local name="$1"
1055-
gh release download "${TAG}" \
1056-
--repo "${REPO}" \
1057-
--pattern "$name" \
1058-
--dir . \
1059-
--clobber
1060-
}
1061-
1062-
# Canonical Windows feed
1063-
WIN_ASSET="Agent.Teams.AI.Setup.${VERSION}.exe"
1064-
download_asset "${WIN_ASSET}"
1065-
WIN_SHA="$(sha512_base64 "${WIN_ASSET}")"
1066-
WIN_SIZE="$(file_size "${WIN_ASSET}")"
1067-
cat > latest.yml <<EOF
1068-
version: ${VERSION}
1069-
files:
1070-
- url: ${WIN_ASSET}
1071-
sha512: ${WIN_SHA}
1072-
size: ${WIN_SIZE}
1073-
path: ${WIN_ASSET}
1074-
sha512: ${WIN_SHA}
1075-
releaseDate: '${RELEASE_DATE}'
1076-
EOF
1077-
1078-
# Canonical Linux feed
1079-
LINUX_ASSET="Agent.Teams.AI-${VERSION}.AppImage"
1080-
download_asset "${LINUX_ASSET}"
1081-
LINUX_SHA="$(sha512_base64 "${LINUX_ASSET}")"
1082-
LINUX_SIZE="$(file_size "${LINUX_ASSET}")"
1083-
cat > latest-linux.yml <<EOF
1084-
version: ${VERSION}
1085-
files:
1086-
- url: ${LINUX_ASSET}
1087-
sha512: ${LINUX_SHA}
1088-
size: ${LINUX_SIZE}
1089-
path: ${LINUX_ASSET}
1090-
sha512: ${LINUX_SHA}
1091-
releaseDate: '${RELEASE_DATE}'
1092-
EOF
1093-
1094-
# Canonical macOS feed.
1095-
# Include both architectures so legacy Intel builds can see the
1096-
# update without downloading the Apple Silicon zip.
1097-
download_asset "Agent.Teams.AI-${VERSION}-arm64-mac.zip"
1098-
download_asset "Agent.Teams.AI-${VERSION}-arm64.dmg"
1099-
download_asset "Agent.Teams.AI-${VERSION}-x64-mac.zip"
1100-
download_asset "Agent.Teams.AI-${VERSION}-x64.dmg"
1101-
MAC_ARM64_ZIP_SHA="$(sha512_base64 "Agent.Teams.AI-${VERSION}-arm64-mac.zip")"
1102-
MAC_ARM64_ZIP_SIZE="$(file_size "Agent.Teams.AI-${VERSION}-arm64-mac.zip")"
1103-
MAC_ARM64_DMG_SHA="$(sha512_base64 "Agent.Teams.AI-${VERSION}-arm64.dmg")"
1104-
MAC_ARM64_DMG_SIZE="$(file_size "Agent.Teams.AI-${VERSION}-arm64.dmg")"
1105-
MAC_X64_ZIP_SHA="$(sha512_base64 "Agent.Teams.AI-${VERSION}-x64-mac.zip")"
1106-
MAC_X64_ZIP_SIZE="$(file_size "Agent.Teams.AI-${VERSION}-x64-mac.zip")"
1107-
MAC_X64_DMG_SHA="$(sha512_base64 "Agent.Teams.AI-${VERSION}-x64.dmg")"
1108-
MAC_X64_DMG_SIZE="$(file_size "Agent.Teams.AI-${VERSION}-x64.dmg")"
1109-
cat > latest-mac.yml <<EOF
1110-
version: ${VERSION}
1111-
files:
1112-
- url: Agent.Teams.AI-${VERSION}-arm64-mac.zip
1113-
sha512: ${MAC_ARM64_ZIP_SHA}
1114-
size: ${MAC_ARM64_ZIP_SIZE}
1115-
- url: Agent.Teams.AI-${VERSION}-arm64.dmg
1116-
sha512: ${MAC_ARM64_DMG_SHA}
1117-
size: ${MAC_ARM64_DMG_SIZE}
1118-
- url: Agent.Teams.AI-${VERSION}-x64-mac.zip
1119-
sha512: ${MAC_X64_ZIP_SHA}
1120-
size: ${MAC_X64_ZIP_SIZE}
1121-
- url: Agent.Teams.AI-${VERSION}-x64.dmg
1122-
sha512: ${MAC_X64_DMG_SHA}
1123-
size: ${MAC_X64_DMG_SIZE}
1124-
path: Agent.Teams.AI-${VERSION}-arm64-mac.zip
1125-
sha512: ${MAC_ARM64_ZIP_SHA}
1126-
releaseDate: '${RELEASE_DATE}'
1127-
EOF
1128-
1129-
gh release upload "${TAG}" latest.yml latest-linux.yml latest-mac.yml --repo "${REPO}" --clobber
1130-
1131-
- name: Publish release
1132-
if: ${{ inputs.publish_release }}
963+
- name: Promote validated release assets
1133964
env:
1134965
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
966+
RELEASE_REPOSITORY: ${{ github.repository }}
967+
PUBLISH_RELEASE: 'true'
968+
ALLOW_PUBLISHED_RELEASE_RECOVERY: 'true'
969+
REDRAFT_INCOMPLETE_RELEASE: 'true'
970+
run: node scripts/ci/promote-existing-draft.mjs
971+
972+
promote-existing-draft:
973+
runs-on: ubuntu-latest
974+
timeout-minutes: 30
975+
if: ${{ github.event_name == 'workflow_dispatch' && inputs.reuse_existing_draft_assets }}
976+
977+
steps:
978+
- name: Checkout release promotion
979+
uses: actions/checkout@v6
980+
with:
981+
persist-credentials: false
982+
983+
- name: Require publication mode
984+
if: ${{ !inputs.publish_release }}
1135985
run: |
1136-
set -euo pipefail
1137-
TAG="${RELEASE_TAG}"
1138-
gh release edit "${TAG}" --repo "${GITHUB_REPOSITORY}" --draft=false --latest
986+
echo "reuse_existing_draft_assets requires publish_release=true" >&2
987+
exit 1
1139988
1140-
- name: Verify published updater channel
989+
- name: Promote existing validated draft
1141990
if: ${{ inputs.publish_release }}
1142991
env:
1143992
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
1144993
RELEASE_REPOSITORY: ${{ github.repository }}
994+
PUBLISH_RELEASE: 'true'
1145995
REDRAFT_INCOMPLETE_RELEASE: 'true'
1146-
run: bash scripts/ci/verify-published-updater-release.sh
1147-
1148-
- name: Keep release as draft
1149-
if: ${{ github.event_name == 'workflow_dispatch' && !inputs.publish_release }}
1150-
run: echo "Draft release ${RELEASE_TAG} is ready. It was not published because publish_release=false."
996+
run: node scripts/ci/promote-existing-draft.mjs

docs/RELEASE.md

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# Release Guide
22

3-
## Draft: v2.9.0 (2026-07-18)
3+
## Published: v2.9.0 (2026-07-19)
4+
5+
GitHub release: [v2.9.0](https://github.com/777genius/agent-teams-ai/releases/tag/v2.9.0).
46

57
Target branch: `dev`.
68

@@ -15,6 +17,12 @@ Draft body source for GitHub release:
1517

1618
Redesigned the team page and related workflows, added simple setup for local models, improved Cursor-style control over code changes, and fixed issues in agent setup, launch, and recovery.
1719

20+
<img width="2624" height="1652" alt="image" src="https://github.com/user-attachments/assets/b23a09f3-0f08-446f-824d-5623ff111574" />
21+
22+
<img width="853" height="684" alt="image" src="https://github.com/user-attachments/assets/f8aff8c8-88bd-4490-a856-03f6d380adda" />
23+
24+
<img width="1592" height="1110" alt="image" src="https://github.com/user-attachments/assets/00ad2f7b-5f42-4dbc-a0e0-d01401791dee" />
25+
1826
### What's New
1927

2028
- Review code changes hunk by hunk with Cursor-style accept/reject controls, undo and redo that survives app restarts, and checkpoint previews.
@@ -717,7 +725,8 @@ gh workflow run release.yml \
717725
--repo 777genius/agent-teams-ai \
718726
--ref v<VERSION> \
719727
-f release_tag=v<VERSION> \
720-
-f publish_release=true
728+
-f publish_release=true \
729+
-f reuse_existing_draft_assets=true
721730

722731
gh run list \
723732
--repo 777genius/agent-teams-ai \
@@ -727,6 +736,18 @@ gh run list \
727736
gh run watch <RUN_ID> --repo 777genius/agent-teams-ai
728737
```
729738

739+
`reuse_existing_draft_assets=true` is the normal reviewed-draft promotion path.
740+
It skips the repeated app build and platform packaging, but still verifies that
741+
the draft targets the exact tag commit, checks the SHA-256 digest of every
742+
source installer, uploads stable and compatibility aliases, generates all three
743+
canonical updater feeds, publishes the same release, and runs the updater guard.
744+
See [Existing Draft Promotion](release-promotion.md) for the full script
745+
contract, dry-run procedure, safety checks, and recovery guidance.
746+
747+
Use `reuse_existing_draft_assets=false` only when the platform installers must
748+
be rebuilt before publication. The full build path runs the same promotion
749+
script after packaging succeeds.
750+
730751
Do not use GitHub's **Publish release** button, `gh release edit --draft=false`,
731752
or any other direct draft-to-public action. Those paths bypass the
732753
`upload-stable-links` job. That job uploads the stable aliases and canonical
@@ -963,7 +984,8 @@ gh workflow run release.yml --repo 777genius/agent-teams-ai --ref v1.0.0 \
963984
# Publish the reviewed draft and generate updater metadata
964985
# Never publish the draft directly through GitHub UI or gh release edit.
965986
gh workflow run release.yml --repo 777genius/agent-teams-ai --ref v1.0.0 \
966-
-f release_tag=v1.0.0 -f publish_release=true
987+
-f release_tag=v1.0.0 -f publish_release=true \
988+
-f reuse_existing_draft_assets=true
967989

968990
# Watch the publish run, then run the required fail-fast gate from step 5.
969991
# Do not announce or close the release until that gate passes.

0 commit comments

Comments
 (0)