Skip to content

Commit

Permalink
Merge pull request #25 from mozilla-it/add-render-and-diff-helm
Browse files Browse the repository at this point in the history
feat: add render and diff helm action
  • Loading branch information
dlactin authored Mar 6, 2024
2 parents 1f0e019 + 31a3aa4 commit 82f39e5
Show file tree
Hide file tree
Showing 2 changed files with 208 additions and 0 deletions.
29 changes: 29 additions & 0 deletions render-and-diff-helm/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Render and diff helm charts

This action is used to render helm charts on the base and ref branches of a pull request, create a diff between charts that have been modified and then post the diff as a comment on the pull request.

## Inputs

### `chart_path`

The path filter for helm charts in the repository. Default `'**/k8s/**/**'`

### Example usage
```
name: render-and-diff-charts
on:
pull_request:
paths:
- '**/k8s/**/**'
jobs:
run_helm_chart_diff:
permissions:
contents: read
pull-requests: write
runs-on: ubuntu-latest
steps:
- name: Render and diff modified helm charts
uses: mozilla-it/deploy-actions/[email protected]
```
179 changes: 179 additions & 0 deletions render-and-diff-helm/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at https://mozilla.org/MPL/2.0/.

name: Matrix render and diff helm charts
description: Renders BASE and REF helm charts then posts the diff of the rendered charts as a comment on the pull request


on:
workflow_call:
inputs:
chart_path:
description: Path filter for helm charts
required: false
type: string
default: '**/k8s/**'

env:
CHART_PATH: ${{ inputs.chart_path }}

jobs:
get_changed_helm_charts:
runs-on: ubuntu-latest
outputs:
matrix_charts: ${{ steps.find_changed_charts.outputs.matrix_changed_charts }}
charts: ${{ steps.find_changed_charts.outputs.changed_charts }}
steps:
- name: checkout repository
uses: actions/checkout@v4
with:
fetch-depth: '100'

- name: find changed helm charts
id: find_changed_charts
run: |
git fetch origin ${{ github.base_ref }}:${{ github.base_ref }}
echo matrix_changed_charts=$(git diff --name-only ${{ github.base_ref }}...HEAD -- '**/k8s/**/*.yaml' '**/k8s/**/*.yml' '**/k8s/**/*.tpl' '**/k8s/**/*.tmpl' | cut -d'/' -f1,2,3 | uniq | jq -R 'split("\n")' | jq -s 'flatten(1)') >> $GITHUB_OUTPUT
echo changed_charts=$(git diff --name-only ${{ github.base_ref }}...HEAD -- '**/k8s/**/*.yaml' '**/k8s/**/*.yml' '**/k8s/**/*.tpl' '**/k8s/**/*.tmpl' | cut -d'/' -f1,2,3 | uniq) >> $GITHUB_OUTPUT
render_head_ref_charts:
runs-on: ubuntu-latest
needs: get_changed_helm_charts
strategy:
matrix:
chart: ${{ fromJSON(needs.get_changed_helm_charts.outputs.matrix_charts) }}
steps:
- name: checkout repository
uses: actions/checkout@v4

- name: setup helm
uses: azure/[email protected]

- name: render ${{ matrix.chart }} from head ref
id: render_head
run: |
mkdir -p shared/head-charts
git fetch origin ${{ github.head_ref }}
git checkout ${{ github.head_ref }} --
if [ -d "${{ matrix.chart }}" ]; then
helm dependency build "${{ matrix.chart }}"
values_files="${{ matrix.chart }}"/values-*
for values_file in $(basename -a $values_files); do
helm template "${{ matrix.chart }}" -f "${{ matrix.chart }}/values.yaml" -f "${{ matrix.chart }}/${values_file}" --output-dir "shared/head-charts/${{ matrix.chart }}/${values_file}"
done
fi
echo sanitized_name=$(echo "${{ matrix.chart }}" | sed 's/\//-/g') >> $GITHUB_OUTPUT
- name: upload artifact
uses: actions/upload-artifact@v4
with:
name: "shared-head-${{ steps.render_head.outputs.sanitized_name }}"
path: "shared"

