Finish up initial depgraph, remove dead code

This commit is contained in:
Radon Rosborough 2021-03-21 14:50:45 -07:00
parent 1b975de021
commit 00c3a4117a
4 changed files with 16 additions and 229 deletions

View File

@ -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)) {

View File

@ -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}"

View File

@ -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))

View File

@ -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}"