Skip to content

Commit 554ba53

Browse files
committed
feat(helm/test-chart): add input to force chart lint and install
Signed-off-by: Emilien Escalle <[email protected]>
1 parent 5a2c3ea commit 554ba53

File tree

11 files changed

+180
-110
lines changed

11 files changed

+180
-110
lines changed

.github/workflows/__test-action-docker-prune-pull-requests-image-tags.yml

+4-3
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@ jobs:
4646
"name": "test-prune-${{ github.run_number }}",
4747
"context": ".",
4848
"dockerfile": "./tests/application/Dockerfile",
49-
"target": "prod",
49+
"build-args": { "BUILD_RUN_ID": "${{ github.run_id }}" },
50+
"target": "base",
5051
"platforms": ["linux/amd64","linux/arm64"]
5152
}
5253
]
@@ -67,7 +68,7 @@ jobs:
6768
username: ${{ github.repository_owner }}
6869
password: ${{ secrets.GITHUB_TOKEN }}
6970

70-
- name: Push extra docker image tags for test
71+
- name: Generate a image tag that should be deleted
7172
run: |
7273
BASE_IMAGE=$(echo '${{ needs.arrange.outputs.built-images }}' | jq -r '."${{ env.IMAGE }}".images[0]')
7374
NEW_IMAGE=ghcr.io/hoverkraft-tech/ci-github-container/${{ env.IMAGE }}:${{ needs.setup.outputs.tag }}
@@ -112,7 +113,7 @@ jobs:
112113
assert.equal(deletedImageTagsForCurrentPullRequest.length, 0, `"deleted-image-tags" output contains current pull request image tag`);
113114
}
114115
115-
- name: Assert - Ensure packages versions have been deleted
116+
- name: Assert - Ensure expected packages versions have been deleted
116117
uses: actions/[email protected]
117118
with:
118119
github-token: ${{ github.token }}

.github/workflows/__test-action-helm-test-chart.yml

+27-10
Original file line numberDiff line numberDiff line change
@@ -7,28 +7,45 @@ on:
77

88
permissions:
99
contents: read
10-
packages: read
10+
issues: read
11+
packages: write
12+
pull-requests: read
13+
# FIXME: This is a workaround for having workflow actions. See https://github.com/orgs/community/discussions/38659
14+
id-token: write
1115

1216
jobs:
13-
tests:
17+
build-test-images:
18+
uses: ./.github/workflows/docker-build-images.yml
19+
secrets:
20+
oci-registry-password: ${{ secrets.GITHUB_TOKEN }}
21+
with:
22+
images: |
23+
[
24+
{
25+
"name": "application-test",
26+
"context": ".",
27+
"dockerfile": "./tests/application/Dockerfile",
28+
"target": "prod",
29+
"platforms": ["linux/amd64"],
30+
"tag": "0.1.0"
31+
}
32+
]
33+
34+
test-lint-and-install:
1435
name: Test for "helm/test-chart" action
36+
needs: build-test-images
1537
runs-on: ubuntu-latest
1638
steps:
1739
- uses: actions/checkout@v4
1840

19-
- id: get-image-metadata
20-
uses: ./actions/docker/get-image-metadata
21-
with:
22-
oci-registry: ghcr.io
23-
image: application-test
24-
2541
- id: test-chart
2642
uses: ./actions/helm/test-chart
2743
with:
44+
check-diff-only: false
2845
helm-set: |
29-
image.tag=${{ steps.get-image-metadata.outputs.tags }}
46+
image.tag=0.1.0
3047
helm-repositories: |
3148
bitnami https://charts.bitnami.com/bitnami
3249
oci-registry: ghcr.io
33-
oci-registry-username: ${{ github.actor }}
50+
oci-registry-username: ${{ github.repository_owner }}
3451
oci-registry-password: ${{ secrets.GITHUB_TOKEN }}

.github/workflows/__test-workflow-docker-build-images.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -41,15 +41,15 @@ jobs:
4141
"context": ".",
4242
"dockerfile": "./tests/application/Dockerfile",
4343
"build-args": { "BUILD_RUN_ID": "${{ github.run_id }}" },
44-
"target": "prod",
44+
"target": "base",
4545
"platforms": ["linux/amd64","linux/arm64","linux/arm/v7"]
4646
},
4747
{
4848
"name": "test-mono-arch",
4949
"context": ".",
5050
"dockerfile": "./tests/application/Dockerfile",
5151
"build-args": { "BUILD_RUN_ID": "${{ github.run_id }}" },
52-
"target": "prod",
52+
"target": "base",
5353
"platforms": ["linux/amd64"],
5454
"tag": "0.1.0"
5555
}

.prettierignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
**/tests/charts/*/**/*.yaml

Makefile

+9
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,15 @@ lint-fix: ## Execute linting and fix
1313
-e FIX_MARKDOWN_PRETTIER=true \
1414
-e FIX_NATURAL_LANGUAGE=true)
1515

16+
test-build-application: ## Build the test application image
17+
@docker buildx build \
18+
--push --platform linux/amd64,linux/arm64 \
19+
--target prod \
20+
-t ghcr.io/hoverkraft-tech/ci-github-container/application-test:0.1.0 ./tests/application
21+
22+
test-ct-install: ## Run ct install to install the test application
23+
@ct install --config ct.yaml --helm-extra-set-args '--set=image.tag=0.1.0'
24+
1625
define run_linter
1726
DEFAULT_WORKSPACE="$(CURDIR)"; \
1827
LINTER_IMAGE="linter:latest"; \

actions/helm/test-chart/action.yml

+87-59
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
---
22
name: "Test Helm Chart"
3-
# yamllint disable-line rule:line-length
4-
description: "Action to test a Helm chart. Mainly using [helm/chart-testing-action](https://github.com/helm/chart-testing-action)"
3+
description: |
4+
Action to lint and test installing some Helm chart(s).
5+
Mainly using [helm/chart-testing-action](https://github.com/helm/chart-testing-action).
6+
57
branding:
68
icon: check-circle
79
color: gray-dark
@@ -41,15 +43,20 @@ inputs:
4143
See <https://github.com/docker/login-action#usage>.
4244
default: ${{ github.token }}
4345
required: false
46+
check-diff-only:
47+
description: |
48+
Only run lint and tests on changed charts.
49+
required: false
50+
default: "true"
4451
enable-lint:
4552
description: |
4653
Enable linting of the Helm chart.
4754
See <https://github.com/helm/chart-testing/blob/main/doc/ct_lint.md>.
4855
required: false
4956
default: "true"
50-
enable-test:
57+
enable-install:
5158
description: |
52-
Enable testing of the Helm chart.
59+
Enable installing the Helm chart.
5360
See <https://github.com/helm/chart-testing/blob/main/doc/ct_install.md>.
5461
required: false
5562
default: "true"
@@ -58,9 +65,9 @@ runs:
5865
using: "composite"
5966
steps:
6067
- shell: bash
61-
if: ${{ inputs.enable-lint != 'true' && inputs.enable-test != 'true' }}
68+
if: ${{ inputs.enable-lint != 'true' && inputs.enable-install != 'true' }}
6269
run: |
63-
echo "::error ::At least one of 'enable-lint' or 'enable-test' input must be true"
70+
echo "::error ::At least one of 'enable-lint' or 'enable-install' input must be true"
6471
exit 1
6572
6673
- uses: hoverkraft-tech/ci-github-common/actions/[email protected]
@@ -92,8 +99,6 @@ runs:
9299
fi
93100
94101
- uses: actions/setup-python@v5
95-
with:
96-
python-version: "3.12"
97102

98103
- name: Set up chart-testing
99104
uses: helm/[email protected]
@@ -110,86 +115,109 @@ runs:
110115
helm repo add $line
111116
done
112117
113-
- name: Run chart-testing (lint)
114-
if: ${{ inputs.enable-lint == 'true' }}
118+
- name: Prepare ct variables
119+
id: prepare-ct-variables
115120
shell: bash
116-
working-directory: ${{ inputs.working-directory }}
117121
run: |
118-
LINT_ARGS="--check-version-increment=false --target-branch ${{ github.event.repository.default_branch }}"
122+
if [ "${{ inputs.check-diff-only }}" == "true" ]; then
123+
if [ "${{ github.event_name }}" == "pull_request" ]; then
124+
TARGET_BRANCH="${{ github.event.pull_request.base.ref }}"
125+
else
126+
TARGET_BRANCH="${{ github.event.repository.default_branch }}"
127+
fi
128+
CT_ARGS="--target-branch $TARGET_BRANCH"
129+
fi
130+
119131
if [ -n "${{ steps.check-ct-yaml.outputs.path }}" ]; then
120-
LINT_ARGS="--config ${{ steps.check-ct-yaml.outputs.path }}"
132+
CT_ARGS="$CT_ARGS --config ${{ steps.check-ct-yaml.outputs.path }}"
121133
fi
122134
123-
ct lint $LINT_ARGS
135+
if [ -z "$CT_ARGS" ]; then
136+
CT_ARGS="--all"
137+
fi
124138
125-
- name: Create kind cluster
126-
if: ${{ inputs.enable-test == 'true' }}
127-
uses: helm/[email protected]
139+
echo "args=$CT_ARGS" >> "$GITHUB_OUTPUT"
140+
141+
# Namespace for the test cluster
142+
NAMESPACE="test-chart-${{ github.run_id}}-$(uuidgen)"
143+
echo "namespace=$NAMESPACE" >> "$GITHUB_OUTPUT"
128144
129-
- name: Install default registry secrets
130-
if: ${{ inputs.enable-test == 'true' }}
145+
- name: Run chart-testing (lint)
146+
if: ${{ inputs.enable-lint == 'true' }}
131147
shell: bash
148+
working-directory: ${{ inputs.working-directory }}
132149
run: |
133-
echo "DOCKER_REGISTRY=$DOCKER_REGISTRY"
134-
echo "DOCKER_USERNAME=${DOCKER_USERNAME: -4}" # last 4 characters
135-
echo "DOCKER_PASSWORD=${DOCKER_PASSWORD: -4}" # last 4 characters
136-
if [ -n "$DOCKER_USERNAME" ] && [ -n "$DOCKER_PASSWORD" ]; then
137-
kubectl create secret docker-registry regcred \
138-
--docker-server=$DOCKER_REGISTRY \
139-
--docker-username=$DOCKER_USERNAME \
140-
--docker-password=$DOCKER_PASSWORD
141-
else
142-
echo "Docker credentials not provided, skipping secret creation"
143-
fi
144-
env:
145-
DOCKER_REGISTRY: ${{ inputs.oci-registry }}
146-
DOCKER_USERNAME: ${{ inputs.oci-registry-username }}
147-
DOCKER_PASSWORD: ${{ inputs.oci-registry-password }}
150+
ct lint ${{ steps.prepare-ct-variables.outputs.args }}
148151
149-
- name: Define target branch
150-
if: ${{ inputs.enable-test == 'true' }}
151-
id: define-target-branch
152+
- name: Create kind cluster
153+
if: ${{ inputs.enable-install == 'true' }}
154+
uses: helm/[email protected]
155+
156+
- name: Install default OCI registry secrets
157+
id: oci-registry-secret
158+
if: ${{ inputs.enable-install == 'true' && inputs.oci-registry != '' && inputs.oci-registry-username != '' && inputs.oci-registry-password != '' }}
152159
shell: bash
153160
run: |
154-
if [ "${{ github.event_name }}" == "pull_request" ]; then
155-
TARGET_BRANCH="${{ github.event.pull_request.base.ref }}"
156-
else
157-
TARGET_BRANCH="${{ github.event.repository.default_branch }}"
158-
fi
159-
echo "target-branch=$TARGET_BRANCH" >> "$GITHUB_OUTPUT"
161+
# See https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/
162+
NAMESPACE="${{ steps.prepare-ct-variables.outputs.namespace }}"
163+
kubectl --context kind-chart-testing create namespace "$NAMESPACE"
164+
165+
SECRET_NAME="regcred"
166+
DOCKER_REGISTRY="${{ inputs.oci-registry }}"
167+
DOCKER_USERNAME="${{ inputs.oci-registry-username }}"
168+
DOCKER_PASSWORD="${{ inputs.oci-registry-password }}"
169+
170+
kubectl --context kind-chart-testing create secret docker-registry "$SECRET_NAME" \
171+
--namespace="$NAMESPACE" \
172+
--docker-server=$DOCKER_REGISTRY \
173+
--docker-username=$DOCKER_USERNAME \
174+
--docker-password=$DOCKER_PASSWORD
175+
176+
echo "oci-registry-secret=$SECRET_NAME" >> "$GITHUB_OUTPUT"
160177
161178
- name: Run chart-testing (install)
162-
if: ${{ inputs.enable-test == 'true' }}
179+
if: ${{ inputs.enable-install == 'true' }}
163180
shell: bash
164181
working-directory: ${{ inputs.working-directory }}
165182
env:
166183
HELM_EXPERIMENTAL_OCI: true
167184
run: |
168-
HELM_SET="${{ inputs.helm-set }}"
169-
HELM_EXTRA_SET_ARGS="imagePullSecrets[0].name=regcred"
185+
NAMESPACE="${{ steps.prepare-ct-variables.outputs.namespace }}"
186+
187+
HELM_SET="namespace=$NAMESPACE
188+
${{ inputs.helm-set }}"
189+
190+
OCI_REGISTRY_SECRET="${{ steps.oci-registry-secret.outputs.oci-registry-secret }}"
191+
if [ -n "$OCI_REGISTRY_SECRET" ]; then
192+
# Ensure secret exists
193+
kubectl --context kind-chart-testing get secret "$OCI_REGISTRY_SECRET" --output=yaml --namespace=$NAMESPACE
194+
195+
HELM_SET="$HELM_SET
196+
imagePullSecrets[0].name=${OCI_REGISTRY_SECRET}"
197+
fi
198+
199+
HELM_EXTRA_SET_ARGS=""
170200
if [ -n "$HELM_SET" ]; then
171201
IFS=$'\n' read -r -d '' -a lines <<< "$HELM_SET" || true
172-
173202
for line in "${lines[@]}"; do
174203
if [ -z "$line" ]; then
175204
continue
176205
fi
177206
# Escape commas in the line
178207
line=$(echo "$line" | sed 's/,/\\,/g') || true
179-
HELM_EXTRA_SET_ARGS+=",${line}"
180-
done
181208
182-
# Format HELM_EXTRA_SET_ARGS for helm command
183-
if [ -n "$HELM_EXTRA_SET_ARGS" ]; then
184-
HELM_EXTRA_SET_ARGS="--set ${HELM_EXTRA_SET_ARGS:1}"
185-
fi
209+
if [ -n "$HELM_EXTRA_SET_ARGS" ]; then
210+
HELM_EXTRA_SET_ARGS="${HELM_EXTRA_SET_ARGS},"
211+
fi
186212
187-
echo "::debug::helm-extra-set-args: $HELM_EXTRA_SET_ARGS"
213+
HELM_EXTRA_SET_ARGS="${HELM_EXTRA_SET_ARGS}${line}"
214+
done
188215
fi
189216
190-
TARGET_BRANCH="${{ steps.define-target-branch.outputs.target-branch }}"
217+
HELM_EXTRA_SET_ARGS="--set=${HELM_EXTRA_SET_ARGS}"
218+
219+
echo "::debug::ct install ${{ steps.prepare-ct-variables.outputs.args }} --helm-extra-set-args ${HELM_EXTRA_SET_ARGS}"
191220
192-
ct install \
193-
--target-branch "$TARGET_BRANCH" \
194-
--helm-extra-args "--wait" \
195-
--helm-extra-set-args "$HELM_EXTRA_SET_ARGS"
221+
ct install ${{ steps.prepare-ct-variables.outputs.args }} \
222+
--namespace $NAMESPACE \
223+
--helm-extra-set-args ${HELM_EXTRA_SET_ARGS}

tests/application/Dockerfile

+11-3
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,18 @@
11
FROM scratch AS base
22

3-
HEALTHCHECK --interval=5s --timeout=3s --retries=3 CMD ["/healthcheck"]
4-
53
USER test
64

7-
FROM base AS prod
5+
FROM nginx:1-alpine AS prod
6+
7+
HEALTHCHECK --interval=5s --timeout=3s --retries=3 CMD ["curl", "-f", "http://localhost:8080/health/check"]
8+
9+
# Configure nginx to listen on port 8080
10+
RUN sed -i 's/listen 80;/listen 8080;/' /etc/nginx/conf.d/default.conf
11+
12+
# Create a hmtl page for healthcheck
13+
RUN mkdir -p /usr/share/nginx/html/health/check && echo "<html><body><h1>OK</h1></body></html>" > /usr/share/nginx/html/health/check/index.html
14+
15+
EXPOSE 8080
816

917
FROM alpine:3 AS test
1018

0 commit comments

Comments
 (0)