Skip to content
Merged
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
5 changes: 5 additions & 0 deletions .github/workflows/build-options.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@
"macos-latest"
],
"unity-version": [
"4.7.2",
"5.6.7f1 (e80cc3114ac1)",
"2017.4.40f1",
"2018",
"2018.4",
"2019.x",
"2020.*",
"2021.3.x",
Expand Down
12 changes: 6 additions & 6 deletions .github/workflows/unity-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ jobs:
contents: read
env:
UNITY_PROJECT_PATH: '' # Set from create-project step
RUN_BUILD: '' # Set to true if the build pipeline package can be installed and used
steps:
- name: Free Disk Space
if: ${{ matrix.os == 'ubuntu-latest' && (matrix.unity-version != '2018' && matrix.unity-version != '2017.4.40f1') }}
Expand Down Expand Up @@ -83,6 +82,7 @@ jobs:
unity-cli create-project --name "Unity Project" --unity-editor "${UNITY_EDITOR_PATH}" --json
- name: Verify UNITY_PROJECT_PATH variable
if: ${{ matrix.unity-version != 'none' }}
id: verify-project-path
shell: bash
run: |
if [ -z "${UNITY_PROJECT_PATH}" ]; then
Expand All @@ -97,16 +97,16 @@ jobs:
if [ -z "$minor" ]; then
minor=0
fi
# numeric comparison: enable build for major > 2019 or major == 2019 and minor >= 4
if [ "$major" -gt 2019 ] || { [ "$major" -eq 2019 ] && [ "$minor" -ge 4 ]; }; then
# numeric comparison: enable build for major >= 2019
if [ "$major" -ge 2019 ]; then
echo "Proceeding with build for Unity version $version"
echo "RUN_BUILD=true" >> $GITHUB_ENV
echo "RUN_BUILD=true" >> $GITHUB_OUTPUT
else
echo "Skipping build: Unity version $version does not support the build pipeline package (requires 2019.4+)"
fi
- name: Install OpenUPM and build pipeline package
shell: bash
if: ${{ env.RUN_BUILD == 'true' }}
if: ${{ steps.verify-project-path.outputs.RUN_BUILD == 'true' }}
run: |
npm install -g openupm-cli
cd "${UNITY_PROJECT_PATH}"
Expand All @@ -120,7 +120,7 @@ jobs:
# ensure android dependencies are installed
unity-cli setup-unity -p "${UNITY_PROJECT_PATH}" -m android
- name: Build Project
if: ${{ env.RUN_BUILD == 'true' }}
if: ${{ steps.verify-project-path.outputs.RUN_BUILD == 'true' }}
timeout-minutes: 60
shell: bash
run: |
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@rage-against-the-pixel/unity-cli",
"version": "1.7.1",
"version": "1.7.2",
"description": "A command line utility for the Unity Game Engine.",
"author": "RageAgainstThePixel",
"license": "MIT",
Expand Down
2 changes: 1 addition & 1 deletion src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -421,7 +421,7 @@ program.command('run')
.option('--unity-editor <unityEditor>', 'The path to the Unity Editor executable. If unspecified, --unity-project or the UNITY_EDITOR_PATH environment variable must be set.')
.option('--unity-project <unityProject>', 'The path to a Unity project. If unspecified, the UNITY_PROJECT_PATH environment variable will be used, otherwise no project will be specified.')
.option('--log-name <logName>', 'The name of the log file.')
.option('--log-level <logLevel>', 'Set the logging level (debug, info, minimal, warning, error).')
.option('--log-level <logLevel>', 'Set the logging level (debug, info, minimal, warning, error). Default is info.')
.option('--verbose', 'Enable verbose logging. Deprecated, use --log-level instead.')
.allowUnknownOption(true)
.argument('<args...>', 'Arguments to pass to the Unity Editor executable.')
Expand Down
92 changes: 45 additions & 47 deletions src/unity-logging.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ class ActionTelemetryAccumulator {
private totalErrorCount = 0;
private playerBuildInfoSteps: PlayerBuildInfoStepSummary[] = [];

record(action: UTPBase): boolean {
public record(action: UTPBase): boolean {
if (action.phase === Phase.Begin) {
this.pendingActions.set(this.getActionKey(action), action);
return true;
Expand Down Expand Up @@ -133,7 +133,7 @@ class ActionTelemetryAccumulator {
return false;
}

recordPlayerBuildInfo(info: UTPPlayerBuildInfo): boolean {
public recordPlayerBuildInfo(info: UTPPlayerBuildInfo): boolean {
if (!Array.isArray(info.steps) || info.steps.length === 0) {
return false;
}
Expand Down Expand Up @@ -162,7 +162,7 @@ class ActionTelemetryAccumulator {
return true;
}

snapshot(): ActionTableSnapshot | undefined {
public snapshot(): ActionTableSnapshot | undefined {
if (this.completedActions.length === 0 && this.pendingActions.size === 0 && this.playerBuildInfoSteps.length === 0) {
return undefined;
}
Expand Down Expand Up @@ -902,14 +902,13 @@ function formatMemoryLeakTable(memLeaks: UTPMemoryLeak): string {

function buildUtpLogPath(logPath: string): string {
const parsed = path.parse(logPath);
const utpFileName = `utp-${parsed.name}.json`;
const utpFileName = `${parsed.name}-utp-json.log`;
return parsed.dir ? path.join(parsed.dir, utpFileName) : utpFileName;
}

async function writeUtpTelemetryLog(filePath: string, entries: UTP[], logger: Logger): Promise<void> {
try {
const content = `${JSON.stringify(entries, null, 2)}\n`;
await fs.promises.writeFile(filePath, content, 'utf8');
await fs.promises.writeFile(filePath, `${JSON.stringify(entries)}\n`, 'utf8');
} catch (error) {
logger.warn(`Failed to write UTP telemetry log (${filePath}): ${error}`);
}
Expand Down Expand Up @@ -940,21 +939,52 @@ export function TailLogFile(logPath: string, projectPath: string | undefined): L
};

const flushTelemetryLog = async (): Promise<void> => {
if (telemetryFlushed) {
return;
}
if (telemetryFlushed) { return; }
telemetryFlushed = true;
await writeUtpTelemetryLog(utpLogPath, telemetry, logger);
};

const writeStdout = (content: string, restoreTable: boolean = true): void => {
const writeStdoutThenTableContent = (content: string, restoreTable: boolean = true): void => {
actionTableRenderer.prepareForContent();
process.stdout.write(content);
if (restoreTable) {
renderActionTable();
}
};

function printUTP(utp: UTP): void {
// switch utp types, fallback to json if we don't have a toString() implementation or a type implementation
switch (utp.type) {
case 'Action': {
const actionEntry = utp as UTPBase;
const tableChanged = actionAccumulator.record(actionEntry);

if (tableChanged) {
renderActionTable();
}

break;
}
case 'MemoryLeaks':
logger.debug(formatMemoryLeakTable(utp as UTPMemoryLeak));
break;
case 'PlayerBuildInfo': {
const infoEntry = utp as UTPPlayerBuildInfo;
const changed = actionAccumulator.recordPlayerBuildInfo(infoEntry);

if (changed) {
renderActionTable();
}

break;
}
default:
// Print raw JSON for unhandled UTP types
writeStdoutThenTableContent(`${JSON.stringify(utp)}\n`);
break;
}
}

async function readNewLogContent(): Promise<void> {
try {
if (!fs.existsSync(logPath)) { return; }
Expand Down Expand Up @@ -990,10 +1020,7 @@ export function TailLogFile(logPath: string, projectPath: string | undefined): L
const jsonPart = line.substring('##utp:'.length).trim();
try {
const sanitizedJson = sanitizeTelemetryJson(jsonPart);

if (!sanitizedJson) {
continue;
}
if (!sanitizedJson) { continue; }

const utpJson = JSON.parse(sanitizedJson);
const utp = utpJson as UTP;
Expand Down Expand Up @@ -1030,44 +1057,15 @@ export function TailLogFile(logPath: string, projectPath: string | undefined): L
}
}
}
} else {
// switch utp types, fallback to json if we don't have a toString() implementation or a type implementation
switch (utp.type) {
case 'Action': {
const actionEntry = utp as UTPBase;
const tableChanged = actionAccumulator.record(actionEntry);

if (tableChanged) {
renderActionTable();
}

break;
}
case 'MemoryLeaks':
logger.debug(formatMemoryLeakTable(utp as UTPMemoryLeak));
break;
case 'PlayerBuildInfo': {
const infoEntry = utp as UTPPlayerBuildInfo;
const changed = actionAccumulator.recordPlayerBuildInfo(infoEntry);

if (changed) {
renderActionTable();
}

break;
}
default:
// Print raw JSON for unhandled UTP types
writeStdout(`${jsonPart}\n`);
break;
}
} else if (Logger.instance.logLevel === LogLevel.UTP) {
printUTP(utp);
}
} catch (error) {
logger.warn(`Failed to parse telemetry JSON: ${error} -- raw: ${jsonPart}`);
}
} else {
if (Logger.instance.logLevel !== LogLevel.UTP) {
writeStdout(`${line}\n`);
process.stdout.write(`${line}\n`);
}
}
}
Expand Down Expand Up @@ -1098,7 +1096,7 @@ export function TailLogFile(logPath: string, projectPath: string | undefined): L

try {
// write a final newline to separate log output
writeStdout('\n');
process.stdout.write('\n');
} catch (error: any) {
if (error.code !== 'EPIPE') {
logger.warn(`Error while writing log tail: ${error}`);
Expand Down
Loading