diff --git a/Makefile b/Makefile index 0d4d35d..6286b1d 100644 --- a/Makefile +++ b/Makefile @@ -224,11 +224,12 @@ upload: # L= T= : Upload .deb to S3 aws s3 cp $(BUILD)/$(DEB) $(S3_DEB) hash="$$(dpkg-deb -f $(BUILD)/$(DEB) Riju-Script-Hash | grep .)"; aws s3 cp - "$(S3_HASH)/$${hash}" < /dev/null -config: # Generate deployment config file +deploy-config: # Generate deployment config file node tools/generate-deploy-config.js -deploy: # Upload deployment config to S3 +deploy: deploy-config # Upload deployment config to S3 and update ASG instances aws s3 cp $(BUILD)/config.json $(S3_CONFIG) + tools/force-update-asg.bash ### Infrastructure diff --git a/backend/api.js b/backend/api.js index d930d25..689beae 100644 --- a/backend/api.js +++ b/backend/api.js @@ -312,9 +312,9 @@ export class Session { this.send({ event: "terminalClear" }); let cmdline; if (code) { - cmdline = run; + cmdline = `set +e; ${run}`; if (compile) { - cmdline = `( ${compile} ) && ( set +e; ${run} )`; + cmdline = `( ${compile} ) && ( ${run} )`; } } else if (repl) { cmdline = repl; diff --git a/docker/app/Dockerfile b/docker/app/Dockerfile index b970056..aa1b828 100644 --- a/docker/app/Dockerfile +++ b/docker/app/Dockerfile @@ -7,7 +7,7 @@ WORKDIR /src COPY Makefile ./ COPY system ./system/ -RUN make system +RUN make system UNPRIVILEGED=1 COPY package.json yarn.lock ./ RUN yarn install diff --git a/langs/unison.yaml b/langs/unison.yaml index d9fc00c..e6d1d62 100644 --- a/langs/unison.yaml +++ b/langs/unison.yaml @@ -38,25 +38,37 @@ input: | output: | base.List.reverse +# runProg implementation courtesy of Robert Offner from Unison Slack! main: "main.u" template: | use io - main : '{IO} () - main = 'let + runProg: '{IO, Exception} a -> '{IO} () + runProg f = 'let + printErr err = match err with + Failure _ errMsg _ -> handle putBytes (stdHandle StdErr) (toUtf8 errMsg) with cases + {raise _ -> _} -> () + {_} -> () + match catch f with + Left err -> printErr err + Right _ -> () + + main: '{IO} () + main = runProg 'let printLine "Hello, world!" +createEmpty: "" run: | - echo "Type 'run main' to run the code." + unison -codebase . run.file main.u main + echo "Type 'load main.u' at the repl prompt to bring variables into scope." unison -codebase . -helloInput: | - DELAY: 3 - run main scope: code: | x = 123 * 234 input: | + DELAY: 3 + load main.u DELAY: 3 add x DELAY: 3 diff --git a/supervisor/src/main.go b/supervisor/src/main.go index f284afe..bbd2f49 100644 --- a/supervisor/src/main.go +++ b/supervisor/src/main.go @@ -33,8 +33,8 @@ const blueName = "riju-app-blue" const greenName = "riju-app-green" type deploymentConfig struct { - LangImageTags map[string]string `json:"langImageTags"` AppImageTag string `json:"appImageTag"` + LangImageTags map[string]string `json:"langImageTags"` } type supervisorConfig struct { diff --git a/system/compile.bash b/system/compile.bash index 3907274..24bee70 100755 --- a/system/compile.bash +++ b/system/compile.bash @@ -18,7 +18,7 @@ for src in system/src/*.c; do out="${src/src/out}" out="${out/.c}" verbosely clang -Wall -Wextra -Werror -std=c11 "${src}" -o "${out}" - if [[ "${out}" == *-privileged ]]; then + if [[ "${out}" == *-privileged && -z "${UNPRIVILEGED:-}" ]]; then verbosely sudo chown root:riju "${out}" verbosely sudo chmod a=,g=rx,u=rwxs "${out}" fi diff --git a/tools/depgraph.js b/tools/depgraph.js index 0760c29..9c4030c 100644 --- a/tools/depgraph.js +++ b/tools/depgraph.js @@ -250,9 +250,22 @@ async function getLanguageTestArtifact({ lang }) { }; } -async function getDeployArtifact(langs) { +async function getDeployReadyArtifact(langs) { return { - name: `deploy:prod`, + name: `deploy:ready`, + dependencies: ["image:app"] + .concat(langs.map((lang) => `image:lang-${lang}`)) + .concat(langs.map((lang) => `test:lang-${lang}`)), + publishTarget: true, + publishToRegistry: async () => { + await runCommand(`make deploy-config`); + }, + }; +} + +async function getDeployLiveArtifact(langs) { + return { + name: `deploy:live`, dependencies: ["image:app"] .concat(langs.map((lang) => `image:lang-${lang}`)) .concat(langs.map((lang) => `test:lang-${lang}`)), @@ -298,7 +311,8 @@ async function getDepGraph() { artifacts.push(await getLanguageTestArtifact({ lang: lang })); } artifacts.push(await getImageArtifact({ tag: "app" })); - artifacts.push(await getDeployArtifact(langs)); + artifacts.push(await getDeployReadyArtifact(langs)); + artifacts.push(await getDeployLiveArtifact(langs)); return { informationalDependencies, artifacts }; } diff --git a/tools/generate-deploy-config.js b/tools/generate-deploy-config.js index b3c6d25..a56e437 100644 --- a/tools/generate-deploy-config.js +++ b/tools/generate-deploy-config.js @@ -1,10 +1,29 @@ import { promises as fs } from "fs"; import url from "url"; +import { Command } from "commander"; + +import { getLangs } from "../lib/yaml.js"; +import { getLocalImageLabel } from "./docker-util.js"; + // Get the contents of the JSON file that will be written to S3 in // order to deploy Riju. async function getDeployConfig() { - // TODO + const langs = await getLangs(); + const langImageTags = Object.fromEntries( + await Promise.all( + langs.map(async (lang) => [ + lang, + `lang-${lang}-` + + (await getLocalImageLabel(`riju:lang-${lang}`, "riju.image-hash")), + ]) + ) + ); + const appImageTag = await getLocalImageLabel(`riju:app`, "riju.image-hash"); + return { + appImageTag, + langImageTags, + } } // Parse command-line arguments, run main functionality, and exit.