Skip to content
Closed
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
1 change: 1 addition & 0 deletions .github/workflows/build-tests-mac.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ jobs:
buildForAllPlatformsMacOS:
name: ${{ matrix.targetPlatform }} on ${{ matrix.unityVersion }}
runs-on: macos-latest
continue-on-error: true
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# First, let's look at the macOS workflow around line 15
cat -n .github/workflows/build-tests-mac.yml | head -30

Repository: game-ci/unity-builder

Length of output: 1057


🏁 Script executed:

# Check the Ubuntu workflow where the retry pattern is mentioned
cat -n .github/workflows/build-tests-ubuntu.yml | head -170 | tail -40

Repository: game-ci/unity-builder

Length of output: 1858


🏁 Script executed:

# Check the Windows workflow for comparison
cat -n .github/workflows/build-tests-windows.yml | head -110 | tail -40

Repository: game-ci/unity-builder

Length of output: 1818


🏁 Script executed:

# Look at the full macOS build section to see if there are retry steps
cat -n .github/workflows/build-tests-mac.yml | sed -n '30,100p'

Repository: game-ci/unity-builder

Length of output: 2765


Remove job-level continue-on-error and implement step-level retries with delays like Ubuntu/Windows.

Line 15 masks failing buildForAllPlatformsMacOS matrix runs without retrying, while fail-fast: false at line 17 only prevents matrix-wide cancellation. Ubuntu and Windows workflows implement explicit retry logic with step duplication and variable sleep delays (60–120s); macOS should follow the same pattern with a continue-on-error on the build step and conditional retry steps, not blanket job-level failure masking.

Suggested removal
-    continue-on-error: true

Then add step-level continue-on-error and explicit retry steps similar to Ubuntu/Windows.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/build-tests-mac.yml at line 15, Remove the job-level
continue-on-error (the `continue-on-error: true` on the
buildForAllPlatformsMacOS job) and instead add step-level retries for the build
step: mark the actual build step (e.g., the matrix build step/id used inside
buildForAllPlatformsMacOS) with continue-on-error: true and then add conditional
retry steps that run only if that build step failed, duplicating the build step
with incremental sleep delays (e.g., 60s then 120s) before each retry and
clearing continue-on-error on the final attempt, mirroring the Ubuntu/Windows
workflow pattern; keep fail-fast: false on the job as-is.

strategy:
fail-fast: false
matrix:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/orchestrator-async-checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ jobs:
# AWS_STACK_NAME: game-ci-github-pipelines
CHECKS_UPDATE: ${{ github.event.inputs.checksObject }}
run: |
git clone -b orchestrator-develop https://github.com/game-ci/unity-builder
git clone -b main https://github.com/game-ci/unity-builder
cd unity-builder
yarn
ls
Expand Down
24 changes: 24 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,28 @@ inputs:
default: 'false'
required: false
description: 'Skip the activation/deactivation of Unity. This assumes Unity is already activated.'
artifactOutputTypes:
description: 'Comma-separated list of output types to collect (build, logs, test-results, coverage, images, metrics, data-export, server-build, custom)'
required: false
default: 'build,logs,test-results'
artifactUploadTarget:
description: 'Where to upload artifacts: github-artifacts, storage, local, none'
required: false
default: 'github-artifacts'
artifactUploadPath:
description: 'Destination path for artifact upload (storage URI or local path)'
required: false
artifactCompression:
description: 'Compression for artifacts: none, gzip, lz4'
required: false
default: 'gzip'
artifactRetentionDays:
description: 'Retention period for uploaded artifacts in days'
required: false
default: '30'
artifactCustomTypes:
description: 'JSON string defining custom output types [{name, defaultPath, description}]'
required: false
cloneDepth:
default: '50'
required: false
Expand All @@ -292,6 +314,8 @@ outputs:
'Returns the exit code from the build scripts. This code is 0 if the build was successful. If there was an error
during activation, the code is from the activation step. If activation is successful, the code is from the project
build step.'
artifactManifestPath:
description: 'Path to the generated artifact manifest JSON file'
branding:
icon: 'box'
color: 'gray-dark'
Expand Down
624 changes: 620 additions & 4 deletions dist/index.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/index.js.map

Large diffs are not rendered by default.

62 changes: 62 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
import * as core from '@actions/core';
import path from 'node:path';
import { Action, BuildParameters, Cache, Orchestrator, Docker, ImageTag, Output } from './model';
import { Cli } from './model/cli/cli';
import MacBuilder from './model/mac-builder';
import PlatformSetup from './model/platform-setup';
import { OutputService } from './model/orchestrator/services/output/output-service';
import { OutputTypeRegistry } from './model/orchestrator/services/output/output-type-registry';
import { ArtifactUploadHandler } from './model/orchestrator/services/output/artifact-upload-handler';

