Skip to content

Commit 4d5cb80

Browse files
hopefully didn't break anything
1 parent 4dedb3b commit 4d5cb80

6 files changed

Lines changed: 185 additions & 114 deletions

File tree

.github/workflows/update-release-tags.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name: Update Release Tags
22
on:
33
push:
4-
tags: '*'
4+
tags: ['*']
55
workflow_dispatch:
66
jobs:
77
update-release-tags:

dist/index.js

Lines changed: 85 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -57464,8 +57464,8 @@ exports.UnauthorizedError = void 0;
5746457464
exports.GetAppId = GetAppId;
5746557465
exports.GetLatestBundleVersion = GetLatestBundleVersion;
5746657466
exports.UpdateTestDetails = UpdateTestDetails;
57467-
exports.GetCertificate = GetCertificate;
5746857467
exports.AddBuildToTestGroups = AddBuildToTestGroups;
57468+
exports.CreateNewCertificate = CreateNewCertificate;
5746957469
const app_store_connect_api_1 = __nccwpck_require__(9073);
5747057470
const utilities_1 = __nccwpck_require__(5739);
5747157471
const core = __nccwpck_require__(2186);
@@ -57756,49 +57756,21 @@ async function UpdateTestDetails(project, whatsNew) {
5775657756
function normalizeVersion(version) {
5775757757
return version.split('.').map(part => parseInt(part, 10).toString()).join('.');
5775857758
}
57759-
async function GetCertificate(project, certificateType = null) {
57760-
await getOrCreateClient(project);
57761-
const certificateQuery = {};
57762-
if (certificateType) {
57763-
certificateQuery.query = {
57764-
'filter[certificateType]': [certificateType],
57765-
};
57766-
}
57767-
(0, utilities_1.log)(`GET /certificates?${JSON.stringify(certificateQuery.query)}`);
57768-
const { data: response, error: responseError } = await appStoreConnectClient.api.CertificatesService.certificatesGetCollection(certificateQuery);
57769-
if (responseError) {
57770-
checkAuthError(responseError);
57771-
throw new Error(`Error fetching certificates: ${JSON.stringify(responseError, null, 2)}`);
57772-
}
57773-
const responseJson = JSON.stringify(response, null, 2);
57774-
if (!response || !response.data || response.data.length === 0) {
57775-
return null;
57776-
}
57777-
(0, utilities_1.log)(responseJson);
57778-
const validCerts = response.data.filter(certificate => {
57779-
if (!certificate.attributes) {
57780-
return false;
57781-
}
57782-
const isExpired = new Date(certificate.attributes.expirationDate) < new Date();
57783-
return certificate.attributes.activated && !isExpired;
57784-
});
57785-
return validCerts.length === 0 ? null : validCerts[0];
57786-
}
5778757759
async function AddBuildToTestGroups(project, build, testGroups) {
5778857760
await getOrCreateClient(project);
5778957761
const betaGroups = await getBetaGroupsByName(project, testGroups);
5779057762
const payload = {
5779157763
path: { id: build.id },
5779257764
body: { data: betaGroups }
5779357765
};
57794-
(0, utilities_1.log)(`POST /builds/${build.id}/relationships/betaGroups\n${JSON.stringify(payload, null, 2)}`);
57766+
core.info(`POST /builds/${build.id}/relationships/betaGroups\n${JSON.stringify(payload, null, 2)}`);
5779557767
const { data: response, error } = await appStoreConnectClient.api.BuildsService.buildsBetaGroupsCreateToManyRelationship(payload);
5779657768
if (error) {
5779757769
checkAuthError(error);
5779857770
throw new Error(`Error adding build to test group: ${JSON.stringify(error, null, 2)}`);
5779957771
}
5780057772
const responseJson = JSON.stringify(response, null, 2);
57801-
(0, utilities_1.log)(responseJson);
57773+
core.info(responseJson);
5780257774
}
5780357775
async function getBetaGroupsByName(project, groupNames) {
5780457776
await getOrCreateClient(project);
@@ -57807,7 +57779,7 @@ async function getBetaGroupsByName(project, groupNames) {
5780757779
"filter[name]": groupNames,
5780857780
}
5780957781
};
57810-
(0, utilities_1.log)(`GET /betaGroups?${JSON.stringify(request.query)}`);
57782+
core.info(`GET /betaGroups?${JSON.stringify(request.query)}`);
5781157783
const { data: response, error } = await appStoreConnectClient.api.BetaGroupsService.betaGroupsGetCollection(request);
5781257784
if (error) {
5781357785
checkAuthError(error);
@@ -57817,7 +57789,33 @@ async function getBetaGroupsByName(project, groupNames) {
5781757789
if (!response || !response.data || response.data.length === 0) {
5781857790
throw new Error(`No test groups found!`);
5781957791
}
57820-
(0, utilities_1.log)(responseJson);
57792+
core.info(responseJson);
57793+
return response.data;
57794+
}
57795+
async function CreateNewCertificate(project, certificateType, csrContent) {
57796+
await getOrCreateClient(project);
57797+
const request = {
57798+
body: {
57799+
data: {
57800+
type: 'certificates',
57801+
attributes: {
57802+
certificateType: certificateType,
57803+
csrContent: csrContent
57804+
}
57805+
}
57806+
}
57807+
};
57808+
core.info(`POST /certificates\n${JSON.stringify(request, null, 2)}`);
57809+
const { data: response, error } = await appStoreConnectClient.api.CertificatesService.certificatesCreateInstance(request);
57810+
if (error) {
57811+
checkAuthError(error);
57812+
throw new Error(`Error creating certificate: ${JSON.stringify(error, null, 2)}`);
57813+
}
57814+
const responseJson = JSON.stringify(response, null, 2);
57815+
if (!response || !response.data) {
57816+
throw new Error(`No certificate found!`);
57817+
}
57818+
core.info(responseJson);
5782157819
return response.data;
5782257820
}
5782357821

@@ -57833,11 +57831,13 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
5783357831
exports.AppleCredential = void 0;
5783457832
exports.ImportCredentials = ImportCredentials;
5783557833
exports.RemoveCredentials = RemoveCredentials;
57836-
exports.ImportCertificate = ImportCertificate;
57834+
exports.CreateSigningCertificate = CreateSigningCertificate;
5783757835
const core = __nccwpck_require__(2186);
5783857836
const exec = __nccwpck_require__(1514);
5783957837
const uuid = __nccwpck_require__(5840);
57838+
const path = __nccwpck_require__(1017);
5784057839
const fs = __nccwpck_require__(7147);
57840+
const AppStoreConnectClient_1 = __nccwpck_require__(7486);
5784157841
const security = '/usr/bin/security';
5784257842
const temp = process.env['RUNNER_TEMP'] || '.';
5784357843
const appStoreConnectKeyDir = `${process.env.HOME}/.appstoreconnect/private_keys`;
@@ -57882,7 +57882,8 @@ async function ImportCredentials() {
5788257882
if (certificateBase64) {
5788357883
const certificatePassword = core.getInput('certificate-password', { required: true });
5788457884
core.info('Importing certificate...');
57885-
const certificatePath = `${temp}/${tempCredential}.p12`;
57885+
const certificateDirectory = await getCertificateDirectory();
57886+
const certificatePath = `${certificateDirectory}/${tempCredential}.p12`;
5788657887
const certificate = Buffer.from(certificateBase64, 'base64').toString('binary');
5788757888
await fs.promises.writeFile(certificatePath, certificate, 'binary');
5788857889
await exec.exec(security, ['import', certificatePath, '-P', certificatePassword, '-A', '-t', 'cert', '-f', 'pkcs12', '-k', keychainPath]);
@@ -57893,7 +57894,6 @@ async function ImportCredentials() {
5789357894
silent: !core.isDebug()
5789457895
});
5789557896
await exec.exec(security, ['list-keychains', '-d', 'user', '-s', keychainPath, 'login.keychain-db']);
57896-
await fs.promises.unlink(certificatePath);
5789757897
if (!signingIdentity) {
5789857898
let output = '';
5789957899
core.info(`[command]${security} find-identity -v -p codesigning ${keychainPath}`);
@@ -57984,15 +57984,45 @@ async function RemoveCredentials() {
5798457984
catch (error) {
5798557985
core.error(`Failed to remove app store connect key!\n${error.stack}`);
5798657986
}
57987-
}
57988-
async function ImportCertificate(certificate) {
57989-
const tempCredential = core.getState('tempCredential');
57990-
if (!tempCredential) {
57991-
throw new Error('Missing tempCredential state');
57987+
core.info('Removing certificate directory...');
57988+
const certificateDirectory = await getCertificateDirectory();
57989+
try {
57990+
await fs.promises.rmdir(certificateDirectory, { recursive: true });
5799257991
}
57993-
const keychainPath = `${temp}/${tempCredential}.keychain-db`;
57994-
const certificatePath = `${temp}/${certificate.attributes.name}.cer`;
57995-
core.info('Importing certificate...');
57992+
catch (error) {
57993+
core.error(`Failed to remove certificate directory!\n${error.stack}`);
57994+
}
57995+
}
57996+
async function CreateSigningCertificate(project, certificateType) {
57997+
const certId = `${uuid.v4()}`;
57998+
const csrContent = await createCSR(certId);
57999+
const certificate = await (0, AppStoreConnectClient_1.CreateNewCertificate)(project, certificateType, csrContent);
58000+
const certificateDirectory = await getCertificateDirectory();
58001+
const certificateName = `${certificateType}-${certId}.cer`;
58002+
const certificatePath = `${certificateDirectory}/${certificateName}`;
58003+
core.debug(`Certificate path: ${certificatePath}`);
58004+
}
58005+
async function createCSR(certId) {
58006+
const certificateDirectory = await getCertificateDirectory();
58007+
const privateKeyPath = path.join(certificateDirectory, `signing-${certId}.key`);
58008+
const csrPath = path.join(certificateDirectory, `signing-${certId}.csr`);
58009+
await exec.exec('openssl', ['genrsa', '-out', privateKeyPath, '2048']);
58010+
await exec.exec('openssl', [
58011+
'req', '-new', '-key', privateKeyPath, '-out', csrPath,
58012+
'-subj', '/CN=Apple Distribution',
58013+
]);
58014+
return await fs.promises.readFile(csrPath, 'utf8');
58015+
}
58016+
async function getCertificateDirectory() {
58017+
const certificateDirectory = `${temp}/certificates`;
58018+
try {
58019+
await fs.promises.access(certificateDirectory, fs.constants.R_OK);
58020+
}
58021+
catch (error) {
58022+
core.info(`Creating directory ${certificateDirectory}`);
58023+
await fs.promises.mkdir(certificateDirectory, { recursive: true });
58024+
}
58025+
return certificateDirectory;
5799658026
}
5799758027

5799858028

@@ -58093,7 +58123,6 @@ const semver = __nccwpck_require__(1383);
5809358123
const AppStoreConnectClient_1 = __nccwpck_require__(7486);
5809458124
const utilities_1 = __nccwpck_require__(5739);
5809558125
const core = __nccwpck_require__(2186);
58096-
const AppleCredential_1 = __nccwpck_require__(4199);
5809758126
const xcodebuild = '/usr/bin/xcodebuild';
5809858127
const xcrun = '/usr/bin/xcrun';
5809958128
const WORKSPACE = process.env.GITHUB_WORKSPACE || process.cwd();
@@ -58492,17 +58521,24 @@ async function ExportXcodeArchive(projectRef) {
5849258521
projectRef.executablePath = await getFirstPathWithGlob(`${projectRef.exportPath}/**/*.app`);
5849358522
if (notarizeInput === 'true') {
5849458523
await signMacOSAppBundle(projectRef);
58495-
if (!projectRef.isSteamBuild) {
58496-
projectRef.executablePath = await createMacOSInstallerPkg(projectRef);
58497-
}
58498-
else {
58524+
const archiveType = core.getInput('archive-type') || 'app';
58525+
if (projectRef.isSteamBuild || archiveType === 'app') {
5849958526
const isNotarized = await isAppBundleNotarized(projectRef.executablePath);
5850058527
if (!isNotarized) {
5850158528
const zipPath = path.join(projectRef.exportPath, projectRef.executablePath.replace('.app', '.zip'));
5850258529
await (0, exec_1.exec)('ditto', ['-c', '-k', '--sequesterRsrc', '--keepParent', projectRef.executablePath, zipPath]);
5850358530
await notarizeArchive(projectRef, zipPath, projectRef.executablePath);
5850458531
}
5850558532
}
58533+
else if (archiveType === 'pkg') {
58534+
projectRef.executablePath = await createMacOSInstallerPkg(projectRef);
58535+
}
58536+
else if (archiveType === 'dmg') {
58537+
throw new Error('DMG export is not supported yet!');
58538+
}
58539+
else {
58540+
throw new Error(`Invalid archive type: ${archiveType}`);
58541+
}
5850658542
}
5850758543
}
5850858544
else {
@@ -58584,9 +58620,6 @@ async function createMacOSInstallerPkg(projectRef) {
5858458620
catch (error) {
5858558621
throw new Error(`Failed to create the pkg at: ${pkgPath}!`);
5858658622
}
58587-
const developerIdInstallerCert = await (0, AppStoreConnectClient_1.GetCertificate)(projectRef, 'MAC_INSTALLER_DISTRIBUTION');
58588-
core.info(`Found Developer ID Installer certificate: [${developerIdInstallerCert.id}] ${developerIdInstallerCert.attributes.name}`);
58589-
await (0, AppleCredential_1.ImportCertificate)(developerIdInstallerCert);
5859058623
const signPkgPath = __nccwpck_require__.ab + "sign-app-pkg.sh";
5859158624
core.info(`Signing pkg: ${pkgPath}`);
5859258625
let codesignOutput = '';

dist/index.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/AppStoreConnectClient.ts

Lines changed: 34 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,13 @@ import {
1212
PrereleaseVersion,
1313
PreReleaseVersionsGetCollectionData,
1414
BetaBuildLocalizationCreateRequest,
15-
CertificatesGetCollectionData,
1615
BetaGroupsGetCollectionData,
1716
BuildsBetaGroupsCreateToManyRelationshipData,
1817
BetaGroup,
1918
Certificate,
19+
CertificateCreateRequest,
20+
CertificateType,
21+
CertificatesCreateInstanceData,
2022
} from '@rage-against-the-pixel/app-store-connect-api/dist/app_store_connect_api';
2123
import { log } from './utilities';
2224
import core = require('@actions/core');
@@ -311,36 +313,6 @@ function normalizeVersion(version: string): string {
311313
return version.split('.').map(part => parseInt(part, 10).toString()).join('.');
312314
}
313315

314-
/**
315-
* https://developer.apple.com/documentation/appstoreconnectapi/list_and_download_certificates
316-
*/
317-
export async function GetCertificate(project: XcodeProject, certificateType: 'APPLE_PAY' | 'APPLE_PAY_MERCHANT_IDENTITY' | 'APPLE_PAY_PSP_IDENTITY' | 'APPLE_PAY_RSA' | 'DEVELOPER_ID_KEXT' | 'DEVELOPER_ID_KEXT_G2' | 'DEVELOPER_ID_APPLICATION' | 'DEVELOPER_ID_APPLICATION_G2' | 'DEVELOPMENT' | 'DISTRIBUTION' | 'IDENTITY_ACCESS' | 'IOS_DEVELOPMENT' | 'IOS_DISTRIBUTION' | 'MAC_APP_DISTRIBUTION' | 'MAC_INSTALLER_DISTRIBUTION' | 'MAC_APP_DEVELOPMENT' | 'PASS_TYPE_ID' | 'PASS_TYPE_ID_WITH_NFC' = null): Promise<Certificate> {
318-
await getOrCreateClient(project);
319-
const certificateQuery: CertificatesGetCollectionData = {};
320-
if (certificateType) {
321-
certificateQuery.query = {
322-
'filter[certificateType]': [certificateType],
323-
}
324-
}
325-
log(`GET /certificates?${JSON.stringify(certificateQuery.query)}`);
326-
const { data: response, error: responseError } = await appStoreConnectClient.api.CertificatesService.certificatesGetCollection(certificateQuery);
327-
if (responseError) {
328-
checkAuthError(responseError);
329-
throw new Error(`Error fetching certificates: ${JSON.stringify(responseError, null, 2)}`);
330-
}
331-
const responseJson = JSON.stringify(response, null, 2);
332-
if (!response || !response.data || response.data.length === 0) {
333-
return null;
334-
}
335-
log(responseJson);
336-
const validCerts = response.data.filter(certificate => {
337-
if (!certificate.attributes) { return false; }
338-
const isExpired = new Date(certificate.attributes.expirationDate) < new Date();
339-
return certificate.attributes.activated && !isExpired;
340-
});
341-
return validCerts.length === 0 ? null : validCerts[0];
342-
}
343-
344316
export async function AddBuildToTestGroups(project: XcodeProject, build: Build, testGroups: string[]): Promise<void> {
345317
await getOrCreateClient(project);
346318
const betaGroups = await getBetaGroupsByName(project, testGroups);
@@ -349,14 +321,14 @@ export async function AddBuildToTestGroups(project: XcodeProject, build: Build,
349321
path: { id: build.id },
350322
body: { data: betaGroups }
351323
};
352-
log(`POST /builds/${build.id}/relationships/betaGroups\n${JSON.stringify(payload, null, 2)}`);
324+
core.info(`POST /builds/${build.id}/relationships/betaGroups\n${JSON.stringify(payload, null, 2)}`);
353325
const { data: response, error } = await appStoreConnectClient.api.BuildsService.buildsBetaGroupsCreateToManyRelationship(payload);
354326
if (error) {
355327
checkAuthError(error);
356328
throw new Error(`Error adding build to test group: ${JSON.stringify(error, null, 2)}`);
357329
}
358330
const responseJson = JSON.stringify(response, null, 2);
359-
log(responseJson);
331+
core.info(responseJson);
360332
}
361333

362334
async function getBetaGroupsByName(project: XcodeProject, groupNames: string[]): Promise<BetaGroup[]> {
@@ -366,7 +338,7 @@ async function getBetaGroupsByName(project: XcodeProject, groupNames: string[]):
366338
"filter[name]": groupNames,
367339
}
368340
}
369-
log(`GET /betaGroups?${JSON.stringify(request.query)}`);
341+
core.info(`GET /betaGroups?${JSON.stringify(request.query)}`);
370342
const { data: response, error } = await appStoreConnectClient.api.BetaGroupsService.betaGroupsGetCollection(request);
371343
if (error) {
372344
checkAuthError(error);
@@ -376,6 +348,33 @@ async function getBetaGroupsByName(project: XcodeProject, groupNames: string[]):
376348
if (!response || !response.data || response.data.length === 0) {
377349
throw new Error(`No test groups found!`);
378350
}
379-
log(responseJson);
351+
core.info(responseJson);
352+
return response.data;
353+
}
354+
355+
export async function CreateNewCertificate(project: XcodeProject, certificateType: CertificateType, csrContent: string): Promise<Certificate> {
356+
await getOrCreateClient(project);
357+
const request: CertificatesCreateInstanceData = {
358+
body: {
359+
data: {
360+
type: 'certificates',
361+
attributes: {
362+
certificateType: certificateType,
363+
csrContent: csrContent
364+
}
365+
}
366+
}
367+
}
368+
core.info(`POST /certificates\n${JSON.stringify(request, null, 2)}`);
369+
const { data: response, error } = await appStoreConnectClient.api.CertificatesService.certificatesCreateInstance(request)
370+
if (error) {
371+
checkAuthError(error);
372+
throw new Error(`Error creating certificate: ${JSON.stringify(error, null, 2)}`);
373+
}
374+
const responseJson = JSON.stringify(response, null, 2);
375+
if (!response || !response.data) {
376+
throw new Error(`No certificate found!`);
377+
}
378+
core.info(responseJson);
380379
return response.data;
381380
}

0 commit comments

Comments
 (0)