Finish up initial depgraph, remove dead code
This commit is contained in:
parent
1b975de021
commit
00c3a4117a
|
@ -228,8 +228,9 @@ async function getDeployArtifact(langs) {
|
|||
dependencies: ["image:app"]
|
||||
.concat(langs.map((lang) => `image:lang-${lang}`))
|
||||
.concat(langs.map((lang) => `test:lang-${lang}`)),
|
||||
getLocalHash: async () => {
|
||||
return null;
|
||||
publishOnly: true,
|
||||
publishToRegistry: async () => {
|
||||
await runCommand(`tools/deploy.bash`);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -273,6 +274,10 @@ async function getDepGraph() {
|
|||
return { informationalDependencies, artifacts };
|
||||
}
|
||||
|
||||
async function executeDepGraph({ publish, yes, targets }) {
|
||||
//
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const program = new Command();
|
||||
program.usage("<target>...");
|
||||
|
@ -293,7 +298,7 @@ async function main() {
|
|||
if (program.args.length === 0) {
|
||||
program.help({ error: true });
|
||||
}
|
||||
console.log("doing things now");
|
||||
await executeDepGraph({ publish, yes, targets: program.args });
|
||||
}
|
||||
|
||||
if (process.argv[1] === url.fileURLToPath(import.meta.url)) {
|
||||
|
|
|
@ -2,6 +2,13 @@
|
|||
|
||||
set -euo pipefail
|
||||
|
||||
if [[ -z "${DEPLOY_SSH_PRIVATE_KEY:-}" ]]; then
|
||||
: ${DEPLOY_SSH_PUBLIC_KEY_FILE}
|
||||
DEPLOY_SSH_PRIVATE_KEY="$(base64 < "${DEPLOY_SSH_PUBLIC_KEY_FILE%.pub}")"
|
||||
fi
|
||||
|
||||
: ${DOMAIN}
|
||||
|
||||
if (( $# != 1 )); then
|
||||
echo "usage: deploy.bash IMAGE" >&2
|
||||
exit 1
|
||||
|
@ -30,4 +37,4 @@ chmod go-rwx "${tmpdir}/id"
|
|||
ssh -o IdentitiesOnly=yes \
|
||||
-o StrictHostKeyChecking=no \
|
||||
-o UserKnownHostsFile=/dev/null \
|
||||
-i "${tmpdir}/id" "deploy@${DOMAIN}" "${image}"
|
||||
-i "${tmpdir}/id" "deploy@${DOMAIN}"
|
||||
|
|
|
@ -17,192 +17,6 @@ import {
|
|||
import { hashDockerfile } from "./hash-dockerfile.js";
|
||||
import { runCommand } from "./util.js";
|
||||
|
||||
async function planDockerImage(name, dependentHashes, opts) {
|
||||
const { deps, hashOpts } = opts || {};
|
||||
const DOCKER_REPO = getDockerRepo();
|
||||
const desired = await hashDockerfile(name, dependentHashes, hashOpts);
|
||||
const local = await getLocalImageLabel(`riju:${name}`, "riju.image-hash");
|
||||
const remote = await getRemoteImageLabel(
|
||||
`${DOCKER_REPO}:${name}`,
|
||||
"riju.image-hash"
|
||||
);
|
||||
dependentHashes[`riju:${name}`] = desired;
|
||||
return {
|
||||
id: getUUID(),
|
||||
deps: deps || [],
|
||||
artifact: "Docker image",
|
||||
name,
|
||||
desired,
|
||||
local,
|
||||
remote,
|
||||
download: async () => {
|
||||
if (name === "app") {
|
||||
// Magic string parsed by publish.bash
|
||||
console.log("[for publish script: plan-publish is tagging app image]");
|
||||
}
|
||||
await runCommand(`make pull I=${name}`);
|
||||
},
|
||||
build: async () => {
|
||||
if (name === "app") {
|
||||
// Magic string parsed by publish.bash
|
||||
console.log("[for publish script: plan-publish is tagging app image]");
|
||||
}
|
||||
await runCommand(`make image I=${name}`);
|
||||
},
|
||||
upload: async () => {
|
||||
if (name === "composite") {
|
||||
await runCommand(`make shell I=composite CMD="make test"`);
|
||||
}
|
||||
await runCommand(`make push I=${name}`);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
async function planDebianPackages(opts) {
|
||||
const { deps } = opts || {};
|
||||
const remoteHashes = Object.fromEntries(
|
||||
JSON.parse(
|
||||
(
|
||||
await runCommand(
|
||||
`aws s3api list-objects-v2 --bucket riju-debs --prefix hashes`,
|
||||
{ getStdout: true }
|
||||
)
|
||||
).stdout
|
||||
).Contents.map(({ Key: key }) => {
|
||||
const [_, remoteName, remoteHash] = key.split("/");
|
||||
return [remoteName, remoteHash];
|
||||
})
|
||||
);
|
||||
const packages = await getPackages();
|
||||
const uuids = Object.fromEntries(
|
||||
packages.map(({ name }) => [name, getUUID()])
|
||||
);
|
||||
const langUUIDs = Object.fromEntries(
|
||||
packages
|
||||
.filter(({ type }) => type === "lang")
|
||||
.map(({ lang, name }) => [lang, uuids[name]])
|
||||
);
|
||||
const sharedUUIDs = Object.fromEntries(
|
||||
packages
|
||||
.filter(({ type }) => type === "shared")
|
||||
.map(({ lang }) => [lang, uuids[lang]])
|
||||
);
|
||||
const langConfigs = Object.fromEntries(
|
||||
await Promise.all(
|
||||
(await getLangs()).map(async (id) => [id, await readLangConfig(id)])
|
||||
)
|
||||
);
|
||||
const plan = await Promise.all(
|
||||
packages.map(async ({ lang, type, name, buildScriptPath, debPath }) => {
|
||||
const desired = crypto
|
||||
.createHash("sha1")
|
||||
.update(await fs.readFile(buildScriptPath, "utf-8"))
|
||||
.digest("hex");
|
||||
let debExists = true;
|
||||
try {
|
||||
await fs.access(debPath);
|
||||
} catch (err) {
|
||||
debExists = false;
|
||||
}
|
||||
let local = null;
|
||||
if (debExists) {
|
||||
local =
|
||||
(
|
||||
await runCommand(`dpkg-deb -f ${debPath} Riju-Script-Hash`, {
|
||||
getStdout: true,
|
||||
})
|
||||
).stdout.trim() || null;
|
||||
}
|
||||
const remote = remoteHashes[name] || null;
|
||||
let sharedDeps = [];
|
||||
if (type === "lang") {
|
||||
const cfg = langConfigs[lang];
|
||||
sharedDeps = ((cfg.install && cfg.install.riju) || []).map(
|
||||
(id) => sharedUUIDs[id]
|
||||
);
|
||||
}
|
||||
return {
|
||||
id: uuids[name],
|
||||
deps: [
|
||||
...(deps || []),
|
||||
...(type === "config" ? [langUUIDs[lang]] : []),
|
||||
...sharedDeps,
|
||||
],
|
||||
artifact: "Debian package",
|
||||
name,
|
||||
desired,
|
||||
local,
|
||||
remote,
|
||||
download: async () => {
|
||||
await runCommand(`make download L=${lang} T=${type}`);
|
||||
},
|
||||
build: async () => {
|
||||
await runCommand(
|
||||
`make shell I=packaging CMD="make pkg L=${lang} T=${type}"`
|
||||
);
|
||||
},
|
||||
upload: async () => {
|
||||
if (type === "config") {
|
||||
const clauses = [];
|
||||
for (const dep of (langConfigs[lang].install || {}).riju || []) {
|
||||
clauses.push(`make install T=shared L=${dep}`);
|
||||
}
|
||||
clauses.push(`make installs L=${lang}`);
|
||||
clauses.push("make test");
|
||||
await runCommand(`make shell I=base CMD="${clauses.join(" && ")}"`);
|
||||
}
|
||||
await runCommand(`make upload L=${lang} T=${type}`);
|
||||
},
|
||||
type,
|
||||
lang,
|
||||
};
|
||||
})
|
||||
);
|
||||
const lazilyDownloadedLanguages = new Set();
|
||||
for (const { type, lang, desired, local, remote } of plan) {
|
||||
if (type === "shared") {
|
||||
continue;
|
||||
}
|
||||
// If *not* a shared package, and all we have to do is download
|
||||
// it, then sort to the end. Unless of course this is the lang
|
||||
// package, and we need to rebuild the config package, in which
|
||||
// case the config package (which comes later) will remove that
|
||||
// lang from the set again.
|
||||
if (local !== desired && remote === desired) {
|
||||
lazilyDownloadedLanguages.add(lang);
|
||||
} else {
|
||||
lazilyDownloadedLanguages.delete(lang);
|
||||
}
|
||||
}
|
||||
return _.sortBy(plan, ({ type, lang }) => {
|
||||
return type !== "shared" && lazilyDownloadedLanguages.has(lang);
|
||||
});
|
||||
}
|
||||
|
||||
async function computePlan() {
|
||||
const dependentHashes = {
|
||||
"ubuntu:rolling": await getLocalImageDigest("ubuntu:rolling"),
|
||||
};
|
||||
const packaging = await planDockerImage("packaging", dependentHashes);
|
||||
const base = await planDockerImage("base", dependentHashes);
|
||||
const packages = await planDebianPackages({
|
||||
deps: [packaging.id, base.id],
|
||||
});
|
||||
const composite = await planDockerImage("composite", dependentHashes, {
|
||||
deps: [base.id, ...packages.map(({ id }) => id)],
|
||||
hashOpts: {
|
||||
salt: {
|
||||
packageHashes: packages.map(({ desired }) => desired).sort(),
|
||||
},
|
||||
},
|
||||
});
|
||||
const compile = await planDockerImage("compile", dependentHashes);
|
||||
const app = await planDockerImage("app", dependentHashes, {
|
||||
deps: [composite.id, compile.id],
|
||||
});
|
||||
return [packaging, base, ...packages, composite, compile, app];
|
||||
}
|
||||
|
||||
function printTable(data, headers) {
|
||||
const widths = headers.map(({ key, title }) =>
|
||||
Math.max(title.length, ...data.map((datum) => datum[key].length))
|
||||
|
|
|
@ -1,39 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
: ${DOCKER_REPO}
|
||||
: ${DOMAIN}
|
||||
: ${S3_BUCKET}
|
||||
|
||||
if [[ -z "${DEPLOY_SSH_PRIVATE_KEY:-}" ]]; then
|
||||
: ${DEPLOY_SSH_PUBLIC_KEY_FILE}
|
||||
DEPLOY_SSH_PRIVATE_KEY="$(base64 < "${DEPLOY_SSH_PUBLIC_KEY_FILE%.pub}")"
|
||||
fi
|
||||
|
||||
tmpdir="$(mktemp -d)"
|
||||
|
||||
function cleanup {
|
||||
rm -rf "${tmpdir}"
|
||||
}
|
||||
|
||||
trap cleanup EXIT
|
||||
|
||||
make pull-base all-scripts
|
||||
|
||||
node tools/plan-publish.js --execute --publish --show-all --omit-unneeded-downloads \
|
||||
| tee "${tmpdir}/plan-publish.out"
|
||||
|
||||
if ! grep -F "plan-publish is tagging app image" "${tmpdir}/plan-publish.out"; then
|
||||
echo "publish.bash: no changes to app image, so not deploying" >&2
|
||||
exit 0
|
||||
fi
|
||||
|
||||
sha="$(git describe --match=always-omit-tag --always --abbrev=40 --dirty)"
|
||||
|
||||
image="${DOCKER_REPO}:app-${sha}"
|
||||
|
||||
docker tag "${DOCKER_REPO}:app" "${image}"
|
||||
docker push "${image}"
|
||||
|
||||
exec tools/deploy.bash "${image}"
|
Loading…
Reference in New Issue