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

fix: avoid confusion if setup-auth is already ran before #12

Merged
merged 11 commits into from
Apr 17, 2024
2 changes: 1 addition & 1 deletion .github/workflows/publish-docker-prod.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ jobs:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3

# Setup gcloud CLI
- uses: google-github-actions/setup-gcloud@v0
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/publish-docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ jobs:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3

# Setup gcloud CLI
- uses: google-github-actions/setup-gcloud@v0
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ jobs:
runs-on: ubuntu-latest

steps:
- uses: 'actions/checkout@v1'
- uses: 'actions/checkout@v3'

- name: 'Build'
run: 'docker build -t helm .'
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM alpine:3.15.0
FROM alpine:3.18.0

ENV BASE_URL="https://get.helm.sh"

Expand Down
105 changes: 75 additions & 30 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const readFile = util.promisify(fs.readFile);
const deleteFile = util.promisify(fs.rm);
const required = { required: true };

const GCLOUD_BINARY = '/opt/google-cloud-sdk/bin/gcloud';
const GCLOUD_BINARY = "/opt/google-cloud-sdk/bin/gcloud";

/**
* Status marks the deployment status. Only activates if token is set as an
Expand Down Expand Up @@ -38,8 +38,8 @@ async function status(state) {
log_url: url,
target_url: url,
headers: {
accept: 'application/vnd.github.ant-man-preview+json'
}
accept: "application/vnd.github.ant-man-preview+json",
},
});
} catch (error) {
core.warning(`Failed to set deployment status: ${error.message}`);
Expand Down Expand Up @@ -96,15 +96,15 @@ function getValueFiles(files) {
if (!Array.isArray(fileList)) {
return [];
}
return fileList.filter(f => !!f);
return fileList.filter((f) => !!f);
}

function getInput(name, options) {
const context = github.context;
const deployment = context.payload.deployment;
let val = core.getInput(name.replace("_", "-"), {
...options,
required: false
required: false,
});
if (deployment) {
if (deployment[name]) val = deployment[name];
Expand All @@ -126,7 +126,7 @@ function renderFiles(files, data) {
`rendering value files [${files.join(",")}] with: ${JSON.stringify(data)}`
);
const tags = ["${{", "}}"];
const promises = files.map(async file => {
const promises = files.map(async (file) => {
const content = await readFile(file, { encoding: "utf8" });
const rendered = Mustache.render(content, data, {}, tags);
await writeFile(file, rendered);
Expand All @@ -149,13 +149,42 @@ function deleteCmd(helm, namespace, release) {
}

async function setupClusterAuthentication(project, location, name, sa_json) {
core.info('Setting up GKE authentication');
core.info("Setting up GKE authentication");
await writeFile("sa.json", sa_json);
await exec.exec(GCLOUD_BINARY, ['auth', 'activate-service-account', '--key-file=sa.json']);
await exec.exec(GCLOUD_BINARY, ['container', 'clusters', 'get-credentials', name, '--zone', location, '--project', project]);
const account = JSON.parse(sa_json).client_email; // get the account passed in. this will prevent issues when multiple accounts have been activated
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is new

await exec.exec(GCLOUD_BINARY, [
"auth",
"activate-service-account",
"--key-file=sa.json",
]);
await exec.exec(GCLOUD_BINARY, [
"container",
"clusters",
"get-credentials",
name,
"--zone",
location,
"--project",
project,
"--account",
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is new

account,
]);
await deleteFile("sa.json");
}

function unsetGloudariables() {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

new

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and with typo's

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hehe 🙈
you're very right

delete process.env.CLOUDSDK_AUTH_CREDENTIAL_FILE_OVERRIDE;
delete process.env.GOOGLE_APPLICATION_CREDENTIALS;
delete process.env.GOOGLE_GHA_CREDS_PATH;
delete process.env.CLOUDSDK_CORE_PROJECT;
delete process.env.CLOUDSDK_PROJECT;
delete process.env.GCLOUD_PROJECT;
delete process.env.GCP_PROJECT;
delete process.env.GOOGLE_CLOUD_PROJECT;
delete process.env.CLOUDSDK_METRICS_ENVIRONMENT;
delete process.env.CLOUDSDK_METRICS_ENVIRONMENT_VERSION;
}

/**
* Run executes the helm deployment.
*/
Expand All @@ -164,6 +193,8 @@ async function run() {
const context = github.context;
await status("pending");

unsetGloudariables();
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

new


const cluster_project = getInput("clusterproject", required);
const cluster_location = getInput("clusterlocation", required);
const cluster_name = getInput("clustername", required);
Expand All @@ -186,11 +217,10 @@ async function run() {
const dryRun = core.getInput("dry-run");
const secrets = getSecrets(core.getInput("secrets"));
const atomic = getInput("atomic") || true;
const ttl = getInput("ttl") || 'false';
const ttl = getInput("ttl") || "false";
// only needed when ttl is specified
// this service account is used when ttl has expired inside the cronjob context.
const service_account = getInput("service_account") || 'helm-ttl-plugin';

const service_account = getInput("service_account") || "helm-ttl-plugin";

core.debug(`param: cluster_project = "${cluster_project}"`);
core.debug(`param: cluster_location = "${cluster_location}"`);
Expand All @@ -217,14 +247,21 @@ async function run() {

// Assert that if ttl is set that release contains '-pr-'
if (helm === "helm3" && ttl !== "false") {
if (!release.includes('-pr-')) {
core.error("ttl is set but release name does not contain '-pr-'. Aborting!");
if (!release.includes("-pr-")) {
core.error(
"ttl is set but release name does not contain '-pr-'. Aborting!"
);
process.exit(1);
}
}

// Setup GKE cluster authentication
await setupClusterAuthentication(cluster_project, cluster_location, cluster_name, cluster_sajson);
await setupClusterAuthentication(
cluster_project,
cluster_location,
cluster_name,
cluster_sajson
);

// Setup command options and arguments.
const args = [
Expand All @@ -237,15 +274,15 @@ async function run() {

// 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/"
process.env.HELM_PLUGINS = "/root/.local/share/helm/plugins"
process.env.HELM_DATA_HOME = "/root/.local/share/helm"
process.env.HELM_CACHE_HOME = "/root/.cache/helm"
process.env.HELM_CONFIG_HOME = "/root/.config/helm"
process.env.XDG_DATA_HOME = "/root/.helm/";
process.env.XDG_CACHE_HOME = "/root/.helm/";
process.env.XDG_CONFIG_HOME = "/root/.helm/";
process.env.HELM_PLUGINS = "/root/.local/share/helm/plugins";
process.env.HELM_DATA_HOME = "/root/.local/share/helm";
process.env.HELM_CACHE_HOME = "/root/.cache/helm";
process.env.HELM_CONFIG_HOME = "/root/.config/helm";
} else {
process.env.HELM_HOME = "/root/.helm/"
process.env.HELM_HOME = "/root/.helm/";
}

if (dryRun) args.push("--dry-run");
Expand All @@ -254,7 +291,7 @@ async function run() {
if (chartVersion) args.push(`--version=${chartVersion}`);
if (timeout) args.push(`--timeout=${timeout}`);
if (repository) args.push(`--repo=${repository}`);
valueFiles.forEach(f => args.push(`--values=${f}`));
valueFiles.forEach((f) => args.push(`--values=${f}`));
args.push("--values=./values.yml");

// Special behaviour is triggered if the track is labelled 'canary'. The
Expand Down Expand Up @@ -288,33 +325,41 @@ async function run() {
if (removeCanary) {
core.debug(`removing canary ${appName}-canary`);
await exec.exec(helm, deleteCmd(helm, namespace, `${appName}-canary`), {
ignoreReturnCode: true
ignoreReturnCode: true,
});
}

// Actually execute the deployment here.
if (task === "remove") {
if (helm === "helm3") { // delete ttl cronjob in case it was set (it is not required).
if (helm === "helm3") {
// delete ttl cronjob in case it was set (it is not required).
await exec.exec(
helm,
[`--namespace=${namespace}`, "release", "ttl", release, `--unset`],
{env: process.env, ignoreReturnCode: true}
{ env: process.env, ignoreReturnCode: true }
);
}

await exec.exec(helm, deleteCmd(helm, namespace, release), {
ignoreReturnCode: true
ignoreReturnCode: true,
});
} else {
await exec.exec(helm, args);
}

// Set ttl if set
if (helm === "helm3" && ttl !== "false") {
core.info('Setting ttl: ' + ttl);
core.info("Setting ttl: " + ttl);
await exec.exec(
helm,
[`--namespace=${namespace}`, "release", "ttl", release, `--service-account=${service_account}`, `--set=${ttl}`],
[
`--namespace=${namespace}`,
"release",
"ttl",
release,
`--service-account=${service_account}`,
`--set=${ttl}`,
],
{ env: process.env }
);
}
Expand Down
2 changes: 1 addition & 1 deletion tests/scenarios/canary.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
INPUT_CLUSTERPROJECT="GKEproject" \
INPUT_CLUSTERLOCATION="GKElocation" \
INPUT_CLUSTERNAME="clusterName" \
INPUT_CLUSTERSAJSON='{"json":"here"}' \
INPUT_CLUSTERSAJSON='{"json":"here", "client_email":"[email protected]"}' \
INPUT_TOKEN=foo \
INPUT_SECRETS='{"secret": "val"}' \
INPUT_CHART=app \
Expand Down
6 changes: 3 additions & 3 deletions tests/scenarios/canary.sh.snap
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
::debug::param: cluster_project = "GKEproject"
::debug::param: cluster_location = "GKElocation"
::debug::param: cluster_name = "clusterName"
::debug::param: cluster_sajson = "{"json":"here"}"
::debug::param: cluster_sajson = "{"json":"here", "client_email":"[email protected]"}"
::debug::param: track = "canary"
::debug::param: release = "app-canary"
::debug::param: appName = "app"
Expand All @@ -24,8 +24,8 @@
Setting up GKE authentication
[command]/opt/google-cloud-sdk/bin/gcloud auth activate-service-account --key-file=sa.json
gcloud auth activate-service-account --key-file=sa.json
[command]/opt/google-cloud-sdk/bin/gcloud container clusters get-credentials clusterName --zone GKElocation --project GKEproject
gcloud container clusters get-credentials clusterName --zone GKElocation --project GKEproject
[command]/opt/google-cloud-sdk/bin/gcloud container clusters get-credentials clusterName --zone GKElocation --project GKEproject --account [email protected]
gcloud container clusters get-credentials clusterName --zone GKElocation --project GKEproject --account [email protected]
::debug::env: KUBECONFIG="undefined"
::debug::rendering value files [./values.yml] with: {"secrets":{"secret":"val"}}
[command]/tmp/bin/helm upgrade app-canary /usr/src/charts/app --install --namespace=default --set=app.name=app --set=app.version=1234 --values=./values.yml --set=service.enabled=false --set=ingress.enabled=false --atomic
Expand Down
2 changes: 1 addition & 1 deletion tests/scenarios/helm3.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
INPUT_CLUSTERPROJECT="GKEproject" \
INPUT_CLUSTERLOCATION="GKElocation" \
INPUT_CLUSTERNAME="clusterName" \
INPUT_CLUSTERSAJSON='{"json":"here"}' \
INPUT_CLUSTERSAJSON='{"json":"here", "client_email":"[email protected]"}' \
INPUT_HELM=helm3 \
INPUT_TOKEN=foo \
INPUT_SECRETS='{"secret": "val"}' \
Expand Down
6 changes: 3 additions & 3 deletions tests/scenarios/helm3.sh.snap
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
::debug::param: cluster_project = "GKEproject"
::debug::param: cluster_location = "GKElocation"
::debug::param: cluster_name = "clusterName"
::debug::param: cluster_sajson = "{"json":"here"}"
::debug::param: cluster_sajson = "{"json":"here", "client_email":"[email protected]"}"
::debug::param: track = "stable"
::debug::param: release = "app"
::debug::param: appName = "app"
Expand All @@ -24,8 +24,8 @@
Setting up GKE authentication
[command]/opt/google-cloud-sdk/bin/gcloud auth activate-service-account --key-file=sa.json
gcloud auth activate-service-account --key-file=sa.json
[command]/opt/google-cloud-sdk/bin/gcloud container clusters get-credentials clusterName --zone GKElocation --project GKEproject
gcloud container clusters get-credentials clusterName --zone GKElocation --project GKEproject
[command]/opt/google-cloud-sdk/bin/gcloud container clusters get-credentials clusterName --zone GKElocation --project GKEproject --account [email protected]
gcloud container clusters get-credentials clusterName --zone GKElocation --project GKEproject --account [email protected]
::debug::env: KUBECONFIG="undefined"
::debug::rendering value files [./values.yml] with: {"secrets":{"secret":"val"}}
[command]/tmp/bin/helm3 upgrade app /usr/src/charts/app --install --namespace=default --set=app.name=app --set=app.version=1234 --values=./values.yml --atomic
Expand Down
2 changes: 1 addition & 1 deletion tests/scenarios/production.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
INPUT_CLUSTERPROJECT="GKEproject" \
INPUT_CLUSTERLOCATION="GKElocation" \
INPUT_CLUSTERNAME="clusterName" \
INPUT_CLUSTERSAJSON='{"json":"here"}' \
INPUT_CLUSTERSAJSON='{"json":"here", "client_email":"[email protected]"}' \
INPUT_TOKEN=foo \
INPUT_SECRETS='{"secret": "val"}' \
INPUT_CHART=app \
Expand Down
6 changes: 3 additions & 3 deletions tests/scenarios/production.sh.snap
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
::debug::param: cluster_project = "GKEproject"
::debug::param: cluster_location = "GKElocation"
::debug::param: cluster_name = "clusterName"
::debug::param: cluster_sajson = "{"json":"here"}"
::debug::param: cluster_sajson = "{"json":"here", "client_email":"[email protected]"}"
::debug::param: track = "stable"
::debug::param: release = "app"
::debug::param: appName = "app"
Expand All @@ -24,8 +24,8 @@
Setting up GKE authentication
[command]/opt/google-cloud-sdk/bin/gcloud auth activate-service-account --key-file=sa.json
gcloud auth activate-service-account --key-file=sa.json
[command]/opt/google-cloud-sdk/bin/gcloud container clusters get-credentials clusterName --zone GKElocation --project GKEproject
gcloud container clusters get-credentials clusterName --zone GKElocation --project GKEproject
[command]/opt/google-cloud-sdk/bin/gcloud container clusters get-credentials clusterName --zone GKElocation --project GKEproject --account [email protected]
gcloud container clusters get-credentials clusterName --zone GKElocation --project GKEproject --account [email protected]
::debug::env: KUBECONFIG="undefined"
::debug::rendering value files [./values.yml] with: {"secrets":{"secret":"val"}}
[command]/tmp/bin/helm upgrade app /usr/src/charts/app --install --namespace=default --set=app.name=app --set=app.version=1234 --timeout=30 --values=./values.yml --atomic
Expand Down
2 changes: 1 addition & 1 deletion tests/scenarios/ttl.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
INPUT_CLUSTERPROJECT="GKEproject" \
INPUT_CLUSTERLOCATION="GKElocation" \
INPUT_CLUSTERNAME="clusterName" \
INPUT_CLUSTERSAJSON='{"json":"here"}' \
INPUT_CLUSTERSAJSON='{"json":"here", "client_email":"[email protected]"}' \
INPUT_HELM=helm3 \
INPUT_TOKEN=foo \
INPUT_SECRETS='{"secret": "val"}' \
Expand Down
6 changes: 3 additions & 3 deletions tests/scenarios/ttl.sh.snap
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
::debug::param: cluster_project = "GKEproject"
::debug::param: cluster_location = "GKElocation"
::debug::param: cluster_name = "clusterName"
::debug::param: cluster_sajson = "{"json":"here"}"
::debug::param: cluster_sajson = "{"json":"here", "client_email":"[email protected]"}"
::debug::param: track = "stable"
::debug::param: release = "app-pr-123"
::debug::param: appName = "app-pr-123"
Expand All @@ -24,8 +24,8 @@
Setting up GKE authentication
[command]/opt/google-cloud-sdk/bin/gcloud auth activate-service-account --key-file=sa.json
gcloud auth activate-service-account --key-file=sa.json
[command]/opt/google-cloud-sdk/bin/gcloud container clusters get-credentials clusterName --zone GKElocation --project GKEproject
gcloud container clusters get-credentials clusterName --zone GKElocation --project GKEproject
[command]/opt/google-cloud-sdk/bin/gcloud container clusters get-credentials clusterName --zone GKElocation --project GKEproject --account [email protected]
gcloud container clusters get-credentials clusterName --zone GKElocation --project GKEproject --account [email protected]
::debug::env: KUBECONFIG="undefined"
::debug::rendering value files [./values.yml] with: {"secrets":{"secret":"val"}}
[command]/tmp/bin/helm3 upgrade app-pr-123 /usr/src/charts/app --install --namespace=default --set=app.name=app-pr-123 --set=app.version=1234 --values=./values.yml --atomic
Expand Down
Loading