chore: remove release repair workflows
This commit is contained in:
@@ -1,144 +0,0 @@
|
|||||||
name: Finalize Existing Release
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
inputs:
|
|
||||||
version:
|
|
||||||
description: Existing release version without the v prefix
|
|
||||||
required: true
|
|
||||||
type: string
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
finalize-release:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
env:
|
|
||||||
DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL }}
|
|
||||||
DISCORD_UPDATE_ROLE_ID: ${{ secrets.DISCORD_UPDATE_ROLE_ID }}
|
|
||||||
steps:
|
|
||||||
- name: Verify release inventory
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
REPOSITORY: ${{ github.repository }}
|
|
||||||
VERSION: ${{ inputs.version }}
|
|
||||||
run: |
|
|
||||||
node - <<'NODE'
|
|
||||||
(async () => {
|
|
||||||
const { GITHUB_TOKEN: token, REPOSITORY: repo, VERSION: version } = process.env;
|
|
||||||
const expected = [
|
|
||||||
`OpenChamber-${version}-mac-arm64.dmg`,
|
|
||||||
`OpenChamber-${version}-mac-arm64.zip`,
|
|
||||||
`OpenChamber-${version}-mac-x64.dmg`,
|
|
||||||
`OpenChamber-${version}-mac-x64.zip`,
|
|
||||||
`OpenChamber-${version}-win-x64.exe`,
|
|
||||||
'latest-mac.yml',
|
|
||||||
'latest.yml',
|
|
||||||
];
|
|
||||||
const response = await fetch(`https://api.github.com/repos/${repo}/releases/tags/v${version}`, {
|
|
||||||
headers: { Authorization: `Bearer ${token}`, Accept: 'application/vnd.github+json' },
|
|
||||||
});
|
|
||||||
if (!response.ok) throw new Error(`Failed to inspect release: ${response.status} ${await response.text()}`);
|
|
||||||
const release = await response.json();
|
|
||||||
for (const name of expected) {
|
|
||||||
const matches = release.assets.filter((asset) => asset.name === name);
|
|
||||||
if (matches.length !== 1) throw new Error(`Expected exactly one ${name}, found ${matches.length}`);
|
|
||||||
if (!Number.isSafeInteger(matches[0].size) || matches[0].size <= 0) {
|
|
||||||
throw new Error(`Release asset ${name} has invalid size ${matches[0].size}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
console.log(`Verified release v${version} inventory before finalization.`);
|
|
||||||
})().catch((error) => {
|
|
||||||
console.error(error);
|
|
||||||
process.exit(1);
|
|
||||||
});
|
|
||||||
NODE
|
|
||||||
|
|
||||||
- name: Publish release
|
|
||||||
uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2.6.2
|
|
||||||
with:
|
|
||||||
tag_name: v${{ inputs.version }}
|
|
||||||
draft: false
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
- name: Send release to Discord
|
|
||||||
if: ${{ env.DISCORD_WEBHOOK_URL != '' }}
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
VERSION: ${{ inputs.version }}
|
|
||||||
REPOSITORY: ${{ github.repository }}
|
|
||||||
UPDATE_ROLE_ID: ${{ env.DISCORD_UPDATE_ROLE_ID }}
|
|
||||||
run: |
|
|
||||||
node - <<'NODE'
|
|
||||||
(async () => {
|
|
||||||
const tag = `v${process.env.VERSION}`;
|
|
||||||
const repo = process.env.REPOSITORY;
|
|
||||||
const rawRoleId = (process.env.UPDATE_ROLE_ID || '').trim();
|
|
||||||
const updateRoleId = /^\d+$/.test(rawRoleId) ? rawRoleId : '';
|
|
||||||
|
|
||||||
const releaseRes = await fetch(`https://api.github.com/repos/${repo}/releases/tags/${tag}`, {
|
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${process.env.GITHUB_TOKEN}`,
|
|
||||||
Accept: 'application/vnd.github+json',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
if (!releaseRes.ok) {
|
|
||||||
throw new Error(`Failed to fetch release ${tag}: ${releaseRes.status} ${await releaseRes.text()}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const release = await releaseRes.json();
|
|
||||||
const description = (release.body || `OpenChamber ${tag} released.`).slice(0, 4096);
|
|
||||||
const mention = updateRoleId ? `<@&${updateRoleId}>` : '';
|
|
||||||
const payload = {
|
|
||||||
username: 'OpenChamber Releases',
|
|
||||||
...(mention ? { content: mention } : {}),
|
|
||||||
...(updateRoleId ? { allowed_mentions: { roles: [updateRoleId] } } : {}),
|
|
||||||
embeds: [{
|
|
||||||
title: release.name || `OpenChamber ${tag}`,
|
|
||||||
url: release.html_url,
|
|
||||||
description,
|
|
||||||
color: 2105893,
|
|
||||||
footer: { text: 'OpenChamber Changelog' },
|
|
||||||
}],
|
|
||||||
};
|
|
||||||
|
|
||||||
const discordRes = await fetch(process.env.DISCORD_WEBHOOK_URL, {
|
|
||||||
method: 'POST',
|
|
||||||
headers: { 'content-type': 'application/json' },
|
|
||||||
body: JSON.stringify(payload),
|
|
||||||
});
|
|
||||||
if (!discordRes.ok) {
|
|
||||||
throw new Error(`Failed to send Discord release: ${discordRes.status} ${await discordRes.text()}`);
|
|
||||||
}
|
|
||||||
})().catch((error) => {
|
|
||||||
console.error(error);
|
|
||||||
process.exit(1);
|
|
||||||
});
|
|
||||||
NODE
|
|
||||||
|
|
||||||
- name: Trigger openchamber-website site refresh
|
|
||||||
env:
|
|
||||||
WEBSITE_REPO: openchamber/openchamber-website
|
|
||||||
WEBSITE_TOKEN: ${{ secrets.OPENCHAMBER_WEBSITE_REPO_TOKEN }}
|
|
||||||
VERSION: ${{ inputs.version }}
|
|
||||||
run: |
|
|
||||||
if [ -z "$WEBSITE_TOKEN" ]; then
|
|
||||||
echo "OPENCHAMBER_WEBSITE_REPO_TOKEN not set; skip site refresh dispatch."
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
curl --fail-with-body -sS -X POST \
|
|
||||||
-H "Authorization: Bearer $WEBSITE_TOKEN" \
|
|
||||||
-H "Accept: application/vnd.github+json" \
|
|
||||||
"https://api.github.com/repos/$WEBSITE_REPO/dispatches" \
|
|
||||||
-d @- <<JSON
|
|
||||||
{
|
|
||||||
"event_type": "site_refresh_requested",
|
|
||||||
"client_payload": {
|
|
||||||
"source_repo": "${{ github.repository }}",
|
|
||||||
"release_tag": "v$VERSION"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
JSON
|
|
||||||
@@ -1,207 +0,0 @@
|
|||||||
name: Repair macOS x64 Release
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
inputs:
|
|
||||||
version:
|
|
||||||
description: Existing release version without the v prefix
|
|
||||||
required: true
|
|
||||||
type: string
|
|
||||||
ref:
|
|
||||||
description: Source ref to package
|
|
||||||
required: true
|
|
||||||
type: string
|
|
||||||
manifest_run_id:
|
|
||||||
description: Release run containing the successful arm64 latest-mac.yml artifact
|
|
||||||
required: true
|
|
||||||
type: string
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
actions: read
|
|
||||||
contents: write
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
repair-macos-x64-release:
|
|
||||||
runs-on: macos-15-intel
|
|
||||||
steps:
|
|
||||||
- name: Checkout release source
|
|
||||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
|
||||||
with:
|
|
||||||
ref: ${{ inputs.ref }}
|
|
||||||
|
|
||||||
- name: Verify requested version
|
|
||||||
env:
|
|
||||||
VERSION: ${{ inputs.version }}
|
|
||||||
run: |
|
|
||||||
PACKAGE_VERSION=$(node -p "require('./package.json').version")
|
|
||||||
if [ "$PACKAGE_VERSION" != "$VERSION" ]; then
|
|
||||||
echo "Requested version $VERSION does not match package version $PACKAGE_VERSION"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Setup bun
|
|
||||||
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
|
|
||||||
|
|
||||||
- name: Setup Node.js
|
|
||||||
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
|
||||||
with:
|
|
||||||
node-version: '22'
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: bun install --frozen-lockfile
|
|
||||||
|
|
||||||
- name: Get bundled OpenCode CLI version
|
|
||||||
id: opencode_cli_version
|
|
||||||
run: |
|
|
||||||
VERSION=$(node -p "require('./package.json').dependencies['@opencode-ai/sdk']")
|
|
||||||
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
|
|
||||||
|
|
||||||
- name: Cache bundled OpenCode CLI artifact
|
|
||||||
uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
|
|
||||||
with:
|
|
||||||
path: packages/electron/.cache/opencode-cli
|
|
||||||
key: opencode-cli-${{ runner.os }}-x64-${{ steps.opencode_cli_version.outputs.version }}
|
|
||||||
restore-keys: |
|
|
||||||
opencode-cli-${{ runner.os }}-x64-
|
|
||||||
|
|
||||||
- name: Install Apple Certificate
|
|
||||||
env:
|
|
||||||
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
|
|
||||||
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
|
|
||||||
run: |
|
|
||||||
KEYCHAIN_PATH=$RUNNER_TEMP/electron-signing.keychain-db
|
|
||||||
KEYCHAIN_PASSWORD=$(openssl rand -base64 32)
|
|
||||||
|
|
||||||
security create-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
|
|
||||||
security set-keychain-settings -lut 21600 "$KEYCHAIN_PATH"
|
|
||||||
security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
|
|
||||||
|
|
||||||
echo "$APPLE_CERTIFICATE" | base64 --decode > "$RUNNER_TEMP/certificate.p12"
|
|
||||||
security import "$RUNNER_TEMP/certificate.p12" \
|
|
||||||
-P "$APPLE_CERTIFICATE_PASSWORD" \
|
|
||||||
-A -t cert -f pkcs12 \
|
|
||||||
-k "$KEYCHAIN_PATH"
|
|
||||||
|
|
||||||
security list-keychain -d user -s "$KEYCHAIN_PATH"
|
|
||||||
security set-key-partition-list -S apple-tool:,apple:,codesign: \
|
|
||||||
-s -k "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
|
|
||||||
|
|
||||||
- name: Build Electron app
|
|
||||||
working-directory: packages/electron
|
|
||||||
env:
|
|
||||||
APPLE_ID: ${{ secrets.APPLE_ID }}
|
|
||||||
APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
|
|
||||||
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
|
||||||
ELECTRON_BUILDER_ARCH: x64
|
|
||||||
run: |
|
|
||||||
bun run build:web-assets
|
|
||||||
bun run prepare:opencode-cli
|
|
||||||
bun run verify:opencode-cli
|
|
||||||
bun run bundle:main
|
|
||||||
bun run rebuild:native
|
|
||||||
bunx electron-builder --mac --x64 --publish=never
|
|
||||||
bun run verify:opencode-cli:packaged
|
|
||||||
|
|
||||||
- name: Verify signature, entitlements, and notarization
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
APP_PATH=$(find packages/electron/dist/mac -maxdepth 2 -name "*.app" -print -quit)
|
|
||||||
if [ -z "$APP_PATH" ]; then
|
|
||||||
echo "Error: x64 .app not found"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
codesign -vv --deep --strict "$APP_PATH"
|
|
||||||
CS_INFO=$(codesign -dv --verbose=4 "$APP_PATH" 2>&1)
|
|
||||||
echo "$CS_INFO"
|
|
||||||
if ! echo "$CS_INFO" | grep -q "flags=.*runtime"; then
|
|
||||||
echo "Error: hardened runtime flag missing"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
xcrun stapler validate "$APP_PATH"
|
|
||||||
|
|
||||||
ENTITLEMENTS=$(codesign -d --entitlements :- "$APP_PATH" 2>&1 || true)
|
|
||||||
if echo "$ENTITLEMENTS" | grep -q "com.apple.security.app-sandbox"; then
|
|
||||||
echo "Error: app sandbox entitlement is present"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
for key in \
|
|
||||||
com.apple.security.cs.allow-jit \
|
|
||||||
com.apple.security.cs.allow-unsigned-executable-memory \
|
|
||||||
com.apple.security.cs.disable-library-validation
|
|
||||||
do
|
|
||||||
if ! echo "$ENTITLEMENTS" | grep -q "<key>$key</key>"; then
|
|
||||||
echo "Error: required entitlement missing: $key"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
- name: Download arm64 update manifest
|
|
||||||
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
|
|
||||||
with:
|
|
||||||
name: latest-yml-aarch64-apple-darwin
|
|
||||||
path: artifacts/latest-yml-aarch64-apple-darwin
|
|
||||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
run-id: ${{ inputs.manifest_run_id }}
|
|
||||||
|
|
||||||
- name: Finalize combined macOS update manifest
|
|
||||||
env:
|
|
||||||
LATEST_YML_DIR: ${{ github.workspace }}/artifacts
|
|
||||||
GH_REPO: ${{ github.repository }}
|
|
||||||
OPENCHAMBER_VERSION: ${{ inputs.version }}
|
|
||||||
run: |
|
|
||||||
mkdir -p artifacts/latest-yml-x86_64-apple-darwin
|
|
||||||
cp packages/electron/dist/latest-mac.yml artifacts/latest-yml-x86_64-apple-darwin/latest-mac.yml
|
|
||||||
node packages/electron/scripts/finalize-latest-yml.mjs
|
|
||||||
test -s "$RUNNER_TEMP/latest-mac.yml"
|
|
||||||
|
|
||||||
- name: Upload repaired macOS release files
|
|
||||||
uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2.6.2
|
|
||||||
with:
|
|
||||||
tag_name: v${{ inputs.version }}
|
|
||||||
draft: false
|
|
||||||
files: |
|
|
||||||
packages/electron/dist/OpenChamber-${{ inputs.version }}-mac-x64.dmg
|
|
||||||
packages/electron/dist/OpenChamber-${{ inputs.version }}-mac-x64.zip
|
|
||||||
packages/electron/dist/OpenChamber-${{ inputs.version }}-mac-x64.dmg.blockmap
|
|
||||||
packages/electron/dist/OpenChamber-${{ inputs.version }}-mac-x64.zip.blockmap
|
|
||||||
${{ runner.temp }}/latest-mac.yml
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
- name: Verify repaired release inventory
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
REPOSITORY: ${{ github.repository }}
|
|
||||||
VERSION: ${{ inputs.version }}
|
|
||||||
run: |
|
|
||||||
node - <<'NODE'
|
|
||||||
(async () => {
|
|
||||||
const { GITHUB_TOKEN: token, REPOSITORY: repo, VERSION: version } = process.env;
|
|
||||||
const expected = [
|
|
||||||
`OpenChamber-${version}-mac-arm64.dmg`,
|
|
||||||
`OpenChamber-${version}-mac-arm64.zip`,
|
|
||||||
`OpenChamber-${version}-mac-x64.dmg`,
|
|
||||||
`OpenChamber-${version}-mac-x64.zip`,
|
|
||||||
'latest-mac.yml',
|
|
||||||
];
|
|
||||||
const response = await fetch(`https://api.github.com/repos/${repo}/releases/tags/v${version}`, {
|
|
||||||
headers: { Authorization: `Bearer ${token}`, Accept: 'application/vnd.github+json' },
|
|
||||||
});
|
|
||||||
if (!response.ok) throw new Error(`Failed to inspect release: ${response.status} ${await response.text()}`);
|
|
||||||
const release = await response.json();
|
|
||||||
if (release.draft) throw new Error(`Release v${version} is still a draft`);
|
|
||||||
for (const name of expected) {
|
|
||||||
const matches = release.assets.filter((asset) => asset.name === name);
|
|
||||||
if (matches.length !== 1) throw new Error(`Expected exactly one ${name}, found ${matches.length}`);
|
|
||||||
if (!Number.isSafeInteger(matches[0].size) || matches[0].size <= 0) {
|
|
||||||
throw new Error(`Release asset ${name} has invalid size ${matches[0].size}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
console.log(`Verified published v${version} with arm64, x64, and combined macOS update assets.`);
|
|
||||||
})().catch((error) => {
|
|
||||||
console.error(error);
|
|
||||||
process.exit(1);
|
|
||||||
});
|
|
||||||
NODE
|
|
||||||
Reference in New Issue
Block a user