feat: add rollback_on_failure feature #88
@@ -6,6 +6,7 @@ This repository is maintained by Gemini.
|
|||||||
|
|
||||||
* **Test-Driven Development (TDD):** Wherever possible, Test-Driven Development principles should be followed. Write tests before writing the code they are intended to validate.
|
* **Test-Driven Development (TDD):** Wherever possible, Test-Driven Development principles should be followed. Write tests before writing the code they are intended to validate.
|
||||||
* **Pre-commit Hooks:** Ensure that `pre-commit` hooks are installed and active before making any commits. This can be done by running `pre-commit install` in your local repository.
|
* **Pre-commit Hooks:** Ensure that `pre-commit` hooks are installed and active before making any commits. This can be done by running `pre-commit install` in your local repository.
|
||||||
|
* **Note for Gemini:** Git commits trigger pre-commit hooks, which can take several seconds (or minutes) to complete. Checking the command status for git commit is only appropriate every 120s.
|
||||||
|
|
||||||
## Repository Comparison
|
## Repository Comparison
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,23 @@ vi.mock("../monitor.js", () => ({
|
|||||||
}),
|
}),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
// Mock screeps-api
|
||||||
|
vi.mock("screeps-api", () => {
|
||||||
|
const mockApi = {
|
||||||
|
auth: vi.fn().mockResolvedValue(),
|
||||||
|
code: {
|
||||||
|
get: vi.fn().mockResolvedValue({ ok: 1, modules: { main: "old_code" } }),
|
||||||
|
set: vi.fn().mockResolvedValue({ ok: 1 }),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
// Use a regular function so it can be called with `new`
|
||||||
|
return {
|
||||||
|
ScreepsAPI: vi.fn(function () {
|
||||||
|
return mockApi;
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
import * as core from "@actions/core";
|
import * as core from "@actions/core";
|
||||||
import { monitorConsole } from "../monitor.js";
|
import { monitorConsole } from "../monitor.js";
|
||||||
|
|
||||||
@@ -29,7 +46,9 @@ import {
|
|||||||
readReplaceAndWriteFiles,
|
readReplaceAndWriteFiles,
|
||||||
readFilesIntoDict,
|
readFilesIntoDict,
|
||||||
applyOnAction,
|
applyOnAction,
|
||||||
|
postCode,
|
||||||
} from "../index.js";
|
} from "../index.js";
|
||||||
|
import { ScreepsAPI } from "screeps-api";
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import os from "os";
|
import os from "os";
|
||||||
@@ -231,31 +250,31 @@ describe("glob functionality", () => {
|
|||||||
describe("applyOnAction", () => {
|
describe("applyOnAction", () => {
|
||||||
beforeEach(() => vi.clearAllMocks());
|
beforeEach(() => vi.clearAllMocks());
|
||||||
|
|
||||||
it("'ignore' + true → no core call", () => {
|
it("'ignore' + true → no core call, returns false", () => {
|
||||||
applyOnAction("ignore", true, "msg");
|
expect(applyOnAction("ignore", true, "msg")).toBe(false);
|
||||||
expect(core.warning).not.toHaveBeenCalled();
|
expect(core.warning).not.toHaveBeenCalled();
|
||||||
expect(core.setFailed).not.toHaveBeenCalled();
|
expect(core.setFailed).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("'warn' + true → core.warning() called with message", () => {
|
it("'warn' + true → core.warning() called with message, returns false", () => {
|
||||||
applyOnAction("warn", true, "boom");
|
expect(applyOnAction("warn", true, "boom")).toBe(false);
|
||||||
expect(core.warning).toHaveBeenCalledWith("boom");
|
expect(core.warning).toHaveBeenCalledWith("boom");
|
||||||
expect(core.setFailed).not.toHaveBeenCalled();
|
expect(core.setFailed).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("'fail' + true → core.setFailed() called with message", () => {
|
it("'fail' + true → core.setFailed() called with message, returns true", () => {
|
||||||
applyOnAction("fail", true, "boom");
|
expect(applyOnAction("fail", true, "boom")).toBe(true);
|
||||||
expect(core.setFailed).toHaveBeenCalledWith("boom");
|
expect(core.setFailed).toHaveBeenCalledWith("boom");
|
||||||
expect(core.warning).not.toHaveBeenCalled();
|
expect(core.warning).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("'fail' + false → no core call", () => {
|
it("'fail' + false → no core call, returns false", () => {
|
||||||
applyOnAction("fail", false, "boom");
|
expect(applyOnAction("fail", false, "boom")).toBe(false);
|
||||||
expect(core.setFailed).not.toHaveBeenCalled();
|
expect(core.setFailed).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("'warn' + false → no core call", () => {
|
it("'warn' + false → no core call, returns false", () => {
|
||||||
applyOnAction("warn", false, "msg");
|
expect(applyOnAction("warn", false, "msg")).toBe(false);
|
||||||
expect(core.warning).not.toHaveBeenCalled();
|
expect(core.warning).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -270,28 +289,60 @@ describe("postCode — monitor wiring", () => {
|
|||||||
// Default core mocks
|
// Default core mocks
|
||||||
core.getInput.mockImplementation((name) => {
|
core.getInput.mockImplementation((name) => {
|
||||||
if (name === "monitor") return "0";
|
if (name === "monitor") return "0";
|
||||||
|
if (name === "token") return "test-token";
|
||||||
|
if (name === "branch") return "default";
|
||||||
|
if (name === "on_traceback") return "fail";
|
||||||
return "";
|
return "";
|
||||||
});
|
});
|
||||||
core.getBooleanInput.mockReturnValue(false);
|
core.getBooleanInput.mockImplementation((name) => {
|
||||||
|
if (name === "rollback_on_failure") return false;
|
||||||
|
return false;
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it("does not call monitorConsole when monitor=0 (default)", async () => {
|
it("does not call monitorConsole when monitor=0 (default)", async () => {
|
||||||
// We need to mock the rest of postCode to not fail before it hits the monitor block
|
// We just run postCode with monitor=0 and verify monitorConsole is not called.
|
||||||
// This is a bit complex as postCode is large, but we can mock the inputs to exit early or mock the API
|
await postCode();
|
||||||
// Actually, I'll just check if monitorConsole is called.
|
expect(monitorConsole).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
// For this test, I'll make validateAuthentication fail so it returns early but after input check
|
it("rolls back to previous code when monitor detects a failure and rollback_on_failure is true", async () => {
|
||||||
|
// Setup inputs for monitor and rollback
|
||||||
core.getInput.mockImplementation((name) => {
|
core.getInput.mockImplementation((name) => {
|
||||||
if (name === "monitor") return "0";
|
if (name === "monitor") return "10";
|
||||||
|
if (name === "token") return "test-token";
|
||||||
|
if (name === "branch") return "default";
|
||||||
|
if (name === "on_traceback") return "fail";
|
||||||
return "";
|
return "";
|
||||||
});
|
});
|
||||||
|
core.getBooleanInput.mockImplementation((name) => {
|
||||||
|
if (name === "rollback_on_failure") return true;
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
// We'll just run a partial check or rely on the monitor unit tests for depth
|
// Simulate a failure in monitorConsole
|
||||||
// The wiring in index.js is:
|
monitorConsole.mockResolvedValueOnce({
|
||||||
// const monitorTicks = parseInt(core.getInput("monitor") || "0", 10);
|
sawTraceback: true, // Should trigger "fail" due to on_traceback=fail
|
||||||
// if (monitorTicks > 0) { ... }
|
sawErrorLog: false,
|
||||||
|
sawWarningLog: false,
|
||||||
|
});
|
||||||
|
|
||||||
// Testing the logic inside index.js directly by calling postCode would require full environment mock.
|
await postCode();
|
||||||
// I'll stick to the applyOnAction unit tests and rely on monitor.test.js for the heavy lifting.
|
|
||||||
|
// Verify rollback was performed
|
||||||
|
const mockApiInstance = new ScreepsAPI();
|
||||||
|
|
||||||
|
// `code.set` should be called twice:
|
||||||
|
// 1st time: uploading the new files
|
||||||
|
// 2nd time: rolling back to oldCode
|
||||||
|
expect(mockApiInstance.code.set).toHaveBeenCalledTimes(2);
|
||||||
|
expect(mockApiInstance.code.set).toHaveBeenNthCalledWith(2, "default", {
|
||||||
|
main: "old_code",
|
||||||
|
});
|
||||||
|
|
||||||
|
// Verify it called core.setFailed due to traceback
|
||||||
|
expect(core.setFailed).toHaveBeenCalledWith(
|
||||||
|
"Screeps console: traceback detected",
|
||||||
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -67,6 +67,10 @@ inputs:
|
|||||||
description: 'Print a progress update every N ticks when log_to_file=true (default: 10).'
|
description: 'Print a progress update every N ticks when log_to_file=true (default: 10).'
|
||||||
required: false
|
required: false
|
||||||
default: '10'
|
default: '10'
|
||||||
|
rollback_on_failure:
|
||||||
|
description: 'Automatically rollback to previous code if the monitor detects failures. Requires monitor > 0. (default: false)'
|
||||||
|
required: false
|
||||||
|
default: 'false'
|
||||||
outputs:
|
outputs:
|
||||||
saw_traceback:
|
saw_traceback:
|
||||||
description: true if a JS traceback was detected during monitoring.
|
description: true if a JS traceback was detected during monitoring.
|
||||||
|
|||||||
@@ -118,17 +118,19 @@ export function validateAuthentication(token, username, password) {
|
|||||||
|
Philipp marked this conversation as resolved
|
|||||||
* @param {'ignore'|'warn'|'fail'} action
|
* @param {'ignore'|'warn'|'fail'} action
|
||||||
* @param {boolean} flag - Only acts when true
|
* @param {boolean} flag - Only acts when true
|
||||||
* @param {string} message - Passed to core.warning / core.setFailed
|
* @param {string} message - Passed to core.warning / core.setFailed
|
||||||
|
* @returns {boolean} - Returns true if the action was 'fail' and the flag was true.
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
*/
|
*/
|
||||||
export function applyOnAction(action, flag, message) {
|
export function applyOnAction(action, flag, message) {
|
||||||
if (!flag) return;
|
if (!flag) return false;
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
if (action === "warn") {
|
if (action === "warn") {
|
||||||
core.warning(message);
|
core.warning(message);
|
||||||
return;
|
return false;
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
}
|
}
|
||||||
if (action === "fail") {
|
if (action === "fail") {
|
||||||
core.setFailed(message);
|
core.setFailed(message);
|
||||||
|
return true;
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
}
|
}
|
||||||
// 'ignore' → no-op
|
return false;
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -179,33 +181,72 @@ export async function postCode() {
|
|||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let api = new ScreepsAPI(login_arguments);
|
let api = new ScreepsAPI(login_arguments);
|
||||||
if (token) {
|
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
|
if (!token) {
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
|
core.info(`Logging in as user ${username}`);
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
|
try {
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
|
await api.auth(username, password, login_arguments);
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
|
} catch (err) {
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
|
core.error(`Authentication error: ${err}`);
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
|
throw err;
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
|
}
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
|
}
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
|
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
|
let oldCode = null;
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
|
let rollbackOnFailure = false;
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
|
try {
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
|
rollbackOnFailure = core.getBooleanInput("rollback_on_failure");
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
|
} catch (e) {
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
|
// getBooleanInput throws if not 'true' or 'false', ignore
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
|
}
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
|
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
|
if (rollbackOnFailure) {
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
|
core.info(
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
|
`Downloading existing code from branch ${branch} for potential rollback...`,
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
|
);
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
|
try {
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
|
const getResponse = await api.code.get(branch);
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
|
if (getResponse && getResponse.ok && getResponse.modules) {
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
|
oldCode = getResponse.modules;
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
|
core.info(
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
|
`Successfully downloaded existing code (modules: ${Object.keys(oldCode).join(", ")})`,
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
|
);
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
AutoReview
commented
If the user explicitly requested If the user explicitly requested `rollback_on_failure`, and the download fails, should the action continue? Currently it results in a warning. If the deployment is critical, failing here might be safer.
|
|||||||
|
} else {
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
|
core.setFailed(
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
|
`Failed to download existing code, but rollback_on_failure is enabled. Aborting deployment.`,
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
|
);
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
|
return;
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
|
}
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
|
} catch (err) {
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
|
core.setFailed(
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
|
`Error downloading existing code: ${err.message}. Aborting deployment.`,
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
|
);
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
|
return;
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
|
}
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
|
}
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
|
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
|
try {
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
const response = await api.code.set(branch, files_to_push);
|
const response = await api.code.set(branch, files_to_push);
|
||||||
core.info(JSON.stringify(response, null, 2));
|
core.info(JSON.stringify(response, null, 2));
|
||||||
core.info(`Code set successfully to ${branch}`);
|
core.info(`Code set successfully to ${branch}`);
|
||||||
} else {
|
} catch (err) {
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
core.info(`Logging in as user ${username}`);
|
core.error(`Upload error: ${err}`);
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
await Promise.resolve()
|
throw err;
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
.then(() => api.auth(username, password, login_arguments))
|
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
.then(() => api.code.set(branch, files_to_push))
|
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
.then(() => {
|
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
core.info(`Code set successfully to ${branch}`);
|
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
})
|
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
.catch((err) => {
|
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
core.error(`Upload error: ${err}`);
|
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
throw err;
|
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
});
|
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Console monitoring (optional)
|
// Console monitoring (optional)
|
||||||
const monitorTicks = parseInt(core.getInput("monitor") || "0", 10);
|
const monitorTicks = parseInt(core.getInput("monitor") || "0", 10);
|
||||||
if (monitorTicks > 0) {
|
if (monitorTicks > 0) {
|
||||||
|
const onTraceback = core.getInput("on_traceback") || "fail";
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
|
const onErrorLog = core.getInput("on_error_log") || "warn";
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
|
const onWarningLog = core.getInput("on_warning_log") || "ignore";
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
|
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
const result = await monitorConsole(api, {
|
const result = await monitorConsole(api, {
|
||||||
monitor: monitorTicks,
|
monitor: monitorTicks,
|
||||||
logToFile: core.getBooleanInput("log_to_file"),
|
logToFile: core.getBooleanInput("log_to_file"),
|
||||||
onTraceback: core.getInput("on_traceback") || "fail",
|
onTraceback,
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
onErrorLog: core.getInput("on_error_log") || "warn",
|
onErrorLog,
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
onWarningLog: core.getInput("on_warning_log") || "ignore",
|
onWarningLog,
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
monitorInterval: parseInt(core.getInput("monitor_interval") || "10", 10),
|
monitorInterval: parseInt(core.getInput("monitor_interval") || "10", 10),
|
||||||
hostname,
|
hostname,
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
This block duplicates the logic found inside This block duplicates the logic found inside `applyOnAction`. While necessary to determine if a rollback should occur before the final `setFailed` call, it might be worth refactoring to avoid inconsistent behavior if more failure conditions are added in the future.
|
|||||||
shard: core.getInput("shard") || undefined,
|
shard: core.getInput("shard") || undefined,
|
||||||
@@ -215,21 +256,37 @@ export async function postCode() {
|
|||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
core.setOutput("saw_error_log", String(result.sawErrorLog));
|
core.setOutput("saw_error_log", String(result.sawErrorLog));
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
Consider defining these defaults in a central place or ensuring they are strictly pulled from Consider defining these defaults in a central place or ensuring they are strictly pulled from `action.yaml`. If `action.yaml` defaults change but these fallbacks don't, the behavior might become inconsistent.
|
|||||||
core.setOutput("saw_warning_log", String(result.sawWarningLog));
|
core.setOutput("saw_warning_log", String(result.sawWarningLog));
|
||||||
|
|
||||||
applyOnAction(
|
const fail1 = applyOnAction(
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
core.getInput("on_traceback"),
|
onTraceback,
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
result.sawTraceback,
|
result.sawTraceback,
|
||||||
"Screeps console: traceback detected",
|
"Screeps console: traceback detected",
|
||||||
);
|
);
|
||||||
applyOnAction(
|
const fail2 = applyOnAction(
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
core.getInput("on_error_log"),
|
onErrorLog,
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
result.sawErrorLog,
|
result.sawErrorLog,
|
||||||
"Screeps console: error log output detected",
|
"Screeps console: error log output detected",
|
||||||
);
|
);
|
||||||
applyOnAction(
|
const fail3 = applyOnAction(
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
core.getInput("on_warning_log"),
|
onWarningLog,
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
result.sawWarningLog,
|
result.sawWarningLog,
|
||||||
"Screeps console: warning log output detected",
|
"Screeps console: warning log output detected",
|
||||||
);
|
);
|
||||||
|
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
|
const shouldFail = fail1 || fail2 || fail3;
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
|
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
|
if (shouldFail && rollbackOnFailure && oldCode) {
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
|
core.info(
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
|
"Action failed based on monitor configuration. Rolling back to previous code...",
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
|
);
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
|
try {
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
|
await api.code.set(branch, oldCode);
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
|
core.info(
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
|
`Successfully rolled back to previous code on branch ${branch}.`,
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
|
);
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
|
} catch (err) {
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
|
core.error(`Rollback failed: ${err}`);
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
AutoReview
commented
Wait-for-ticks logic in Wait-for-ticks logic in `monitorConsole` handles the timing, but consider if a failed rollback should also `setFailed` the action explicitly if `api.code.set` fails during the rollback phase. Currently, it only logs an error.
|
|||||||
|
}
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
|
}
|
||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
|
Philipp marked this conversation as resolved
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
AutoReview
commented
The The `api.auth` call is now explicitly awaited outside the conditional block. This is cleaner than the previous `.then()` chain.
|
|||||||
The
api.authcall is now explicitly awaited outside the conditional block. This is cleaner than the previous.then()chain.The
api.authcall is now explicitly awaited outside the conditional block. This is cleaner than the previous.then()chain.