98 lines
2.7 KiB
JavaScript
98 lines
2.7 KiB
JavaScript
import { promises as fs } from "fs";
|
|
import http from "http";
|
|
|
|
import express from "express";
|
|
|
|
import { getLangs, getPackages, getSharedDeps } from "./config.js";
|
|
import { getLocalImageLabel } from "./docker-util.js";
|
|
import { hashDockerfile } from "./hash-dockerfile.js";
|
|
import { runCommand } from "./util.js";
|
|
|
|
// Number of package installation layers in the composite Docker
|
|
// image. This needs to match the number of installation RUN commands
|
|
// in the composite Dockerfile.
|
|
const NUM_SHARDS = 10;
|
|
|
|
// Get a Node.js http server object that will serve information and
|
|
// files for packages that should be installed into the composite
|
|
// Docker image.
|
|
function getServer({ shards }) {
|
|
const app = express();
|
|
app.get("/shard/:shard", (req, res) => {
|
|
res.send(
|
|
shards[parseInt(req.params.shard)]
|
|
.map(({ debPath }) => debPath + "\n")
|
|
.join("")
|
|
);
|
|
});
|
|
app.use("/fs", express.static("."));
|
|
return http.createServer(app);
|
|
}
|
|
|
|
// Given a list of the packages to be built, split them into shards.
|
|
// Return a list of shards. Each shard is a list of the package
|
|
// objects, such that there are NUM_SHARDS shards. Traversing each
|
|
// shard in order will return the packages in the same order as the
|
|
// original list.
|
|
//
|
|
// Currently this uses an extremely simple algorithm, but that might
|
|
// be improved in the future.
|
|
function getShards(pkgs) {
|
|
const shards = [];
|
|
for (let i = 0; i < NUM_SHARDS; ++i) {
|
|
shards.push([]);
|
|
}
|
|
const shardSize = Math.ceil(pkgs.length / NUM_SHARDS);
|
|
for (let i = 0; i < pkgs.length; ++i) {
|
|
shards[Math.floor(i / shardSize)].push(pkgs[i]);
|
|
}
|
|
return shards;
|
|
}
|
|
|
|
// Parse command-line arguments, run main functionality, and exit.
|
|
async function main() {
|
|
const packages = await getPackages();
|
|
const hash = await hashDockerfile(
|
|
"composite",
|
|
{
|
|
"riju:runtime": await getLocalImageLabel(
|
|
"riju:runtime",
|
|
"riju.image-hash"
|
|
),
|
|
},
|
|
{
|
|
salt: {
|
|
packageHashes: (
|
|
await Promise.all(
|
|
packages.map(async ({ debPath }) => {
|
|
return (
|
|
await runCommand(`dpkg-deb -f ${debPath} Riju-Script-Hash`, {
|
|
getStdout: true,
|
|
})
|
|
).stdout.trim();
|
|
})
|
|
)
|
|
).sort(),
|
|
},
|
|
}
|
|
);
|
|
const server = getServer({
|
|
shards: getShards(packages),
|
|
});
|
|
await new Promise((resolve) => server.listen(8487, "localhost", resolve));
|
|
try {
|
|
await runCommand(
|
|
`docker build . -f docker/composite/Dockerfile -t riju:composite` +
|
|
` --network host --no-cache --label riju.image-hash=${hash}`
|
|
);
|
|
} finally {
|
|
await server.close();
|
|
}
|
|
process.exit(0);
|
|
}
|
|
|
|
main().catch((err) => {
|
|
console.error(err);
|
|
process.exit(1);
|
|
});
|