Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 39 additions & 15 deletions .github/workflows/live-host-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -120,21 +120,32 @@ jobs:
env:
APPLE_CERTIFICATE: '${{ secrets.APPLE_CERTIFICATE }}'
APPLE_CERTIFICATE_PASSWORD: '${{ secrets.APPLE_CERTIFICATE_PASSWORD }}'
LEGACY_APPLE_CERTIFICATE: '${{ secrets.MAC_CSC_LINK }}'
LEGACY_APPLE_CERTIFICATE_PASSWORD: '${{ secrets.MAC_CSC_KEY_PASSWORD }}'
KEYCHAIN_PASSWORD: '${{ secrets.APPLE_KEYCHAIN_PASSWORD }}'
run: |
set -euo pipefail
for name in APPLE_CERTIFICATE APPLE_CERTIFICATE_PASSWORD KEYCHAIN_PASSWORD; do
if [ -z "${!name}" ]; then echo "::error::$name is required for published Qwen Live Host releases."; exit 1; fi
done
if [ -n "$APPLE_CERTIFICATE" ] && [ -n "$APPLE_CERTIFICATE_PASSWORD" ]; then
certificate_data="$APPLE_CERTIFICATE"
certificate_password="$APPLE_CERTIFICATE_PASSWORD"
elif [ -n "$LEGACY_APPLE_CERTIFICATE" ] && [ -n "$LEGACY_APPLE_CERTIFICATE_PASSWORD" ]; then
certificate_data="$LEGACY_APPLE_CERTIFICATE"
certificate_password="$LEGACY_APPLE_CERTIFICATE_PASSWORD"
else
echo '::error::A complete APPLE_CERTIFICATE pair or MAC_CSC pair is required for published Qwen Live Host releases.'
exit 1
fi
keychain_password="${KEYCHAIN_PASSWORD:-$(openssl rand -hex 32)}"
certificate="$RUNNER_TEMP/qwen-live-host.p12"
keychain="$RUNNER_TEMP/qwen-live-host.keychain-db"
printf '%s' "$APPLE_CERTIFICATE" | base64 --decode > "$certificate"
security create-keychain -p "$KEYCHAIN_PASSWORD" "$keychain"
certificate_data="${certificate_data#*base64,}"
printf '%s' "$certificate_data" | base64 --decode > "$certificate"
security create-keychain -p "$keychain_password" "$keychain"
security set-keychain-settings -lut 21600 "$keychain"
security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$keychain"
security import "$certificate" -P "$APPLE_CERTIFICATE_PASSWORD" -A -t cert -f pkcs12 -k "$keychain"
security unlock-keychain -p "$keychain_password" "$keychain"
security import "$certificate" -P "$certificate_password" -A -t cert -f pkcs12 -k "$keychain"
security list-keychains -d user -s "$keychain" login.keychain-db
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$KEYCHAIN_PASSWORD" "$keychain"
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$keychain_password" "$keychain"
identity="$(security find-identity -v -p codesigning "$keychain" | sed -n 's/.*"\(Developer ID Application:.*\)"/\1/p' | head -n 1)"
if [ -z "$identity" ]; then echo '::error::Developer ID Application identity was not found.'; exit 1; fi
{
Expand All @@ -149,18 +160,31 @@ jobs:
APPLE_API_ISSUER: '${{ secrets.APPLE_API_ISSUER }}'
APPLE_API_KEY_ID: '${{ secrets.APPLE_API_KEY }}'
APPLE_API_KEY_P8: '${{ secrets.APPLE_API_KEY_P8 }}'
LEGACY_APPLE_API_ISSUER: '${{ secrets.APPLE_NOTARY_ISSUER_ID }}'
LEGACY_APPLE_API_KEY_ID: '${{ secrets.APPLE_NOTARY_KEY_ID }}'
LEGACY_APPLE_API_KEY_P8: '${{ secrets.APPLE_NOTARY_API_KEY_P8_BASE64 }}'
APPLE_TEAM_ID: '${{ secrets.APPLE_TEAM_ID }}'
run: |
set -euo pipefail
for name in APPLE_API_ISSUER APPLE_API_KEY_ID APPLE_API_KEY_P8 APPLE_TEAM_ID; do
if [ -z "${!name}" ]; then echo "::error::$name is required for Qwen Live Host notarization."; exit 1; fi
done
key_path="$RUNNER_TEMP/AuthKey_${APPLE_API_KEY_ID}.p8"
printf '%s' "$APPLE_API_KEY_P8" > "$key_path"
if [ -n "$APPLE_API_ISSUER" ] && [ -n "$APPLE_API_KEY_ID" ] && [ -n "$APPLE_API_KEY_P8" ]; then
api_issuer="$APPLE_API_ISSUER"
api_key_id="$APPLE_API_KEY_ID"
key_path="$RUNNER_TEMP/AuthKey_${api_key_id}.p8"
printf '%s' "$APPLE_API_KEY_P8" > "$key_path"
elif [ -n "$LEGACY_APPLE_API_ISSUER" ] && [ -n "$LEGACY_APPLE_API_KEY_ID" ] && [ -n "$LEGACY_APPLE_API_KEY_P8" ]; then
api_issuer="$LEGACY_APPLE_API_ISSUER"
api_key_id="$LEGACY_APPLE_API_KEY_ID"
key_path="$RUNNER_TEMP/AuthKey_${api_key_id}.p8"
printf '%s' "$LEGACY_APPLE_API_KEY_P8" | base64 --decode > "$key_path"
else
echo '::error::A complete APPLE_API notarization set or APPLE_NOTARY set is required for Qwen Live Host notarization.'
exit 1
fi
if [ -z "$APPLE_TEAM_ID" ]; then echo '::error::APPLE_TEAM_ID is required for Qwen Live Host notarization.'; exit 1; fi
{
echo "APPLE_API_KEY=$key_path"
echo "APPLE_API_KEY_ID=$APPLE_API_KEY_ID"
echo "APPLE_API_ISSUER=$APPLE_API_ISSUER"
echo "APPLE_API_KEY_ID=$api_key_id"
echo "APPLE_API_ISSUER=$api_issuer"
echo "APPLE_TEAM_ID=$APPLE_TEAM_ID"
} >> "$GITHUB_ENV"

Expand Down
26 changes: 26 additions & 0 deletions scripts/tests/release-workflow.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,32 @@ describe('Live Host release workflow', () => {
'https://github.com/QwenLM/qwen-code/releases/download/live-host-latest',
);
});

it('accepts the repository macOS signing and notarization secrets', () => {
for (const secret of [
'MAC_CSC_LINK',
'MAC_CSC_KEY_PASSWORD',
'APPLE_NOTARY_ISSUER_ID',
'APPLE_NOTARY_KEY_ID',
'APPLE_NOTARY_API_KEY_P8_BASE64',
'APPLE_TEAM_ID',
]) {
expect(liveHostReleaseWorkflow).toContain(`secrets.${secret}`);
}
expect(liveHostReleaseWorkflow).toContain(
'keychain_password="${KEYCHAIN_PASSWORD:-$(openssl rand -hex 32)}"',
);
expect(liveHostReleaseWorkflow).toContain(
'certificate_data="${certificate_data#*base64,}"',
);
expect(liveHostReleaseWorkflow).toContain(
'printf \'%s\' "$LEGACY_APPLE_API_KEY_P8" | base64 --decode > "$key_path"',
);
expect(liveHostReleaseWorkflow).toContain('echo "APPLE_API_KEY=$key_path"');
expect(liveHostReleaseWorkflow).toContain(
'echo "APPLE_API_KEY_ID=$api_key_id"',
);
});
});

describe('Live Host CI workflow', () => {
Expand Down
Loading