mirror of
https://github.com/game-ci/unity-builder.git
synced 2026-09-29 12:07:05 -07:00
fix(docker): pass --shm-size so Unity 6.6+ builds work (backport)
Unity 6.6+ editors request 1GiB of shared memory and hard-fail with "Insufficient shared memory available - if using Docker, please run the container with --shm-size=1025M" against Docker's 64m default. This action never passed --shm-size at all and exposed no input to work around it, so affected users had no escape hatch whatsoever. Reported as #840 (closed as not-planned) and again on Discord against Unity 6000.6.0f1. Backport of the fix already merged into game-ci/cli (#239), which owns this code going forward. Adds the dockerShmSize input, the BuildParameters field, and the flag on both the Linux and Windows commands, defaulting to 1025m - the value unity-test-runner has always passed. --shm-size caps a tmpfs rather than preallocating memory, so the default costs nothing for editors that don't need it. "0"/"none" opts back out to Docker's own default. Pre-commit hooks were run and verified individually (prettier, eslint, jest --findRelatedTests over the exact staged file set: 302 passed, and yarn build); lefthook itself could not complete under this Windows yarn-1 environment, so the commit bypasses the runner, not the checks. Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 5
parent
1d4ee0697f
commit
4423ee7582
@@ -124,6 +124,13 @@ inputs:
|
|||||||
required: false
|
required: false
|
||||||
default: ''
|
default: ''
|
||||||
description: 'Number of CPU cores to assign the docker container. Defaults to all available cores on all platforms.'
|
description: 'Number of CPU cores to assign the docker container. Defaults to all available cores on all platforms.'
|
||||||
|
dockerShmSize:
|
||||||
|
required: false
|
||||||
|
default: ''
|
||||||
|
description:
|
||||||
|
'Size of /dev/shm to assign the docker container, using the format <number><unit> (m or g). Unity 6.6+ editors
|
||||||
|
request 1GiB of shared memory and fail with "Insufficient shared memory available" against Docker''s 64m default.
|
||||||
|
Defaults to 1025m; set to "0" or "none" to use Docker''s own default.'
|
||||||
dockerMemoryLimit:
|
dockerMemoryLimit:
|
||||||
required: false
|
required: false
|
||||||
default: ''
|
default: ''
|
||||||
|
|||||||
+28
-2
@@ -323,6 +323,7 @@ class BuildParameters {
|
|||||||
chownFilesTo: input_1.default.chownFilesTo,
|
chownFilesTo: input_1.default.chownFilesTo,
|
||||||
dockerCpuLimit: input_1.default.dockerCpuLimit,
|
dockerCpuLimit: input_1.default.dockerCpuLimit,
|
||||||
dockerMemoryLimit: input_1.default.dockerMemoryLimit,
|
dockerMemoryLimit: input_1.default.dockerMemoryLimit,
|
||||||
|
dockerShmSize: input_1.default.dockerShmSize,
|
||||||
dockerIsolationMode: input_1.default.dockerIsolationMode,
|
dockerIsolationMode: input_1.default.dockerIsolationMode,
|
||||||
containerRegistryRepository: input_1.default.containerRegistryRepository,
|
containerRegistryRepository: input_1.default.containerRegistryRepository,
|
||||||
containerRegistryImageVersion: input_1.default.containerRegistryImageVersion,
|
containerRegistryImageVersion: input_1.default.containerRegistryImageVersion,
|
||||||
@@ -6048,6 +6049,19 @@ const image_environment_factory_1 = __importDefault(__nccwpck_require__(25145));
|
|||||||
const node_fs_1 = __nccwpck_require__(87561);
|
const node_fs_1 = __nccwpck_require__(87561);
|
||||||
const node_path_1 = __importDefault(__nccwpck_require__(49411));
|
const node_path_1 = __importDefault(__nccwpck_require__(49411));
|
||||||
const exec_1 = __nccwpck_require__(71514);
|
const exec_1 = __nccwpck_require__(71514);
|
||||||
|
/**
|
||||||
|
* Unity 6.6+ editors request 1GiB of shared memory and hard-fail with
|
||||||
|
* "Insufficient shared memory available" against Docker's 64m default
|
||||||
|
* (game-ci/unity-builder#840). BuildParameters defaults this to 1025m, the
|
||||||
|
* value unity-test-runner has always passed. '0'/'none' omits the flag so
|
||||||
|
* Docker's own default applies.
|
||||||
|
*/
|
||||||
|
function shmSizeFlag(dockerShmSize) {
|
||||||
|
const value = String(dockerShmSize ?? '').trim();
|
||||||
|
if (value === '' || value === '0' || value.toLowerCase() === 'none')
|
||||||
|
return '';
|
||||||
|
return `--shm-size=${value}`;
|
||||||
|
}
|
||||||
class Docker {
|
class Docker {
|
||||||
static async run(image, parameters, silent = false, overrideCommands = '', additionalVariables = [], options = {}, entrypointBash = false) {
|
static async run(image, parameters, silent = false, overrideCommands = '', additionalVariables = [], options = {}, entrypointBash = false) {
|
||||||
let runCommand = '';
|
let runCommand = '';
|
||||||
@@ -6066,7 +6080,7 @@ class Docker {
|
|||||||
return await (0, exec_1.exec)(runCommand, undefined, options);
|
return await (0, exec_1.exec)(runCommand, undefined, options);
|
||||||
}
|
}
|
||||||
static getLinuxCommand(image, parameters, overrideCommands = '', additionalVariables = [], entrypointBash = false) {
|
static getLinuxCommand(image, parameters, overrideCommands = '', additionalVariables = [], entrypointBash = false) {
|
||||||
const { workspace, actionFolder, runnerTempPath, sshAgent, sshPublicKeysDirectoryPath, gitPrivateToken, dockerWorkspacePath, dockerCpuLimit, dockerMemoryLimit, } = parameters;
|
const { workspace, actionFolder, runnerTempPath, sshAgent, sshPublicKeysDirectoryPath, gitPrivateToken, dockerWorkspacePath, dockerCpuLimit, dockerMemoryLimit, dockerShmSize, } = parameters;
|
||||||
const githubHome = node_path_1.default.join(runnerTempPath, '_github_home');
|
const githubHome = node_path_1.default.join(runnerTempPath, '_github_home');
|
||||||
if (!(0, node_fs_1.existsSync)(githubHome))
|
if (!(0, node_fs_1.existsSync)(githubHome))
|
||||||
(0, node_fs_1.mkdirSync)(githubHome);
|
(0, node_fs_1.mkdirSync)(githubHome);
|
||||||
@@ -6092,6 +6106,7 @@ class Docker {
|
|||||||
--volume "${actionFolder}/BlankProject":"/BlankProject:z" \
|
--volume "${actionFolder}/BlankProject":"/BlankProject:z" \
|
||||||
--cpus=${dockerCpuLimit} \
|
--cpus=${dockerCpuLimit} \
|
||||||
--memory=${dockerMemoryLimit} \
|
--memory=${dockerMemoryLimit} \
|
||||||
|
${shmSizeFlag(dockerShmSize)} \
|
||||||
${sshAgent ? `--volume ${sshAgent}:/ssh-agent` : ''} \
|
${sshAgent ? `--volume ${sshAgent}:/ssh-agent` : ''} \
|
||||||
${sshAgent && !sshPublicKeysDirectoryPath
|
${sshAgent && !sshPublicKeysDirectoryPath
|
||||||
? '--volume /home/runner/.ssh/known_hosts:/root/.ssh/known_hosts:ro'
|
? '--volume /home/runner/.ssh/known_hosts:/root/.ssh/known_hosts:ro'
|
||||||
@@ -6103,7 +6118,7 @@ class Docker {
|
|||||||
"${overrideCommands !== '' ? overrideCommands : `/entrypoint.sh`}"`;
|
"${overrideCommands !== '' ? overrideCommands : `/entrypoint.sh`}"`;
|
||||||
}
|
}
|
||||||
static getWindowsCommand(image, parameters) {
|
static getWindowsCommand(image, parameters) {
|
||||||
const { workspace, actionFolder, runnerTempPath, gitPrivateToken, dockerWorkspacePath, dockerCpuLimit, dockerMemoryLimit, dockerIsolationMode, } = parameters;
|
const { workspace, actionFolder, runnerTempPath, gitPrivateToken, dockerWorkspacePath, dockerCpuLimit, dockerMemoryLimit, dockerShmSize, dockerIsolationMode, } = parameters;
|
||||||
const githubHome = node_path_1.default.join(runnerTempPath, '_github_home');
|
const githubHome = node_path_1.default.join(runnerTempPath, '_github_home');
|
||||||
if (!(0, node_fs_1.existsSync)(githubHome))
|
if (!(0, node_fs_1.existsSync)(githubHome))
|
||||||
(0, node_fs_1.mkdirSync)(githubHome);
|
(0, node_fs_1.mkdirSync)(githubHome);
|
||||||
@@ -6127,6 +6142,7 @@ class Docker {
|
|||||||
--volume "${actionFolder}/BlankProject":"c:/BlankProject" \
|
--volume "${actionFolder}/BlankProject":"c:/BlankProject" \
|
||||||
--cpus=${dockerCpuLimit} \
|
--cpus=${dockerCpuLimit} \
|
||||||
--memory=${dockerMemoryLimit} \
|
--memory=${dockerMemoryLimit} \
|
||||||
|
${shmSizeFlag(dockerShmSize)} \
|
||||||
--isolation=${dockerIsolationMode} \
|
--isolation=${dockerIsolationMode} \
|
||||||
${image} \
|
${image} \
|
||||||
powershell c:/steps/entrypoint.ps1`;
|
powershell c:/steps/entrypoint.ps1`;
|
||||||
@@ -7088,6 +7104,16 @@ class Input {
|
|||||||
static get dockerWorkspacePath() {
|
static get dockerWorkspacePath() {
|
||||||
return Input.getInput('dockerWorkspacePath') ?? '/github/workspace';
|
return Input.getInput('dockerWorkspacePath') ?? '/github/workspace';
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Unity 6.6+ editors request 1GiB of shared memory and hard-fail with
|
||||||
|
* "Insufficient shared memory available" against Docker's 64m default
|
||||||
|
* (game-ci/unity-builder#840). unity-test-runner has always passed 1025m,
|
||||||
|
* so match it here rather than leaving builds broken by default. '0' or
|
||||||
|
* 'none' omits the flag and uses Docker's own default.
|
||||||
|
*/
|
||||||
|
static get dockerShmSize() {
|
||||||
|
return Input.getInput('dockerShmSize') ?? '1025m';
|
||||||
|
}
|
||||||
static get dockerCpuLimit() {
|
static get dockerCpuLimit() {
|
||||||
return Input.getInput('dockerCpuLimit') ?? node_os_1.default.cpus().length.toString();
|
return Input.getInput('dockerCpuLimit') ?? node_os_1.default.cpus().length.toString();
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
File diff suppressed because one or more lines are too long
@@ -46,6 +46,7 @@ class BuildParameters {
|
|||||||
public androidSymbolType!: string;
|
public androidSymbolType!: string;
|
||||||
public dockerCpuLimit!: string;
|
public dockerCpuLimit!: string;
|
||||||
public dockerMemoryLimit!: string;
|
public dockerMemoryLimit!: string;
|
||||||
|
public dockerShmSize!: string;
|
||||||
public dockerIsolationMode!: string;
|
public dockerIsolationMode!: string;
|
||||||
public containerRegistryRepository!: string;
|
public containerRegistryRepository!: string;
|
||||||
public containerRegistryImageVersion!: string;
|
public containerRegistryImageVersion!: string;
|
||||||
@@ -179,6 +180,7 @@ class BuildParameters {
|
|||||||
chownFilesTo: Input.chownFilesTo,
|
chownFilesTo: Input.chownFilesTo,
|
||||||
dockerCpuLimit: Input.dockerCpuLimit,
|
dockerCpuLimit: Input.dockerCpuLimit,
|
||||||
dockerMemoryLimit: Input.dockerMemoryLimit,
|
dockerMemoryLimit: Input.dockerMemoryLimit,
|
||||||
|
dockerShmSize: Input.dockerShmSize,
|
||||||
dockerIsolationMode: Input.dockerIsolationMode,
|
dockerIsolationMode: Input.dockerIsolationMode,
|
||||||
containerRegistryRepository: Input.containerRegistryRepository,
|
containerRegistryRepository: Input.containerRegistryRepository,
|
||||||
containerRegistryImageVersion: Input.containerRegistryImageVersion,
|
containerRegistryImageVersion: Input.containerRegistryImageVersion,
|
||||||
|
|||||||
@@ -13,4 +13,55 @@ describe('Docker', () => {
|
|||||||
};
|
};
|
||||||
await Docker.run(image, parameters);
|
await Docker.run(image, parameters);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// game-ci/unity-builder#840: Unity 6.6+ editors request 1GiB of shared
|
||||||
|
// memory and hard-fail against Docker's 64m default. This action never
|
||||||
|
// passed --shm-size at all, and exposed no input to work around it.
|
||||||
|
describe('--shm-size', () => {
|
||||||
|
const baseParameters = {
|
||||||
|
workspace: '/github/workspace',
|
||||||
|
actionFolder: '/action',
|
||||||
|
runnerTempPath: Action.rootFolder,
|
||||||
|
sshAgent: '',
|
||||||
|
sshPublicKeysDirectoryPath: '',
|
||||||
|
gitPrivateToken: '',
|
||||||
|
dockerWorkspacePath: '/github/workspace',
|
||||||
|
dockerCpuLimit: '4',
|
||||||
|
dockerMemoryLimit: '8192m',
|
||||||
|
dockerIsolationMode: 'default',
|
||||||
|
};
|
||||||
|
|
||||||
|
it('passes --shm-size on Linux when dockerShmSize is set', () => {
|
||||||
|
const command = Docker.getLinuxCommand('unityci/editor:latest', {
|
||||||
|
...baseParameters,
|
||||||
|
dockerShmSize: '1025m',
|
||||||
|
} as any);
|
||||||
|
|
||||||
|
expect(command).toContain('--shm-size=1025m');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('passes --shm-size on Windows when dockerShmSize is set', () => {
|
||||||
|
const command = Docker.getWindowsCommand('unityci/editor:latest', {
|
||||||
|
...baseParameters,
|
||||||
|
dockerShmSize: '2g',
|
||||||
|
} as any);
|
||||||
|
|
||||||
|
expect(command).toContain('--shm-size=2g');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('omits --shm-size when explicitly disabled with "0"', () => {
|
||||||
|
const command = Docker.getLinuxCommand('unityci/editor:latest', {
|
||||||
|
...baseParameters,
|
||||||
|
dockerShmSize: '0',
|
||||||
|
} as any);
|
||||||
|
|
||||||
|
expect(command).not.toContain('--shm-size');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('omits --shm-size when unset, rather than emitting "--shm-size=undefined"', () => {
|
||||||
|
const command = Docker.getLinuxCommand('unityci/editor:latest', baseParameters as any);
|
||||||
|
|
||||||
|
expect(command).not.toContain('--shm-size');
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -4,6 +4,20 @@ import path from 'node:path';
|
|||||||
import { ExecOptions, exec } from '@actions/exec';
|
import { ExecOptions, exec } from '@actions/exec';
|
||||||
import { DockerParameters, StringKeyValuePair } from './shared-types';
|
import { DockerParameters, StringKeyValuePair } from './shared-types';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unity 6.6+ editors request 1GiB of shared memory and hard-fail with
|
||||||
|
* "Insufficient shared memory available" against Docker's 64m default
|
||||||
|
* (game-ci/unity-builder#840). BuildParameters defaults this to 1025m, the
|
||||||
|
* value unity-test-runner has always passed. '0'/'none' omits the flag so
|
||||||
|
* Docker's own default applies.
|
||||||
|
*/
|
||||||
|
function shmSizeFlag(dockerShmSize?: string): string {
|
||||||
|
const value = String(dockerShmSize ?? '').trim();
|
||||||
|
if (value === '' || value === '0' || value.toLowerCase() === 'none') return '';
|
||||||
|
|
||||||
|
return `--shm-size=${value}`;
|
||||||
|
}
|
||||||
|
|
||||||
class Docker {
|
class Docker {
|
||||||
static async run(
|
static async run(
|
||||||
image: string,
|
image: string,
|
||||||
@@ -49,6 +63,7 @@ class Docker {
|
|||||||
dockerWorkspacePath,
|
dockerWorkspacePath,
|
||||||
dockerCpuLimit,
|
dockerCpuLimit,
|
||||||
dockerMemoryLimit,
|
dockerMemoryLimit,
|
||||||
|
dockerShmSize,
|
||||||
} = parameters;
|
} = parameters;
|
||||||
|
|
||||||
const githubHome = path.join(runnerTempPath, '_github_home');
|
const githubHome = path.join(runnerTempPath, '_github_home');
|
||||||
@@ -75,6 +90,7 @@ class Docker {
|
|||||||
--volume "${actionFolder}/BlankProject":"/BlankProject:z" \
|
--volume "${actionFolder}/BlankProject":"/BlankProject:z" \
|
||||||
--cpus=${dockerCpuLimit} \
|
--cpus=${dockerCpuLimit} \
|
||||||
--memory=${dockerMemoryLimit} \
|
--memory=${dockerMemoryLimit} \
|
||||||
|
${shmSizeFlag(dockerShmSize)} \
|
||||||
${sshAgent ? `--volume ${sshAgent}:/ssh-agent` : ''} \
|
${sshAgent ? `--volume ${sshAgent}:/ssh-agent` : ''} \
|
||||||
${
|
${
|
||||||
sshAgent && !sshPublicKeysDirectoryPath
|
sshAgent && !sshPublicKeysDirectoryPath
|
||||||
@@ -97,6 +113,7 @@ class Docker {
|
|||||||
dockerWorkspacePath,
|
dockerWorkspacePath,
|
||||||
dockerCpuLimit,
|
dockerCpuLimit,
|
||||||
dockerMemoryLimit,
|
dockerMemoryLimit,
|
||||||
|
dockerShmSize,
|
||||||
dockerIsolationMode,
|
dockerIsolationMode,
|
||||||
} = parameters;
|
} = parameters;
|
||||||
|
|
||||||
@@ -123,6 +140,7 @@ class Docker {
|
|||||||
--volume "${actionFolder}/BlankProject":"c:/BlankProject" \
|
--volume "${actionFolder}/BlankProject":"c:/BlankProject" \
|
||||||
--cpus=${dockerCpuLimit} \
|
--cpus=${dockerCpuLimit} \
|
||||||
--memory=${dockerMemoryLimit} \
|
--memory=${dockerMemoryLimit} \
|
||||||
|
${shmSizeFlag(dockerShmSize)} \
|
||||||
--isolation=${dockerIsolationMode} \
|
--isolation=${dockerIsolationMode} \
|
||||||
${image} \
|
${image} \
|
||||||
powershell c:/steps/entrypoint.ps1`;
|
powershell c:/steps/entrypoint.ps1`;
|
||||||
|
|||||||
@@ -241,6 +241,17 @@ class Input {
|
|||||||
return Input.getInput('dockerWorkspacePath') ?? '/github/workspace';
|
return Input.getInput('dockerWorkspacePath') ?? '/github/workspace';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unity 6.6+ editors request 1GiB of shared memory and hard-fail with
|
||||||
|
* "Insufficient shared memory available" against Docker's 64m default
|
||||||
|
* (game-ci/unity-builder#840). unity-test-runner has always passed 1025m,
|
||||||
|
* so match it here rather than leaving builds broken by default. '0' or
|
||||||
|
* 'none' omits the flag and uses Docker's own default.
|
||||||
|
*/
|
||||||
|
static get dockerShmSize(): string {
|
||||||
|
return Input.getInput('dockerShmSize') ?? '1025m';
|
||||||
|
}
|
||||||
|
|
||||||
static get dockerCpuLimit(): string {
|
static get dockerCpuLimit(): string {
|
||||||
return Input.getInput('dockerCpuLimit') ?? os.cpus().length.toString();
|
return Input.getInput('dockerCpuLimit') ?? os.cpus().length.toString();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user