render_base_ref_charts:
runs-on: ubuntu-latest
needs: get_changed_helm_charts
strategy:
matrix:
chart: ${{ fromJSON(needs.get_changed_helm_charts.outputs.matrix_charts) }}
steps:
- name: checkout repository
uses: actions/checkout@v4

- name: setup helm
uses: azure/[email protected]

- name: render ${{ matrix.chart }} from base ref
id: render_base
run: |
mkdir -p shared/base-charts
git fetch origin ${{ github.base_ref }}
git checkout ${{ github.base_ref }} --
if [ -d "${{ matrix.chart }}" ]; then
helm dependency build "${{ matrix.chart }}"
values_files="${{ matrix.chart }}"/values-*
for values_file in $(basename -a $values_files); do
helm template "${{ matrix.chart }}" -f "${{ matrix.chart }}/values.yaml" -f "${{ matrix.chart }}/${values_file}" --output-dir "shared/base-charts/${{ matrix.chart }}/${values_file}"
done
fi
echo sanitized_name=$(echo "${{ matrix.chart }}" | sed 's/\//-/g') >> $GITHUB_OUTPUT
- name: upload artifact
uses: actions/upload-artifact@v4
with:
name: "shared-base-${{ steps.render_base.outputs.sanitized_name }}"
path: "shared"

diff_helm_charts:
runs-on: ubuntu-latest
needs:
- get_changed_helm_charts
- render_base_ref_charts
- render_head_ref_charts
steps:
- name: setup helm
uses: azure/[email protected]

- name: download artifacts
uses: actions/download-artifact@v4
with:
pattern: shared-*
merge-multiple: true
path: "shared"

- name: diff helm charts
id: diff_helm_charts
run: |
for chart in ${{ needs.get_changed_helm_charts.outputs.charts }}; do
chart_diff_output=$(diff -r "shared/base-charts/${chart}" "shared/head-charts/${chart}" || true)
if [ -n "$chart_diff_output" ]; then
echo -e "Changes found in chart: ${chart}\n$(diff -ru shared/base-charts/${chart} shared/head-charts/${chart})\n" >> diff.log
fi
done
- name: post diff as comment on pull request
if: needs.get_changed_helm_charts.outputs.charts != ''
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const comment_char_limit = 65536; // GitHub comment character limit
const diff = fs.readFileSync('diff.log', 'utf8');
function splitComment(comment, maxSize, sepEnd, sepStart, comStart) {
// Adapted from Atlantis SplitComment function
// https://github.com/runatlantis/atlantis/blob/main/server/events/vcs/common/common.go#L18
if (comment.length <= (comment_char_limit - comStart.length)) {
return [comStart + diff]
}
maxWithSep = comment_char_limit - sepEnd.length - sepStart.length;
var comments = [];
var numComments = Math.ceil(comment.length / maxWithSep);
for (var i = 0; i < numComments; i++) {
var upTo = Math.min(comment.length, (i + 1) * maxWithSep);
var portion = comment.slice(i * maxWithSep, upTo);
if (i < numComments - 1) {
portion += sepEnd;
}
if (i > 0) {
portion = sepStart + portion
} else {
portion = comStart + portion
}
comments.push(portion);
}
return comments;
}
var sepEnd = "\n```\n</details>" + "\n<br>\n\n**Warning**: Output length greater than max comment size. Continued in next comment.";
var sepStart = "Continued from previous comment.\n<details><summary>Show Output</summary>\n\n" + "```diff\n";
var comStart = "Changes found in Helm charts.\n<details><summary>Show Output</summary>\n\n" + "```diff\n";
comments = splitComment(diff, comment_char_limit, sepEnd, sepStart, comStart);
for (const comment of comments) {
await github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: comment
})
}

0 comments on commit 82f39e5

Please sign in to comment.