Should be ready to go now??
This commit is contained in:
parent
e402db67ad
commit
b96c4ca7eb
4
Makefile
4
Makefile
|
@ -83,8 +83,6 @@ endif
|
||||||
IMAGE_HASH := "$$(docker inspect riju:$(LANG_TAG) | jq '.[0].Config.Labels["riju.image-hash"]' -r)"
|
IMAGE_HASH := "$$(docker inspect riju:$(LANG_TAG) | jq '.[0].Config.Labels["riju.image-hash"]' -r)"
|
||||||
WITH_IMAGE_HASH := -e RIJU_IMAGE_HASH=$(IMAGE_HASH)
|
WITH_IMAGE_HASH := -e RIJU_IMAGE_HASH=$(IMAGE_HASH)
|
||||||
|
|
||||||
LANG_IMAGE_HASH := "$$(docker inspect riju:lang-$(L) | jq '.[0].Config.Labels["riju.image-hash"]' -r)"
|
|
||||||
|
|
||||||
shell: # I=<shell> [L=<lang>] [E[E]=1] [P1|P2=<port>] : Launch Docker image with shell
|
shell: # I=<shell> [L=<lang>] [E[E]=1] [P1|P2=<port>] : Launch Docker image with shell
|
||||||
@: $${I}
|
@: $${I}
|
||||||
ifneq (,$(filter $(I),admin ci))
|
ifneq (,$(filter $(I),admin ci))
|
||||||
|
@ -184,7 +182,7 @@ dev: # Compile, run, and watch all artifacts and server for development
|
||||||
## are provided, then only tests matching both are run.
|
## are provided, then only tests matching both are run.
|
||||||
|
|
||||||
test: # [L=<lang>[,...]] [T=<test>[,...]] : Run test(s) for language or test category
|
test: # [L=<lang>[,...]] [T=<test>[,...]] : Run test(s) for language or test category
|
||||||
RIJU_LANG_IMAGE_HASH=$(LANG_IMAGE_HASH) node backend/test-runner.js
|
node backend/test-runner.js
|
||||||
|
|
||||||
## Functions such as 'repl', 'run', 'format', etc. are available in
|
## Functions such as 'repl', 'run', 'format', etc. are available in
|
||||||
## the sandbox, and initial setup has already been done (e.g. 'setup'
|
## the sandbox, and initial setup has already been done (e.g. 'setup'
|
||||||
|
|
|
@ -432,9 +432,9 @@ export class Session {
|
||||||
};
|
};
|
||||||
|
|
||||||
ensure = async (cmd) => {
|
ensure = async (cmd) => {
|
||||||
const code = await this.run(this.privilegedExec(cmd), {
|
const code = (await this.run(this.privilegedExec(cmd), {
|
||||||
check: false,
|
check: false,
|
||||||
});
|
})).code;
|
||||||
this.send({ event: "ensured", code });
|
this.send({ event: "ensured", code });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -44,4 +44,4 @@ async function updateLangsFromDisk() {
|
||||||
|
|
||||||
export const langsPromise = updateLangsFromDisk().then(() => langs);
|
export const langsPromise = updateLangsFromDisk().then(() => langs);
|
||||||
|
|
||||||
fsOrig.watch("langs", debounce(updateLangsFromDisk, 200));
|
export const langWatcher = fsOrig.watch("langs", debounce(updateLangsFromDisk, 200));
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
import { langWatcher } from "./langs.js";
|
||||||
|
|
||||||
|
export function shutdown() {
|
||||||
|
langWatcher.close();
|
||||||
|
}
|
|
@ -9,7 +9,8 @@ import stripAnsi from "strip-ansi";
|
||||||
import { getTestHash } from "../lib/hash-test.js";
|
import { getTestHash } from "../lib/hash-test.js";
|
||||||
import * as api from "./api.js";
|
import * as api from "./api.js";
|
||||||
import { langsPromise } from "./langs.js";
|
import { langsPromise } from "./langs.js";
|
||||||
import { getUUID } from "./util.js";
|
import { shutdown } from "./shutdown.js";
|
||||||
|
import { getUUID, run } from "./util.js";
|
||||||
|
|
||||||
let langs = {};
|
let langs = {};
|
||||||
|
|
||||||
|
@ -637,18 +638,31 @@ async function writeLog(lang, type, result, log) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
|
if (process.env.HOSTNAME !== "runtime") {
|
||||||
|
throw new Error("tests should be run in runtime container");
|
||||||
|
}
|
||||||
langs = await langsPromise;
|
langs = await langsPromise;
|
||||||
let tests = getTestList();
|
let tests = getTestList();
|
||||||
if (process.env.L) {
|
if (process.env.L) {
|
||||||
tests = tests.filter(({ lang }) => process.env.L.split().includes(lang));
|
tests = tests.filter(({ lang }) => process.env.L.split(",").includes(lang));
|
||||||
}
|
}
|
||||||
if (process.env.T) {
|
if (process.env.T) {
|
||||||
tests = tests.filter(({ type }) => process.env.T.split().includes(type));
|
tests = tests.filter(({ type }) => process.env.T.split(",").includes(type));
|
||||||
}
|
}
|
||||||
if (tests.length === 0) {
|
if (tests.length === 0) {
|
||||||
console.error("no tests selected");
|
console.error("no tests selected");
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
const langHashes = Object.fromEntries(
|
||||||
|
await Promise.all(
|
||||||
|
_.uniq(tests.map(({ lang }) => lang)).map(async (lang) => {
|
||||||
|
const output = (await run(["docker", "inspect", `riju:lang-${lang}`], console.error, {
|
||||||
|
suppressOutput: true,
|
||||||
|
})).output;
|
||||||
|
return [lang, JSON.parse(output)[0].Config.Labels["riju.image-hash"]];
|
||||||
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
console.error(`Running ${tests.length} test${tests.length !== 1 ? "s" : ""}`);
|
console.error(`Running ${tests.length} test${tests.length !== 1 ? "s" : ""}`);
|
||||||
const lintSeen = new Set();
|
const lintSeen = new Set();
|
||||||
let lintPassed = new Set();
|
let lintPassed = new Set();
|
||||||
|
@ -758,10 +772,13 @@ async function main() {
|
||||||
await fs.mkdir(`build/test-hashes/lang`, { recursive: true });
|
await fs.mkdir(`build/test-hashes/lang`, { recursive: true });
|
||||||
await fs.writeFile(
|
await fs.writeFile(
|
||||||
`build/test-hashes/lang/${lang}`,
|
`build/test-hashes/lang/${lang}`,
|
||||||
await getTestHash(lang, process.env.RIJU_LANG_IMAGE_HASH)
|
await getTestHash(lang, langHashes[lang]),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
process.exit(failed.size > 0 ? 1 : 0);
|
process.exit(failed.size > 0 ? 1 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
main().catch(console.error);
|
main().catch((err) => {
|
||||||
|
console.error(err);
|
||||||
|
shutdown();
|
||||||
|
});
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { spawn, spawnSync } from "child_process";
|
import { spawn } from "child_process";
|
||||||
import os from "os";
|
import os from "os";
|
||||||
import process from "process";
|
import process from "process";
|
||||||
|
|
||||||
|
@ -40,6 +40,7 @@ export async function run(args, log, options) {
|
||||||
options = options || {};
|
options = options || {};
|
||||||
const input = options.input;
|
const input = options.input;
|
||||||
const check = options.check === undefined ? true : options.check;
|
const check = options.check === undefined ? true : options.check;
|
||||||
|
const suppressOutput = options.suppressOutput || false;
|
||||||
delete options.input;
|
delete options.input;
|
||||||
delete options.check;
|
delete options.check;
|
||||||
const proc = spawn(args[0], args.slice(1), options);
|
const proc = spawn(args[0], args.slice(1), options);
|
||||||
|
@ -57,11 +58,11 @@ export async function run(args, log, options) {
|
||||||
proc.on("error", reject);
|
proc.on("error", reject);
|
||||||
proc.on("close", (code, signal) => {
|
proc.on("close", (code, signal) => {
|
||||||
output = output.trim();
|
output = output.trim();
|
||||||
if (output) {
|
if (output && !suppressOutput) {
|
||||||
log(`Output from ${args[0]}:\n` + output);
|
log(`Output from ${args[0]}:\n` + output);
|
||||||
}
|
}
|
||||||
if (code === 0 || !check) {
|
if (code === 0 || !check) {
|
||||||
resolve(code);
|
resolve({ code, output });
|
||||||
} else {
|
} else {
|
||||||
reject(`command ${args[0]} failed with error code ${signal || code}`);
|
reject(`command ${args[0]} failed with error code ${signal || code}`);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
import crypto from "crypto";
|
import crypto from "crypto";
|
||||||
|
import child_process from "child_process";
|
||||||
import { promises as fs } from "fs";
|
import { promises as fs } from "fs";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
|
import util from "util";
|
||||||
|
|
||||||
import { parse } from "@babel/parser";
|
import { parse } from "@babel/parser";
|
||||||
import { simple as babelWalk } from "babel-walk";
|
import { simple as babelWalk } from "babel-walk";
|
||||||
|
@ -54,6 +56,7 @@ async function getTestRunnerHash() {
|
||||||
const files = await getTransitiveRelativeImports("backend/test-runner.js");
|
const files = await getTransitiveRelativeImports("backend/test-runner.js");
|
||||||
files.push("package.json");
|
files.push("package.json");
|
||||||
files.push("yarn.lock");
|
files.push("yarn.lock");
|
||||||
|
files.push("system/src/riju-system-privileged.c");
|
||||||
const hashes = [];
|
const hashes = [];
|
||||||
for (const file of files) {
|
for (const file of files) {
|
||||||
hashes.push(
|
hashes.push(
|
||||||
|
@ -63,6 +66,9 @@ async function getTestRunnerHash() {
|
||||||
.digest("hex")
|
.digest("hex")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
hashes.push((await util.promisify(child_process.exec)(
|
||||||
|
`docker inspect riju:runtime -f '{{ index .Config.Labels "riju.image-hash" }}'`,
|
||||||
|
)).stdout.trim());
|
||||||
return crypto.createHash("sha1").update(hashes.join(",")).digest("hex");
|
return crypto.createHash("sha1").update(hashes.join(",")).digest("hex");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue