diff --git a/.github/workflows/vault_helm_lint_publish.yml b/.github/workflows/vault_helm_lint_publish.yml new file mode 100644 index 00000000..b640c705 --- /dev/null +++ b/.github/workflows/vault_helm_lint_publish.yml @@ -0,0 +1,77 @@ +name: "Test and publish Helm Chart" + +on: + workflow_call: + inputs: + release: + type: boolean + required: false + default: false + version: + type: string + required: false + chart-testing-config: + type: string + required: false + default: ".github/ct.yaml" + charts-path: + type: string + required: false + default: "./helm/charts/" + +jobs: + lint-chart: + runs-on: [self-hosted, shared] + steps: + - name: Run Chart lint + uses: LedgerHQ/actions/helm/lint@main + with: + chart-testing-config: ${{inputs.chart-testing-config}} + + kubeconform-chart: + runs-on: [self-hosted, shared] + strategy: + matrix: + k8s: + - v1.24.17 + - v1.23.17 + steps: + - name: Run the helm conform + uses: LedgerHQ/actions/helm/conform@main + with: + kubernetes-version: ${{ matrix.k8s }} + charts-path: ${{ inputs.charts-path }} + + publish-chartmuseum-dev: + name: publish-chartmuseum-dev + environment: chartmuseum-dev + if: inputs.version != '' + runs-on: [self-hosted, shared] + needs: [lint-chart, kubeconform-chart] + steps: + - name: Push chart to chartmuseum-prd repo + uses: LedgerHQ/actions/helm/publish-cm@main + with: + charts-path: ${{ inputs.charts-path }} + version: ${{ inputs.version }} + chartmuseum-url: ${{ secrets.CHARTMUSEUM_URL }} + chartmuseum-user: ${{ secrets.CHARTMUSEUM_USER }} + chartmuseum-password: ${{ secrets.CHARTMUSEUM_PASSWORD }} + force: startsWith( ${{ inputs.version}}, '0.0.0' ) + + publish-chartmuseum-prd: + name: publish-chartmuseum-prd + environment: chartmuseum-prd + if: inputs.version != '' && inputs.release != false + runs-on: [self-hosted, shared] + needs: [publish-chartmuseum-dev] + steps: + - name: Push chart to chartmuseum-prd repo + uses: LedgerHQ/actions/helm/publish-cm@main + with: + charts-path: ${{ inputs.charts-path }} + version: ${{ inputs.version }} + chartmuseum-url: ${{ secrets.CHARTMUSEUM_URL }} + chartmuseum-user: ${{ secrets.CHARTMUSEUM_USER }} + chartmuseum-password: ${{ secrets.CHARTMUSEUM_PASSWORD }} + force: startsWith( ${{ inputs.version}}, '0.0.0' ) diff --git a/helm/README.md b/helm/README.md new file mode 100644 index 00000000..5f27cd4b --- /dev/null +++ b/helm/README.md @@ -0,0 +1,53 @@ +# helm + +See the [Vault helm workflow](.github/workflows/vault_helm_lint_publish.yml) as an example. + +It is combining below actions to meet Vault needs. + +Please create your own reusable workflow matching your need + +## helm-conform action + +Check the chart conformity with K8 version + +```yaml + - name: Verify conformity + uses: LedgerHQ/actions/helm/conform@main + with: + kubernetes-version: "v1.23.17" # current default value + kuberconform-version: "v0.6.3" # current default value + charts-path: "./helm/charts/" # where helm charts are + schemas-path: ... # overriding schemas location +``` + +Here is the schemas-path [documentation](https://github.com/yannh/kubeconform#overriding-schemas-location) + +## helm-lint action + +Lint the helm chart + +```yaml + - name: Run lint on chart + uses: LedgerHQ/actions/helm/lint@main + with: + chart-testing-config: ... # the ct config + helm-docs-version: "1.11.0" # current default value +``` + +## helm-publish-cm action + +Push the chart to internal chartmuseum . +It need `secrets: inherit` to be used within another workflow + +```yaml + - uses: LedgerHQ/actions/helm/publish-cm@main + environment: prd # environment defining your CHARTMUSEUM secrets + with: + version: 1.2.3 # overwriting the chart version from Chart.yaml + chartmuseum-url: ${{ secrets.CHARTMUSEUM_URL }} + chartmuseum-user: ${{ secrets.CHARTMUSEUM_USER }} + chartmuseum-password: ${{ secrets.CHARTMUSEUM_PASSWORD }} + charts-path: "./helm/charts/" # where helm charts are + force: true # force overwriting helm charts in chartmuseum +``` + diff --git a/helm/conform/action.yml b/helm/conform/action.yml new file mode 100644 index 00000000..8f0563b0 --- /dev/null +++ b/helm/conform/action.yml @@ -0,0 +1,64 @@ +name: "Run Kubeconform" +description: "Run Kubeconform againt specified K8S version." + +inputs: + kubernetes-version: + description: "Specify the kubernetes version that you want to test." + required: true + default: "v1.23.17" # match Vault prod + kuberconform-version: + description: "Specify the kuberconform version that you want to use." + required: true + default: "v0.6.3" # currently latest + schemas-path: + description: "Specify the path where the schemas are located." + required: true + default: "./helm/k8s-crds-schemas/{{.ResourceKind}}{{.KindSuffix}}.json" + charts-path: + description: "Specify the path where the charts are located." + required: true + default: "./helm/charts/" + +runs: + using: "composite" + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install kubeconform + shell: bash + env: + KUBECONFORM_VERSION: ${{ inputs.kuberconform-version }} + KUBECONFORM_BASE_URL: "https://github.com/yannh/kubeconform/releases/download" + run: | + set -o pipefail + OS=$(uname) + curl -sSfL "${KUBECONFORM_BASE_URL}/${KUBECONFORM_VERSION}/kubeconform-${OS}-amd64.tar.gz" | + tar -xzf - kubeconform + - name: Run kubeconform + shell: bash + env: + KUBERNETES_VERSION: ${{ inputs.kubernetes-version }} + HELM_SCHEMA_LOCATION: ${{ inputs.schema-path }} + HELM_CHART_FOLDER: ${{ charts-path }} + run: | + set -o pipefail + for chart_file in ${HELM_CHART_FOLDER}/*/Chart.yaml; do + echo "Running kubeconform on '${chart_file}'" + chart_dir="$(dirname $chart_file)" + values_file="${chart_dir}/values.yaml" + helm template --kube-version "$KUBERNETES_VERSION" -f "$value_file" "$chart_dir" | + ./kubeconform -strict -exit-on-error -kubernetes-version ${KUBERNETES_VERSION#v}\ + -schema-location "$HELM_SCHEMA_LOCATION" -schema-location default -ignore-missing-schemas + + # below is temporary duplicated code to test Vault Helm value located in another folder + vault_values_dir=$(echo "$chart_dir" | sed "s/charts/values/g") + if [ -d "$vault_values_dir" ]; then + for vault_value_file in ${$vault_values_dir}/*.yaml; do + echo -e "▶ Validating ${chart_file} with values from ${vault_value_file}" + helm template --kube-version "$KUBERNETES_VERSION" -f "$vault_value_file" "$chart_dir" | + ./kubeconform -strict -exit-on-error -kubernetes-version ${KUBERNETES_VERSION#v}\ + -schema-location "$HELM_SCHEMA_LOCATION" -schema-location default -ignore-missing-schemas + done + fi + done diff --git a/helm/lint/action.yml b/helm/lint/action.yml new file mode 100644 index 00000000..073073e8 --- /dev/null +++ b/helm/lint/action.yml @@ -0,0 +1,39 @@ +name: "Run Helm Chart Testing & Docs" +description: "Run Helm Chart Testing & Docs" + +inputs: + chart-testing-config: + description: "Specify the path where the ct.yaml is located." + required: true + default: ".github/ct.yaml" + helm-docs-version: + description: "Specify the helm-docs version that you want to use." + required: true + default: "1.11.0" + +runs: + using: "composite" + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up chart-testing + uses: helm/chart-testing-action@v2.2.0 + + - name: Run chart-testing (lint) + shell: bash + run: ct lint --config ${{ inputs.chart-testing-config }} --check-version-increment=false + + - name: Run helm-docs + shell: bash + env: + HELM_DOCS_VERSION: ${{ inputs.helm-docs-version }} + HELM_DOCS_BASE_URL: "https://github.com/norwoodj/helm-docs/releases/download" + run: | + OS=$(uname) + # install helm-docs + curl -sSfL "${HELM_DOCS_BASE_URL}/v${HELM_DOCS_VERSION}/helm-docs_${HELM_DOCS_VERSION}_${OS}_x86_64.tar.gz" | + tar -xzf - helm-docs + # validate docs + ./helm-docs + git diff --exit-code diff --git a/helm/publish-cm/action.yml b/helm/publish-cm/action.yml new file mode 100644 index 00000000..2d4a4df8 --- /dev/null +++ b/helm/publish-cm/action.yml @@ -0,0 +1,49 @@ +name: "Publish Helm Chart on chart museum" +description: "Publish Helm Chart on chart museum." + +inputs: + version: + description: "Specify the chart version to publish." + required: true + charts-path: + description: "Specify the path where the charts are located." + required: false + default: "./helm/charts/" + chartmuseum-url: + description: "Specify the URL of Chart Museum" + required: true + chartmuseum-user: + description: "Specify the user of Chart Museum" + required: true + chartmuseum-password: + description: "Specify the password of Chart Museum" + required: true + force: + description: "Replace charts if it exists" + required: false + +runs: + using: "composite" + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Add chartmuseum helm repo + shell: bash + run: | + if ! helm plugin list | grep -q "cm-push"; then + helm plugin install https://github.com/chartmuseum/helm-push.git + fi + helm repo add chartmuseum --username ${{ inputs.chartmuseum-user }} --password ${{ inputs.chartmuseum-password }} ${{ inputs.chartmuseum-url }} && + helm repo update + - name: Push chart to chartmuseum repo + shell: bash + env: + HELM_CHART_FOLDER: ${{ inputs.charts-path }} + FORCE_CHART_OVERWRITE: ${{ inputs.force }} + CHART_VERSION: ${{ inputs.version }} + run: | + for chart_file in ${HELM_CHART_FOLDER}/*/Chart.yaml; do + chart_dir=$(dirname "$chart_file") + helm cm-push ${{ "$FORCE_CHART_OVERWRITE" && "-f"}} "$chart_dir" chartmuseum --version "$CHART_VERSION" + done diff --git a/python-app/action.yml b/python-app/action.yml index 6fca449b..8818ed09 100644 --- a/python-app/action.yml +++ b/python-app/action.yml @@ -35,6 +35,12 @@ inputs: required: false default: "" +outputs: + version: + description: "Computed Semantic version." + value: ${{ steps.docker.outputs.version }} + + runs: using: "composite" steps: diff --git a/python-app/docker/action.yml b/python-app/docker/action.yml index f084de9f..34b51932 100644 --- a/python-app/docker/action.yml +++ b/python-app/docker/action.yml @@ -7,6 +7,12 @@ inputs: required: false default: "" +outputs: + version: + description: "Computed Semantic version." + value: ${{ steps.compute-semantic-version.outputs.semver }} + + runs: using: "composite" @@ -20,7 +26,7 @@ runs: - if: ${{ steps.check-docker.outputs.is-docker-needed == 'true' }} name: Clone - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: 0 # needed for VERSION @@ -32,6 +38,19 @@ runs: echo VERSION=$(git describe --tags) >> $GITHUB_ENV shell: bash + - if: ${{ steps.check-docker.outputs.is-docker-needed == 'true' }} + name: Semantic Version preparation + id: compute-semantic-version + env: + REF: ${{ github.event.pull_request && github.head_ref || github.ref_name }} + run: | + if [[ $REF =~ ^[0-9]+\.[0-9]+\.[0-9]+(.*)$ ]]; then + echo "semver=$REF" >> ${GITHUB_OUTPUT} + else + echo "semver=0.0.0-${REF//[\/_]/-}" >> ${GITHUB_OUTPUT} + fi + shell: bash + - if: ${{ steps.check-docker.outputs.is-docker-needed == 'true' }} name: Docker meta id: meta @@ -45,6 +64,7 @@ runs: type=ref,event=branch type=ref,event=tag type=ref,event=pr + type=semver,pattern={{version}},value=${{steps.compute-semantic-version.outputs.semver}} - if: ${{ steps.check-docker.outputs.is-docker-needed == 'true' }} name: Set up QEMU