Skip to content

Commit

Permalink
reset back to electron-ghactions changes
Browse files Browse the repository at this point in the history
  • Loading branch information
MartinBarker committed Jan 26, 2025
1 parent a188d7e commit edeb264
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 42 deletions.
21 changes: 7 additions & 14 deletions .github/workflows/electron-builder.yml
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,13 @@ jobs:
run: |
echo -n "$PROVISIONING_PROFILE_BASE64" | base64 --decode > splitBySilence_macAppStore.provisionprofile
- name: (MacOS) Prepare for app notarization
if: startsWith(matrix.os, 'macos')
run: |
mkdir -p ~/private_keys/
echo '${{ secrets.APPLE_API_KEY }}' > ~/private_keys/AuthKey_${{ secrets.APPLE_API_KEY_ID }}.p8
- name: (MacOS) Download ffmpeg
if: startsWith(matrix.os, 'macos')
run: |
Expand Down Expand Up @@ -113,25 +120,11 @@ jobs:
PKG_FILE=$(ls dist/mas-universal/*.pkg)
echo "PKG_FILE=$PKG_FILE" >> $GITHUB_ENV
- name: (MacOS) Prepare for app notarization
if: startsWith(matrix.os, 'macos')
run: |
mkdir -p ~/private_keys/
echo "${{ secrets.APPLE_API_KEY }}" > ~/private_keys/AuthKey_${{ secrets.APPLE_API_KEY_ID }}.p8
chmod 600 ~/private_keys/AuthKey_${{ secrets.APPLE_API_KEY_ID }}.p8
- name: Check .p8 file and folder contents
if: startsWith(matrix.os, 'macos') && env.is_tag == 'true'
run: |
echo "Contents of ~/private_keys:"
ls -la ~/private_keys/
- name: (MacOS) Upload to Mac App Store
if: startsWith(matrix.os, 'macos') && env.is_tag == 'true'
run: |
npx tsx script/xcrun-wrapper.mts $PKG_FILE ${{ secrets.APPLE_API_KEY_ID }} ${{ secrets.APPLE_API_ISSUER }} 1552674375 com.martinbarker.digifyunique
- name: (MacOS) Upload artifacts
uses: actions/upload-artifact@v3
if: startsWith(matrix.os, 'macos') && env.is_tag == 'false'
Expand Down
108 changes: 80 additions & 28 deletions script/xcrun-wrapper.mts
Original file line number Diff line number Diff line change
Expand Up @@ -3,62 +3,114 @@
import { execa } from 'execa';
import { readFile } from 'node:fs/promises';

// Get arguments from the command line
const [filePath, apiKeyId, apiIssuer, bundleId] = process.argv.slice(2);
// we need a wrapper script because altool tends to error out very often
// https://developer.apple.com/forums/thread/698477
// and it errors if binary already exists, we want it to just silently fail in that case

if (!filePath || !apiKeyId || !apiIssuer || !bundleId) {
console.error('Usage: npx tsx xcrun-wrapper.mts <filePath> <apiKeyId> <apiIssuer> <bundleId>');
process.exit(1);
}
const args = process.argv.slice(2);

const filePath = args[0];
const apiKeyId = args[1];
const apiIssuer = args[2];
const appleId = args[3];
const bundleId = args[4];

// seems to be the same
const ascPublicId = apiIssuer;

const packageJson = JSON.parse(
await readFile(new URL('../package.json', import.meta.url)) as unknown as string
);
const packageJson = JSON.parse(await readFile(new URL('../package.json', import.meta.url)) as unknown as string);

console.log('Using version', packageJson.version);

const packageVersion = packageJson.version;
// const packageVersion = '3.39.2';

const bundleVersion = packageVersion;
const bundleShortVersionString = packageVersion;

/*
Example JSON response:
{
"tool-version": "4.060.1220",
"tool-path": "\\/Applications\\/Xcode.app\\/Contents\\/SharedFrameworks\\/ContentDeliveryServices.framework\\/Versions\\/A\\/Frameworks\\/AppStoreService.framework",
"os-version": "11.6.0",
"product-errors": [
{
"message": "Unable to upload archive.",
"userInfo": {
"NSLocalizedDescription": "Unable to upload archive.",
"NSLocalizedFailureReason": "The file 'test' cannot be found."
},
"code": -43
},
{
"message": "Unable to upload archive.",
"userInfo": {
"NSLocalizedDescription": "Unable to upload archive.",
"NSLocalizedFailureReason": "--upload-app is missing one or more required options: --type."
},
"code": -1027
}
]
}
*/

async function runAttempt() {
// Command arguments for altool
// const xcrunArgs = ['altool', '--list-apps', '--output-format', 'json', '--apiKey', apiKeyId, '--apiIssuer', apiIssuer];

const xcrunArgs = [
'altool',
'--output-format', 'json',
'--upload-package', filePath,
'--type', 'macos',
'--apiKey', apiKeyId,
'--apiIssuer', apiIssuer,
'--upload-package', filePath, '--type', 'macos',
'--apiKey', apiKeyId, '--apiIssuer', apiIssuer,
'--asc-public-id', ascPublicId,
'--apple-id', appleId,
'--bundle-id', bundleId,
'--bundle-version', bundleVersion,
'--bundle-short-version-string', bundleShortVersionString,
];

console.log('Running command: xcrun', xcrunArgs.join(' '));

try {
const { stdout } = await execa('xcrun', xcrunArgs);
console.log('Upload succeeded:', stdout);
return false; // No retry needed
console.log('stdout', stdout);
return false;
} catch (err) {
if (err instanceof Error) {
console.error('Upload failed:', err.message);

if ('stdout' in err && typeof err.stdout === 'string') {
console.error('Error details:', err.stdout);
if (err instanceof Error && 'exitCode' in err && err.exitCode === 1 && 'stdout' in err && err.stdout && typeof err.stdout === 'string') {
const errorJson = JSON.parse(err.stdout) as unknown;
if (!(errorJson != null && typeof errorJson === 'object' && 'product-errors' in errorJson && Array.isArray(errorJson['product-errors']))) {
throw new TypeError('Invalid JSON');
}
const productErrors = errorJson['product-errors'];
// Unable to authenticate
if (productErrors.some((error) => error.code === -19209)) {
console.log(productErrors);
return true; // retry
}
// "The bundle version, x.y.z, must be a higher than the previously uploaded version."
if (productErrors.some((error) => error.code === -19210)) {
console.log(productErrors);
// ignore
return false;
}
}
throw err; // Rethrow other errors
throw err;
}
}

const maxRetries = 3;

async function run() {
for (let i = 0; i < maxRetries; i += 1) {
// eslint-disable-next-line no-await-in-loop
const wantRetry = await runAttempt();
if (!wantRetry) return; // Success
console.log('Retrying in 1 second...');
if (!wantRetry) return; // success
console.log('Retrying soon');
// eslint-disable-next-line no-await-in-loop
await new Promise((resolve) => setTimeout(resolve, 1000));
}

console.log('Gave up after retries.');
console.log('gave up');
process.exitCode = 1;
}

await run();
await run();

0 comments on commit edeb264

Please sign in to comment.