Skip to content

Commit 3a1064b

Browse files
unity-xcode-builder@v1.4.0 (#25)
- updated xcode version handling - refactored action to be more robust and reliable
1 parent 9342b48 commit 3a1064b

File tree

8 files changed

+99
-82
lines changed

8 files changed

+99
-82
lines changed

.github/workflows/build-options.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
],
1717
"xcode-version": [
1818
"16.3",
19-
"16.4"
19+
""
2020
],
2121
"exclude": [
2222
{

.github/workflows/build.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,13 +83,13 @@ jobs:
8383
- run: openupm add com.virtualmaker.buildalon
8484
name: Add Build Pipeline Package
8585
working-directory: ${{ env.UNITY_PROJECT_PATH }}
86-
- uses: buildalon/unity-action@v1
86+
- uses: buildalon/unity-action@v2
8787
name: '${{ matrix.build-target }}-Validate'
8888
with:
8989
build-target: ${{ matrix.build-target }}
9090
log-name: '${{ matrix.build-target }}-Validate'
9191
args: '-quit -nographics -batchmode -executeMethod Buildalon.Editor.BuildPipeline.UnityPlayerBuildTools.ValidateProject -importTMProEssentialsAsset'
92-
- uses: buildalon/unity-action@v1
92+
- uses: buildalon/unity-action@v2
9393
name: '${{ matrix.build-target }}-Build'
9494
with:
9595
build-target: ${{ matrix.build-target }}

.github/workflows/validate.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ on:
33
push:
44
branches: ['main']
55
pull_request:
6-
types: [opened, reopened, synchronize, ready_for_review]
76
branches: ['*']
7+
types: [opened, reopened, synchronize, ready_for_review]
88
workflow_dispatch: # Allows you to run this workflow manually from the Actions tab
99
concurrency:
1010
group: ${{ github.workflow }}-${{ github.ref }}

dist/index.js

Lines changed: 40 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -58506,46 +58506,54 @@ const xcodebuild = '/usr/bin/xcodebuild';
5850658506
const xcrun = '/usr/bin/xcrun';
5850758507
const WORKSPACE = process.env.GITHUB_WORKSPACE || process.cwd();
5850858508
async function GetOrSetXcodeVersion() {
58509-
let xcodeVersionString = core.getInput('xcode-version');
58510-
if (xcodeVersionString) {
58511-
core.info(`Setting xcode version to ${xcodeVersionString}`);
58512-
let xcodeVersionOutput = '';
58513-
const installedExitCode = await (0, exec_1.exec)('xcodes', ['installed'], {
58514-
listeners: {
58515-
stdout: (data) => {
58516-
xcodeVersionOutput += data.toString();
58517-
}
58518-
}
58519-
});
58520-
if (installedExitCode !== 0) {
58521-
throw new Error('Failed to get installed Xcode versions!');
58522-
}
58523-
const installedXcodeVersions = xcodeVersionOutput.split('\n').map(line => {
58524-
const match = line.match(/(\d+\.\d+(\s\w+)?)/);
58525-
return match ? match[1] : null;
58526-
}).filter(Boolean);
58527-
core.info(`Installed Xcode versions:`);
58528-
installedXcodeVersions.forEach(version => core.info(` > ${version}`));
58529-
if (installedXcodeVersions.length === 0 || !xcodeVersionString.includes('latest')) {
58530-
if (installedXcodeVersions.length === 0 || !installedXcodeVersions.includes(xcodeVersionString)) {
58531-
throw new Error(`Xcode version ${xcodeVersionString} is not installed! You will need to install this is a step before this one.`);
58509+
let xcodeVersionString = core.getInput('xcode-version') || 'latest';
58510+
core.info(`Setting xcode version to ${xcodeVersionString}`);
58511+
let xcodeVersionOutput = '';
58512+
const installedExitCode = await (0, exec_1.exec)('xcodes', ['installed'], {
58513+
listeners: {
58514+
stdout: (data) => {
58515+
xcodeVersionOutput += data.toString();
5853258516
}
5853358517
}
58534-
else {
58535-
const nonBetaVersions = installedXcodeVersions.filter(v => !/Beta/i.test(v));
58536-
if (nonBetaVersions.length === 0) {
58537-
throw new Error('No Xcode versions installed!');
58538-
}
58539-
xcodeVersionString = nonBetaVersions[nonBetaVersions.length - 1];
58518+
});
58519+
if (installedExitCode !== 0) {
58520+
throw new Error('Failed to get installed Xcode versions!');
58521+
}
58522+
const installedLines = xcodeVersionOutput.split('\n').filter(l => l.trim().length > 0);
58523+
const installedXcodeEntries = installedLines.map(line => {
58524+
const match = line.match(/^(\d+\.\d+)/);
58525+
if (!match) {
58526+
return null;
58527+
}
58528+
const version = match[1];
58529+
const isBeta = /Beta/i.test(line);
58530+
const isRC = /(Release[_\s]?Candidate|\bRC\b)/i.test(line);
58531+
const isSelected = /(Selected)/i.test(line);
58532+
return { version, raw: line, isBeta, isRC, isSelected };
58533+
}).filter(Boolean);
58534+
core.info(`Installed Xcode versions:`);
58535+
installedXcodeEntries.forEach(e => core.info(` > ${e.version}${e.isBeta ? ' (Beta)' : e.isRC ? ' (RC)' : ''}`));
58536+
if (installedXcodeEntries.length === 0 || !xcodeVersionString.includes('latest')) {
58537+
if (installedXcodeEntries.length === 0 || !installedXcodeEntries.some(e => e.version === xcodeVersionString)) {
58538+
throw new Error(`Xcode version ${xcodeVersionString} is not installed! You will need to install this in a step before this one.`);
58539+
}
58540+
}
58541+
else {
58542+
const stableVersions = installedXcodeEntries.filter(e => !e.isBeta && !e.isRC);
58543+
if (stableVersions.length === 0) {
58544+
throw new Error('No stable (non-Beta / non-RC) Xcode versions installed!');
5854058545
}
58541-
core.info(`Selecting latest installed Xcode version ${xcodeVersionString}...`);
58546+
xcodeVersionString = stableVersions[stableVersions.length - 1].version;
58547+
}
58548+
if (installedXcodeEntries.some(e => e.isSelected && e.version !== xcodeVersionString)) {
58549+
core.info(`Selecting new Xcode version ${xcodeVersionString}...`);
5854258550
const selectExitCode = await (0, exec_1.exec)('xcodes', ['select', xcodeVersionString]);
5854358551
if (selectExitCode !== 0) {
5854458552
throw new Error(`Failed to select Xcode version ${xcodeVersionString}!`);
5854558553
}
58554+
await (0, exec_1.exec)('xcodes', ['installed']);
5854658555
}
58547-
await (0, exec_1.exec)('xcodes', ['installed']);
58548-
let xcodeVersionOutput = '';
58556+
xcodeVersionOutput = '';
5854958557
await (0, exec_1.exec)('xcodebuild', ['-version'], {
5855058558
listeners: {
5855158559
stdout: (data) => {

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.

package-lock.json

Lines changed: 6 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "unity-xcode-builder",
3-
"version": "1.3.4",
3+
"version": "1.4.0",
44
"description": "A GitHub Action to build, archive, and upload Unity exported xcode projects.",
55
"author": "buildalon",
66
"license": "MIT",
@@ -25,7 +25,7 @@
2525
"uuid": "^10.0.0"
2626
},
2727
"devDependencies": {
28-
"@types/node": "^22.18.1",
28+
"@types/node": "^22.18.5",
2929
"@types/plist": "^3.0.5",
3030
"@types/semver": "^7.7.1",
3131
"@types/uuid": "^10.0.0",

src/xcode.ts

Lines changed: 46 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -31,58 +31,67 @@ const xcrun = '/usr/bin/xcrun';
3131
const WORKSPACE = process.env.GITHUB_WORKSPACE || process.cwd();
3232

3333
export async function GetOrSetXcodeVersion(): Promise<SemVer> {
34-
let xcodeVersionString = core.getInput('xcode-version');
34+
let xcodeVersionString = core.getInput('xcode-version') || 'latest';
3535

36-
if (xcodeVersionString) {
37-
core.info(`Setting xcode version to ${xcodeVersionString}`);
38-
let xcodeVersionOutput = '';
36+
core.info(`Setting xcode version to ${xcodeVersionString}`);
37+
let xcodeVersionOutput = '';
3938

40-
const installedExitCode = await exec('xcodes', ['installed'], {
41-
listeners: {
42-
stdout: (data: Buffer) => {
43-
xcodeVersionOutput += data.toString();
44-
}
39+
const installedExitCode = await exec('xcodes', ['installed'], {
40+
listeners: {
41+
stdout: (data: Buffer) => {
42+
xcodeVersionOutput += data.toString();
4543
}
46-
});
47-
48-
if (installedExitCode !== 0) {
49-
throw new Error('Failed to get installed Xcode versions!');
5044
}
45+
});
5146

52-
const installedXcodeVersions = xcodeVersionOutput.split('\n').map(line => {
53-
const match = line.match(/(\d+\.\d+(\s\w+)?)/);
54-
return match ? match[1] : null;
55-
}).filter(Boolean) as string[];
56-
57-
core.info(`Installed Xcode versions:`);
58-
installedXcodeVersions.forEach(version => core.info(` > ${version}`));
59-
60-
if (installedXcodeVersions.length === 0 || !xcodeVersionString.includes('latest')) {
61-
if (installedXcodeVersions.length === 0 || !installedXcodeVersions.includes(xcodeVersionString)) {
62-
throw new Error(`Xcode version ${xcodeVersionString} is not installed! You will need to install this is a step before this one.`);
63-
}
64-
} else {
65-
// Exclude versions containing 'Beta' and select the latest version
66-
const nonBetaVersions = installedXcodeVersions.filter(v => !/Beta/i.test(v));
67-
68-
if (nonBetaVersions.length === 0) {
69-
throw new Error('No Xcode versions installed!');
70-
}
47+
if (installedExitCode !== 0) {
48+
throw new Error('Failed to get installed Xcode versions!');
49+
}
50+
51+
// Keep full lines so we can detect Beta & Release Candidate builds
52+
const installedLines = xcodeVersionOutput.split('\n').filter(l => l.trim().length > 0);
53+
type XcodeInstallEntry = { version: string; raw: string; isBeta: boolean; isRC: boolean; isSelected?: boolean; };
54+
const installedXcodeEntries: XcodeInstallEntry[] = installedLines.map(line => {
55+
const match = line.match(/^(\d+\.\d+)/); // first number like 16.4, 26.0
56+
if (!match) { return null; }
57+
const version = match[1];
58+
const isBeta = /Beta/i.test(line);
59+
// Detect various RC naming styles (Release Candidate, Release_Candidate, RC suffix/word)
60+
const isRC = /(Release[_\s]?Candidate|\bRC\b)/i.test(line);
61+
const isSelected = /(Selected)/i.test(line);
62+
return { version, raw: line, isBeta, isRC, isSelected };
63+
}).filter(Boolean) as XcodeInstallEntry[];
64+
65+
core.info(`Installed Xcode versions:`);
66+
installedXcodeEntries.forEach(e => core.info(` > ${e.version}${e.isBeta ? ' (Beta)' : e.isRC ? ' (RC)' : ''}`));
67+
68+
if (installedXcodeEntries.length === 0 || !xcodeVersionString.includes('latest')) {
69+
if (installedXcodeEntries.length === 0 || !installedXcodeEntries.some(e => e.version === xcodeVersionString)) {
70+
throw new Error(`Xcode version ${xcodeVersionString} is not installed! You will need to install this in a step before this one.`);
71+
}
72+
} else {
73+
// Exclude Beta & Release Candidate versions when selecting 'latest'
74+
const stableVersions = installedXcodeEntries.filter(e => !e.isBeta && !e.isRC);
7175

72-
xcodeVersionString = nonBetaVersions[nonBetaVersions.length - 1];
76+
if (stableVersions.length === 0) {
77+
throw new Error('No stable (non-Beta / non-RC) Xcode versions installed!');
7378
}
7479

75-
core.info(`Selecting latest installed Xcode version ${xcodeVersionString}...`);
80+
xcodeVersionString = stableVersions[stableVersions.length - 1].version;
81+
}
82+
83+
if (installedXcodeEntries.some(e => e.isSelected && e.version !== xcodeVersionString)) {
84+
core.info(`Selecting new Xcode version ${xcodeVersionString}...`);
7685
const selectExitCode = await exec('xcodes', ['select', xcodeVersionString]);
7786

7887
if (selectExitCode !== 0) {
7988
throw new Error(`Failed to select Xcode version ${xcodeVersionString}!`);
8089
}
81-
}
8290

83-
await exec('xcodes', ['installed']);
91+
await exec('xcodes', ['installed']);
92+
}
8493

85-
let xcodeVersionOutput = '';
94+
xcodeVersionOutput = '';
8695
await exec('xcodebuild', ['-version'], {
8796
listeners: {
8897
stdout: (data: Buffer) => {

0 commit comments

Comments
 (0)