async function runMain() {
try {
Expand Down Expand Up @@ -42,6 +46,64 @@ async function runMain() {
await Output.setAndroidVersionCode(buildParameters.androidVersionCode);
await Output.setEngineExitCode(exitCode);

// Artifact collection and upload (runs on both success and failure)
try {
// Register custom output types if provided
if (buildParameters.artifactCustomTypes) {
try {
const customTypes = JSON.parse(buildParameters.artifactCustomTypes);
if (Array.isArray(customTypes)) {
for (const ct of customTypes) {
OutputTypeRegistry.registerType({
name: ct.name,
defaultPath: ct.defaultPath || ct.pattern || `./${ct.name}/`,
description: ct.description || `Custom output type: ${ct.name}`,
builtIn: false,
});
}
}
} catch (parseError) {
core.warning(`Failed to parse artifactCustomTypes: ${(parseError as Error).message}`);
}
}

// Collect outputs and generate manifest
const manifestPath = path.join(buildParameters.projectPath, 'output-manifest.json');
const manifest = await OutputService.collectOutputs(
buildParameters.projectPath,
buildParameters.buildGuid,
buildParameters.artifactOutputTypes,
manifestPath,
);

core.setOutput('artifactManifestPath', manifestPath);

// Upload artifacts
const uploadConfig = ArtifactUploadHandler.parseConfig(
buildParameters.artifactUploadTarget,
buildParameters.artifactUploadPath || undefined,
buildParameters.artifactCompression,
buildParameters.artifactRetentionDays,
);

const uploadResult = await ArtifactUploadHandler.uploadArtifacts(
manifest,
uploadConfig,
buildParameters.projectPath,
);

if (!uploadResult.success) {
core.warning(
`Artifact upload completed with errors: ${uploadResult.entries
.filter((e) => !e.success)
.map((e) => `${e.type}: ${e.error}`)
.join('; ')}`,
);
}
} catch (artifactError) {
core.warning(`Artifact collection/upload failed: ${(artifactError as Error).message}`);
}

if (exitCode !== 0) {
core.setFailed(`Build failed with exit code ${exitCode}`);
}
Expand Down
12 changes: 12 additions & 0 deletions src/model/build-parameters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,12 @@ class BuildParameters {
public cacheUnityInstallationOnMac!: boolean;
public unityHubVersionOnMac!: string;
public dockerWorkspacePath!: string;
public artifactOutputTypes!: string;
public artifactUploadTarget!: string;
public artifactUploadPath!: string;
public artifactCompression!: string;
public artifactRetentionDays!: string;
public artifactCustomTypes!: string;

public static shouldUseRetainedWorkspaceMode(buildParameters: BuildParameters) {
return buildParameters.maxRetainedWorkspaces > 0 && Orchestrator.lockedWorkspace !== ``;
Expand Down Expand Up @@ -242,6 +248,12 @@ class BuildParameters {
cacheUnityInstallationOnMac: Input.cacheUnityInstallationOnMac,
unityHubVersionOnMac: Input.unityHubVersionOnMac,
dockerWorkspacePath: Input.dockerWorkspacePath,
artifactOutputTypes: Input.artifactOutputTypes,
artifactUploadTarget: Input.artifactUploadTarget,
artifactUploadPath: Input.artifactUploadPath,
artifactCompression: Input.artifactCompression,
artifactRetentionDays: Input.artifactRetentionDays,
artifactCustomTypes: Input.artifactCustomTypes,
};
}

Expand Down
24 changes: 24 additions & 0 deletions src/model/input.ts
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,30 @@ class Input {
return Input.getInput('containerRegistryImageVersion') ?? '3';
}

static get artifactOutputTypes(): string {
return Input.getInput('artifactOutputTypes') ?? 'build,logs,test-results';
}

static get artifactUploadTarget(): string {
return Input.getInput('artifactUploadTarget') ?? 'github-artifacts';
}

static get artifactUploadPath(): string {
return Input.getInput('artifactUploadPath') ?? '';
}

static get artifactCompression(): string {
return Input.getInput('artifactCompression') ?? 'gzip';
}

static get artifactRetentionDays(): string {
return Input.getInput('artifactRetentionDays') ?? '30';
}

static get artifactCustomTypes(): string {
return Input.getInput('artifactCustomTypes') ?? '';
}

static get skipActivation(): string {
return Input.getInput('skipActivation')?.toLowerCase() ?? 'false';
}
Expand Down
Loading
Loading