Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

First add repo, then run deployment #3

Merged
merged 4 commits into from
Jan 25, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
276 changes: 147 additions & 129 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -145,150 +145,168 @@ 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 === "") {
throw new Error("repo alias is required when you are setting a repository");
}

// 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}`,
];

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}`);
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");

core.debug(`env: KUBECONFIG="${process.env.KUBECONFIG}"`);
// 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);

// Render value files using github variables.
await renderFiles(valueFiles.concat(["./values.yml"]), {
secrets,
deployment: context.payload.deployment,
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") || "helm3";
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);
Expand Down