From 8d177003551f2c9f2cd7fcc5c3cc61833985bd98 Mon Sep 17 00:00:00 2001 From: mpraski Date: Mon, 25 Jan 2021 16:11:01 +0100 Subject: [PATCH 1/4] First add repo, then run deployment --- index.js | 282 ++++++++++++++++++++++++++++++------------------------- 1 file changed, 153 insertions(+), 129 deletions(-) diff --git a/index.js b/index.js index 476dfb6d..3dd24a85 100644 --- a/index.js +++ b/index.js @@ -145,150 +145,174 @@ function deleteCmd(helm, namespace, release) { return ["delete", "--purge", release]; } -/** - * Run executes the helm deployment. +/* + * Optionally add a helm repository */ -async function run() { - try { - const context = github.context; - await status("pending"); +async function addRepo(helm) { + const repo = getInput("repo"); + const repoAlias = getInput("repo-alias"); + const repoUsername = getInput("repo-username"); + const repoPassword = getInput("repo-password"); - const track = getInput("track") || "stable"; - const appName = getInput("release", required); - const release = releaseName(appName, track); - const namespace = getInput("namespace", required); - const chart = chartName(getInput("chart", required)); - const chartVersion = getInput("chart_version"); - const values = getValues(getInput("values")); - const task = getInput("task"); - const version = getInput("version"); - const valueFiles = getValueFiles(getInput("value_files")); - const removeCanary = getInput("remove_canary"); - const helm = getInput("helm") || "helm"; - const timeout = getInput("timeout"); - const repo = getInput("repo"); - const repoAlias = getInput("repo-alias"); - const repoUsername = getInput("repo-username"); - const repoPassword = getInput("repo-password"); - const dryRun = core.getInput("dry-run"); - const secrets = getSecrets(core.getInput("secrets")); - const atomic = getInput("atomic") || true; - - core.debug(`param: track = "${track}"`); - core.debug(`param: release = "${release}"`); - core.debug(`param: appName = "${appName}"`); - core.debug(`param: namespace = "${namespace}"`); - core.debug(`param: chart = "${chart}"`); - core.debug(`param: chart_version = "${chartVersion}"`); - core.debug(`param: values = "${values}"`); - core.debug(`param: dryRun = "${dryRun}"`); - core.debug(`param: task = "${task}"`); - core.debug(`param: version = "${version}"`); - core.debug(`param: secrets = "${JSON.stringify(secrets)}"`); - core.debug(`param: valueFiles = "${JSON.stringify(valueFiles)}"`); - core.debug(`param: removeCanary = ${removeCanary}`); - core.debug(`param: timeout = "${timeout}"`); - core.debug(`param: atomic = "${atomic}"`); - core.debug(`param: repo = "${repo}"`); - core.debug(`param: repoAlias = "${repoAlias}"`); - core.debug(`param: repoUsername = "${repoUsername}"`); - core.debug(`param: repoPassword = "${repoPassword}"`); - - // Setup command options and arguments. - let args = [ - "upgrade", - release, - chart, - "--install", - "--wait", - `--namespace=${namespace}`, - ]; - - // Per https://helm.sh/docs/faq/#xdg-base-directory-support - if (helm === "helm3") { - process.env.XDG_DATA_HOME = "/root/.helm/" - process.env.XDG_CACHE_HOME = "/root/.helm/" - process.env.XDG_CONFIG_HOME = "/root/.helm/" - } else { - process.env.HELM_HOME = "/root/.helm/" - } + core.debug(`param: repo = "${repo}"`); + core.debug(`param: repoAlias = "${repoAlias}"`); + core.debug(`param: repoUsername = "${repoUsername}"`); + core.debug(`param: repoPassword = "${repoPassword}"`); - if (dryRun) args.push("--dry-run"); - if (appName) args.push(`--set=app.name=${appName}`); - if (version) args.push(`--set=app.version=${version}`); - if (chartVersion) args.push(`--version=${chartVersion}`); - if (timeout) args.push(`--timeout=${timeout}`); - valueFiles.forEach(f => args.push(`--values=${f}`)); - args.push("--values=./values.yml"); - - // Special behaviour is triggered if the track is labelled 'canary'. The - // service and ingress resources are disabled. Access to the canary - // deployments can be routed via the main stable service resource. - if (track === "canary") { - args.push("--set=service.enabled=false", "--set=ingress.enabled=false"); + if (repo !== "") { + if (repoAlias === "") { + core.setFailed("repo alias is required when you are setting a repository"); + return status("failure"); } - // If true upgrade process rolls back changes made in case of failed upgrade. - if (atomic === true) { - args.push("--atomic"); - } + core.debug(`adding custom repository ${repo} with alias ${repoAlias}`); - // Setup necessary files. - if (process.env.KUBECONFIG_FILE) { - process.env.KUBECONFIG = "./kubeconfig.yml"; - await writeFile(process.env.KUBECONFIG, process.env.KUBECONFIG_FILE); - } - await writeFile("./values.yml", values); + const args = [ + "repo", + "add", + repoAlias, + repo, + ] + + if (repoUsername) args.push(`--username=${repoUsername}`); + if (repoPassword) args.push(`--password=${repoPassword}`); + + return exec.exec(helm, args); + } + + return Promise.resolve() +} + +/* + * Deploy the release + */ +async function deploy(helm) { + const context = github.context; + + const track = getInput("track") || "stable"; + const appName = getInput("release", required); + const release = releaseName(appName, track); + const namespace = getInput("namespace", required); + const chart = chartName(getInput("chart", required)); + const chartVersion = getInput("chart_version"); + const values = getValues(getInput("values")); + const task = getInput("task"); + const version = getInput("version"); + const valueFiles = getValueFiles(getInput("value_files")); + const removeCanary = getInput("remove_canary"); + const timeout = getInput("timeout"); + const dryRun = core.getInput("dry-run"); + const secrets = getSecrets(core.getInput("secrets")); + const atomic = getInput("atomic") || true; + + core.debug(`param: track = "${track}"`); + core.debug(`param: release = "${release}"`); + core.debug(`param: appName = "${appName}"`); + core.debug(`param: namespace = "${namespace}"`); + core.debug(`param: chart = "${chart}"`); + core.debug(`param: chart_version = "${chartVersion}"`); + core.debug(`param: values = "${values}"`); + core.debug(`param: dryRun = "${dryRun}"`); + core.debug(`param: task = "${task}"`); + core.debug(`param: version = "${version}"`); + core.debug(`param: secrets = "${JSON.stringify(secrets)}"`); + core.debug(`param: valueFiles = "${JSON.stringify(valueFiles)}"`); + core.debug(`param: removeCanary = ${removeCanary}`); + core.debug(`param: timeout = "${timeout}"`); + core.debug(`param: atomic = "${atomic}"`); + + // Setup command options and arguments. + let args = [ + "upgrade", + release, + chart, + "--install", + "--wait", + `--namespace=${namespace}`, + ]; + + // Per https://helm.sh/docs/faq/#xdg-base-directory-support + if (helm === "helm3") { + process.env.XDG_DATA_HOME = "/root/.helm/" + process.env.XDG_CACHE_HOME = "/root/.helm/" + process.env.XDG_CONFIG_HOME = "/root/.helm/" + } else { + process.env.HELM_HOME = "/root/.helm/" + } + + if (dryRun) args.push("--dry-run"); + if (appName) args.push(`--set=app.name=${appName}`); + if (version) args.push(`--set=app.version=${version}`); + if (chartVersion) args.push(`--version=${chartVersion}`); + if (timeout) args.push(`--timeout=${timeout}`); + + valueFiles.forEach(f => args.push(`--values=${f}`)); - core.debug(`env: KUBECONFIG="${process.env.KUBECONFIG}"`); + args.push("--values=./values.yml"); - // Render value files using github variables. - await renderFiles(valueFiles.concat(["./values.yml"]), { - secrets, - deployment: context.payload.deployment, + // Special behaviour is triggered if the track is labelled 'canary'. The + // service and ingress resources are disabled. Access to the canary + // deployments can be routed via the main stable service resource. + if (track === "canary") { + args.push("--set=service.enabled=false", "--set=ingress.enabled=false"); + } + + // If true upgrade process rolls back changes made in case of failed upgrade. + if (atomic === true) { + args.push("--atomic"); + } + + // Setup necessary files. + if (process.env.KUBECONFIG_FILE) { + process.env.KUBECONFIG = "./kubeconfig.yml"; + await writeFile(process.env.KUBECONFIG, process.env.KUBECONFIG_FILE); + } + + await writeFile("./values.yml", values); + + core.debug(`env: KUBECONFIG="${process.env.KUBECONFIG}"`); + + // Render value files using github variables. + await renderFiles(valueFiles.concat(["./values.yml"]), { + secrets, + deployment: context.payload.deployment, + }); + + // Remove the canary deployment before continuing. + if (removeCanary) { + core.debug(`removing canary ${appName}-canary`); + await exec.exec(helm, deleteCmd(helm, namespace, `${appName}-canary`), { + ignoreReturnCode: true }); + } - // Remove the canary deployment before continuing. - if (removeCanary) { - core.debug(`removing canary ${appName}-canary`); - await exec.exec(helm, deleteCmd(helm, namespace, `${appName}-canary`), { - ignoreReturnCode: true - }); - } + // Actually execute the deployment here. + if (task === "remove") { + return exec.exec(helm, deleteCmd(helm, namespace, release), { + ignoreReturnCode: true + }); + } - if (repo !== "") { - if (repoAlias === "") { - core.setFailed("repo alias is required when you are setting a repository"); - await status("failure"); - } + return exec.exec(helm, args); +} - core.debug(`adding custom repository ${repo} with alias ${repoAlias}`); - const repoAddArgs = [ - "repo", - "add", - repoAlias, - repo, - ] - - if (repoUsername) repoAddArgs.push(`--username=${repoUsername}`); - if (repoPassword) repoAddArgs.push(`--password=${repoPassword}`); - - repoAddArgs.push(";"); - repoAddArgs.push(helm); - - args = repoAddArgs.concat(args) - } +/** + * Run executes the helm deployment. + */ +async function run() { + const commands = [addRepo, deploy] + + try { + await status("pending"); + + const helm = getInput("helm") || "helm"; + core.debug(`param: helm = "${helm}"`); - // Actually execute the deployment here. - if (task === "remove") { - await exec.exec(helm, deleteCmd(helm, namespace, release), { - ignoreReturnCode: true - }); - } else { - await exec.exec(helm, args); + for(const command of commands) { + await command(helm); } - await status(task === "remove" ? "inactive" : "success"); + await status("success"); } catch (error) { core.error(error); core.setFailed(error.message); From bf37844b14476488a474ada74cbf251a245f4fb5 Mon Sep 17 00:00:00 2001 From: mpraski Date: Mon, 25 Jan 2021 16:14:29 +0100 Subject: [PATCH 2/4] Use exception to signal failure --- index.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/index.js b/index.js index 3dd24a85..09478025 100644 --- a/index.js +++ b/index.js @@ -161,8 +161,7 @@ async function addRepo(helm) { if (repo !== "") { if (repoAlias === "") { - core.setFailed("repo alias is required when you are setting a repository"); - return status("failure"); + throw new Error("repo alias is required when you are setting a repository"); } core.debug(`adding custom repository ${repo} with alias ${repoAlias}`); From 66e7ea1f1370485a9763892d90fbc3957efecd9e Mon Sep 17 00:00:00 2001 From: mpraski Date: Mon, 25 Jan 2021 16:21:46 +0100 Subject: [PATCH 3/4] Default to helm3 --- index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.js b/index.js index 09478025..e0498f85 100644 --- a/index.js +++ b/index.js @@ -304,7 +304,7 @@ async function run() { try { await status("pending"); - const helm = getInput("helm") || "helm"; + const helm = getInput("helm") || "helm3"; core.debug(`param: helm = "${helm}"`); for(const command of commands) { From eef52034b40ddb2590128dbdb8b24c10513666d0 Mon Sep 17 00:00:00 2001 From: mpraski Date: Mon, 25 Jan 2021 16:23:45 +0100 Subject: [PATCH 4/4] Default options for helm3 --- index.js | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/index.js b/index.js index e0498f85..82a6ef23 100644 --- a/index.js +++ b/index.js @@ -230,14 +230,9 @@ async function deploy(helm) { `--namespace=${namespace}`, ]; - // Per https://helm.sh/docs/faq/#xdg-base-directory-support - if (helm === "helm3") { - process.env.XDG_DATA_HOME = "/root/.helm/" - process.env.XDG_CACHE_HOME = "/root/.helm/" - process.env.XDG_CONFIG_HOME = "/root/.helm/" - } else { - process.env.HELM_HOME = "/root/.helm/" - } + process.env.XDG_DATA_HOME = "/root/.helm/" + process.env.XDG_CACHE_HOME = "/root/.helm/" + process.env.XDG_CONFIG_HOME = "/root/.helm/" if (dryRun) args.push("--dry-run"); if (appName) args.push(`--set=app.name=${appName}`);