[bitnami/superset] Add chart #35738
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Copyright Broadcom, Inc. All Rights Reserved. | |
# SPDX-License-Identifier: APACHE-2.0 | |
name: '[CI/CD] CI Pipeline' | |
on: # rebuild any PRs and main branch changes | |
pull_request_target: | |
types: | |
- opened | |
- reopened | |
- synchronize | |
- labeled | |
branches: | |
- main | |
- bitnami:main | |
# Remove all permissions by default | |
permissions: {} | |
# Avoid concurrency over the same PR | |
concurrency: | |
group: ${{ github.workflow }}-${{ github.event.pull_request.number }} | |
jobs: | |
get-chart: | |
runs-on: ubuntu-latest | |
name: Get modified charts | |
permissions: | |
pull-requests: read | |
outputs: | |
chart: ${{ steps.get-chart.outputs.chart }} | |
result: ${{ steps.get-chart.outputs.result }} | |
values-updated: ${{ steps.get-chart.outputs.values-updated }} | |
steps: | |
- id: get-chart | |
name: Get modified charts | |
env: | |
PULL_REQUEST_NUMBER: "${{ github.event.pull_request.number }}" | |
PULL_REQUEST_URL: "${{ github.event.pull_request.url }}" | |
GITHUB_TOKEN: "${{ github.token }}" | |
run: | | |
# Using the Github API to detect the files changed as git merge-base stops working when the branch is behind | |
files_changed_data="$(gh api --paginate /repos/${GITHUB_REPOSITORY}/pulls/${PULL_REQUEST_NUMBER}/files)" | |
files_changed="$(echo "$files_changed_data" | jq -r '.[] | .filename')" | |
# Adding || true to avoid "Process exited with code 1" errors | |
charts_dirs_changed="$(echo "$files_changed" | xargs dirname | grep -o "bitnami/[^/]*" | sort | uniq || true)" | |
# Using grep -c as a better alternative to wc -l when dealing with empty strings." | |
num_charts_changed="$(echo "$charts_dirs_changed" | grep -c "bitnami" || true)" | |
num_version_bumps="$(echo "$files_changed_data" | jq -r '[.[] | select(.filename|endswith("Chart.yaml")) | select(.patch|contains("+version")) ] | length' )" | |
non_readme_files=$(echo "$files_changed" | grep -vc "\.md" || true) | |
if [[ $(curl -Lks "${PULL_REQUEST_URL}" | jq '.state | index("closed")') != *null* ]]; then | |
# The PR for which this workflow run was launched is now closed -> SKIP | |
echo "error=The PR for which this workflow run was launched is now closed. The tests will be skipped." >> $GITHUB_OUTPUT | |
echo "result=skip" >> $GITHUB_OUTPUT | |
elif [[ "$non_readme_files" -le "0" ]]; then | |
# The only changes are .md files -> SKIP | |
echo "result=skip" >> $GITHUB_OUTPUT | |
elif [[ "$num_charts_changed" -ne "$num_version_bumps" ]]; then | |
# Changes done in charts but version not bumped -> ERROR | |
echo "error=Detected changes in charts without version bump in Chart.yaml. Charts changed: ${num_charts_changed}. Version bumps detected: ${num_version_bumps}" >> $GITHUB_OUTPUT | |
echo "result=fail" >> $GITHUB_OUTPUT | |
elif [[ "$num_charts_changed" -eq "1" ]]; then | |
# Changes done in only one chart -> OK | |
echo "result=ok" >> $GITHUB_OUTPUT | |
# Extra output: chart name | |
chart_name=$(echo "$charts_dirs_changed" | sed "s|bitnami/||g") | |
echo "chart=${chart_name}" >> $GITHUB_OUTPUT | |
# Extra output: values-updated | |
if [[ ${files_changed[@]} =~ "bitnami/${chart_name}/values.yaml" ]]; then | |
echo "values-updated=true" >> $GITHUB_OUTPUT | |
fi | |
elif [[ "$num_charts_changed" -le "0" ]]; then | |
# Changes done in the bitnami/ folder but not inside a chart subfolder -> SKIP | |
echo "error=No changes detected in charts. The rest of the tests will be skipped." >> $GITHUB_OUTPUT | |
echo "result=skip" >> $GITHUB_OUTPUT | |
else | |
# Changes done in more than chart -> SKIP | |
echo "error=Changes detected in more than one chart directory. It is strongly advised to change only one chart in a PR. The rest of the tests will be skipped." >> $GITHUB_OUTPUT | |
echo "result=skip" >> $GITHUB_OUTPUT | |
fi | |
# Using actions/github-scripts because using exit 1 in the script above would not provide any output | |
# Source: https://github.community/t/no-output-on-process-completed-with-exit-code-1/123821/3 | |
- id: show-error | |
name: Show error | |
if: ${{ steps.get-chart.outputs.result != 'ok' }} | |
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea | |
with: | |
script: | | |
let message='${{ steps.get-chart.outputs.error }}'; | |
if ('${{ steps.get-chart.outputs.result }}' === 'fail' ) { | |
core.setFailed(message); | |
} else { | |
core.warning(message); | |
} | |
update-pr: | |
runs-on: ubuntu-latest | |
needs: [get-chart] | |
name: Automatically update README, CRDs and CHANGELOG | |
permissions: | |
contents: write | |
outputs: | |
result: ${{ steps.update-pr.outputs.result }} | |
if: needs.get-chart.outputs.result == 'ok' | |
steps: | |
- name: Checkout bitnami/charts | |
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 | |
with: | |
ref: ${{github.event.pull_request.head.ref}} | |
repository: ${{github.event.pull_request.head.repo.full_name}} | |
token: ${{ secrets.BITNAMI_BOT_TOKEN }} | |
path: charts | |
- name: Clone upstream bitnami/charts repository | |
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 | |
with: | |
path: upstream-charts | |
- name: Setup git configuration | |
run: | | |
cd $GITHUB_WORKSPACE/charts | |
git config user.name "Bitnami Containers" | |
git config user.email "[email protected]" | |
# In order to avoid doing a full clone (which would fetch the index branch), we | |
# unshallow the clone only using the main branch. We need to get the tags to | |
# regenerate the changelog too | |
- name: Unshallow main branch and get tags | |
run: | | |
cd $GITHUB_WORKSPACE/upstream-charts | |
git fetch origin main --unshallow | |
git fetch --tags | |
- name: Install conventional-changelog-cli | |
run: npm install -g conventional-changelog-cli | |
- id: generate-changelog | |
name: Generate changelog | |
env: | |
CHART: ${{ needs.get-chart.outputs.chart }} | |
run: | | |
cd $GITHUB_WORKSPACE/upstream-charts | |
# The generator needs the file to exist | |
chart_version="$(yq e '.version' $GITHUB_WORKSPACE/charts/bitnami/${CHART}/Chart.yaml)" | |
changelog_file="$GITHUB_WORKSPACE/charts/bitnami/${CHART}/CHANGELOG.md" | |
changelog_tmp="$GITHUB_WORKSPACE/charts/bitnami/${CHART}/CHANGELOG.md.tmp" | |
touch "$changelog_file" | |
npx conventional-changelog-cli -i ${changelog_file} -s -t ${CHART}/ -r 0 --commit-path bitnami/${CHART} | |
# The tool uses short sha to generate commit links. Sometimes, Github does not offer links with the short sha, so we change all commit links to use the full sha instead | |
for short_sha in $(grep -Eo "/commit/[a-z0-9]+" ${changelog_file} | awk -F/ '{print $3}'); do | |
long_sha="$(git rev-list @ | grep "^$short_sha" | head -n 1)"; | |
sed -i "s%/commit/$short_sha%/commit/$long_sha%g" ${changelog_file}; | |
done | |
cd $GITHUB_WORKSPACE/charts | |
# Remove unreleased section (includes all intermediate commits in the branch) and create future entry based on PR title | |
# The unreleased section looks like this "## (YYYY-MM-DD)" whereas a released section looks like this "## 0.0.1 (YYYY-MM-DD)" | |
# So we only need to find a released section to start printing in the awk script below | |
awk '/^##[^(]*[0-9]/ {flag=1} flag {print}' ${changelog_file} > ${changelog_tmp} | |
# Remove extra newlines so the changelog file passes the markdown linter | |
sed -i -E -e '/^$/d' ${changelog_tmp} && sed -i -E -e 's/(##.*)/\n\1\n/g' ${changelog_tmp} | |
# Include h1 heading and add entry for the current version. There is no tag for the current version (this will be created once merged), so we need to manually add it. | |
# We know the final squashed commit title, which will be the PR title. We cannot add a link to the commit in the main branch because it has not been | |
# merged yet (this will be corrected once a new version regenerates the changelog). Instead, we add the PR url which contains the exact same information. | |
echo -e -n "# Changelog\n\n## $chart_version ($(date +'%Y-%m-%d'))\n\n* ${{ github.event.pull_request.title }} ([#${{ github.event.number }}](${{ github.server_url }}/${{ github.repository }}/pull/${{ github.event.number }}))\n" > ${changelog_file} | |
cat ${changelog_tmp} >> ${changelog_file} | |
rm ${changelog_tmp} | |
if git status -s | grep "bitnami/${CHART}/CHANGELOG.md"; then | |
git add "bitnami/${CHART}/CHANGELOG.md" && git commit -m "Update CHANGELOG.md" --signoff | |
fi | |
- name: Install readme-generator-for-helm | |
if: needs.get-chart.outputs.values-updated == 'true' | |
run: npm install -g @bitnami/readme-generator-for-helm | |
- id: update-readme | |
name: 'Update README' | |
if: needs.get-chart.outputs.values-updated == 'true' | |
env: | |
CHART: ${{ needs.get-chart.outputs.chart }} | |
run: | | |
exit_code=0 | |
cd $GITHUB_WORKSPACE/charts | |
echo "Validating README.md for bitnami/${CHART}" | |
# Validating *.registry parameters | |
while read line; do | |
echo "$line" | grep --quiet "\[default: \(REGISTRY_NAME\|\"\"\)\]" || exit_code=$? | |
done < <(grep "@param\s\+[A-Za-z\.]\+\.registry\s\+" "bitnami/${CHART}/values.yaml") | |
if [[ $exit_code -ne 0 ]]; then | |
echo "error=Please ensure all *.registry params include the [default: REGISTRY_NAME] modifier in the chart bitnami/${CHART}/values.yaml file" | |
exit "$exit_code" | |
fi | |
# Validating *.repository parameters | |
while read line; do | |
param=$(echo "$line" | awk '{print $3}') | |
# Checking if it's a image's registry-related param | |
registry_param=$(echo ${param} | sed 's/\.repository/\.registry/g') | |
grep --quiet "@param\s\+${registry_param}" "bitnami/${CHART}/values.yaml" && ( echo "$line" | grep --quiet "\[default: \(REPOSITORY_NAME/.*\|\"\"\)\]" || exit_code=$? ) | |
done < <(grep "@param\s\+[A-Za-z\.]\+\.repository\s\+" "bitnami/${CHART}/values.yaml") | |
if [[ $exit_code -ne 0 ]]; then | |
echo "error=Please ensure all *.repository params include the [default: REPOSITORY_NAME] modifier the in the chart bitnami/${CHART}/values.yaml file" | |
exit "$exit_code" | |
fi | |
# Validating *.tag parameters | |
! grep --quiet "@param\s\+[A-Za-z\.]\+\.tag\s\+" "bitnami/${CHART}/values.yaml" || exit_code=$? | |
if [[ $exit_code -ne 0 ]]; then | |
echo "error=Please ensure all *.tag params are skipped (@skip) in the bitnami/${CHART}/values.yaml file" | |
exit "$exit_code" | |
fi | |
echo "Updating README.md for bitnami/${CHART}" | |
readme-generator --values "bitnami/${CHART}/values.yaml" --readme "bitnami/${CHART}/README.md" --schema "/tmp/schema.json" | |
# Commit all changes, if any | |
if git status -s | grep "bitnami/${CHART}"; then | |
git add "bitnami/${CHART}" && git commit -m "Update README.md with readme-generator-for-helm" --signoff | |
fi | |
- id: update-crds | |
name: 'Update CRDs' | |
# To avoid malicious executions, only PRs performed by the bitnami-bot will perform the CRDs update | |
if: github.event.pull_request.user.login == 'bitnami-bot' | |
env: | |
CHART: ${{ needs.get-chart.outputs.chart }} | |
run: | | |
# Updating CRDs stored at 'bitnami/$CHART/crds' and 'bitnami/$CHART/templates/crds' | |
cd $GITHUB_WORKSPACE/charts | |
mapfile -t crd_files < <(find "bitnami/${CHART}/crds" "bitnami/${CHART}/templates/crds" -name "*.yaml" -o -name "*.yml" 2>/dev/null || true) | |
for file in "${crd_files[@]}"; do | |
# Automatically update CRDs that use the '# Source' header | |
source_url_tpl="$(head -n 1 $file | grep -E "^# ?Source: ?" | sed -E 's|^# ?Source: ?||' || true)" | |
if [[ -n "$source_url_tpl" ]]; then | |
# Validate the second line of the CRD file includes the version of the CRD | |
crd_version="$(head -n 2 $file | tail -n 1 | grep -E "^# ?Version: ?" | sed -E 's|^# ?Version: ?||' || true)" | |
if [[ -z "$crd_version" ]]; then | |
echo "error=CRD file '${file}' does not include the '#Version: <version> header'" | |
exit 1 | |
fi | |
# Additional headers may be used for extra features | |
# Conditional - Adds a conditional {{if}}/{{end}} to the downloaded upstream CRD | |
# VersionOf - Name of a subcomponent, its version will be used for CRD tracking instead of the main component version | |
# UseKustomize - If set to true, uses Kustomize to render the CRDs | |
# RequiresFilter - If set to true, uses yq to filter resources having 'kind: CustomResourceDefinition', useful when using 'install.yaml' file as upstream source | |
continue=true | |
line_n=2 | |
extra_headers="" | |
CONDITIONAL="" | |
SUBCOMPONENT="" | |
USE_KUSTOMIZE="" | |
REQUIRES_FILTER="" | |
while [ "$continue" = true ]; do | |
line_n=$((line_n+1)) | |
line="$(head -n $line_n $file | tail -n 1)" | |
if [[ $line =~ ^#\ ?[a-zA-Z]+:\ ? ]]; then | |
if [[ $line =~ ^#\ ?Conditional:\ ? ]]; then | |
CONDITIONAL="$(echo $line | sed -E 's|^# ?Conditional: ?||')" | |
CONDITIONAL="{{- if ${CONDITIONAL} }}\n" | |
elif [[ $line =~ ^#\ ?VersionOf:\ ? ]]; then | |
SUBCOMPONENT="$(echo $line | sed -E 's|^# ?VersionOf: ?||')" | |
elif [[ $line =~ ^#\ ?UseKustomize:\ ? ]]; then | |
USE_KUSTOMIZE="$(echo $line | sed -E 's|^# ?UseKustomize: ?||' || true)" | |
elif [[ $line =~ ^#\ ?RequiresFilter:\ ? ]]; then | |
REQUIRES_FILTER="$(echo $line | sed -E 's|^# ?RequiresFilter: ?||' || true)" | |
else | |
echo "error=Header ${line} not recognized'" | |
exit 1 | |
fi | |
extra_headers="${extra_headers}${line}\n" | |
else | |
continue=false | |
fi | |
done | |
# Obtain the version of the subcomponent if provided, otherwise use the main component version | |
if [[ -n "$SUBCOMPONENT" ]]; then | |
APP_VERSION="$(cat bitnami/${CHART}/Chart.yaml | grep -E "image: \S+${SUBCOMPONENT}:" | sed -E "s|.*${SUBCOMPONENT}:([0-9\.]+)-.*|\1|")" | |
else | |
APP_VERSION="$(yq e '.appVersion' bitnami/${CHART}/Chart.yaml)" | |
fi | |
# Replace version placeholder, if present | |
source_url=$(echo "$source_url_tpl" | sed "s/{version}/${APP_VERSION}/") | |
# If the application version is newer, automatically update the CRD file | |
if [[ "$APP_VERSION" != "$crd_version" || "$skip_version" = true ]]; then | |
if [[ "$USE_KUSTOMIZE" = "true" ]]; then | |
kubectl kustomize "$source_url" > $file | |
else | |
curl -Lks --fail -o $file "$source_url" | |
fi | |
if [[ "$REQUIRES_FILTER" = "true" ]]; then | |
yq -i e '. | select(.kind == "CustomResourceDefinition") | ... head_comment=""' $file | |
fi | |
sed -i "1s|^|# Source: ${source_url_tpl}\n# Version: ${APP_VERSION}\n${extra_headers}${CONDITIONAL}|" $file | |
if [[ -n "$CONDITIONAL" ]]; then | |
echo -E "{{- end }}" >> $file | |
fi | |
echo "info=CRD file '${file}' automatically updated using source '$source_url'" | |
fi | |
else | |
echo "info=CRD file '$file' does not contain the '#Source' header. Skipping..." | |
fi | |
done | |
# Commit all changes, if any | |
if git status -s | grep "bitnami/${CHART}"; then | |
git add "bitnami/${CHART}" && git commit -m "Update CRDs automatically" --signoff | |
fi | |
- id: update-pr | |
name: Push changes | |
run: | | |
cd $GITHUB_WORKSPACE/charts | |
# Push all the new commits, if any | |
if [[ $(git cherry -v) ]]; then | |
git push | |
echo "result=ok" >> $GITHUB_OUTPUT | |
else | |
echo "result=skip" >> $GITHUB_OUTPUT | |
fi | |
vib-verify: | |
runs-on: ubuntu-latest | |
needs: [get-chart, update-pr] | |
permissions: | |
contents: read | |
# Given performance issues of the action feature on GH's side, we need to be very restrictive in the job's triggers: | |
# -> The 'Get modified charts' job suceededs AND | |
# -> The 'Update PR' job did not push any new changes AND | |
# ( ---> The pipeline was triggered due to a label addition and said label was the 'verify' one OR | |
# ---> the PR already contains the 'verify' label ) | |
if: | | |
needs.get-chart.outputs.result == 'ok' && | |
needs.update-pr.outputs.result == 'skip' && | |
( | |
contains(github.event.pull_request.labels.*.name, 'verify') || (github.event.action == 'labeled' && github.event.label.name == 'verify') | |
) | |
name: VIB Verify | |
steps: | |
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 | |
name: Checkout Repository | |
with: | |
ref: ${{ github.event.pull_request.head.ref }} | |
repository: ${{ github.event.pull_request.head.repo.full_name }} | |
- id: log-chart-info | |
name: Get chart version and app version | |
env: | |
CHART: ${{ needs.get-chart.outputs.chart }} | |
run: | | |
# Log chart info | |
chart_version="$(yq e '.version' bitnami/${CHART}/Chart.yaml)" | |
app_version="$(yq e '.appVersion' bitnami/${CHART}/Chart.yaml)" | |
echo "Chart: ${CHART} ChartVersion: ${chart_version} AppVersion: ${app_version}" | |
- id: get-asset-vib-config | |
name: Get asset-specific configuration for VIB action | |
run: | | |
config_file=".vib/${{ needs.get-chart.outputs.chart }}/vib-action.config" | |
# Supported configuration customizations and default values | |
verification_mode="PARALLEL" | |
if [[ -f $config_file ]]; then | |
verification_mode="$(cat $config_file | grep 'verification-mode' | cut -d'=' -f2)" | |
fi | |
runtime_parameters_file="" | |
if [[ -f ".vib/${{ needs.get-chart.outputs.chart }}/runtime-parameters.yaml" ]]; then | |
# The path is relative to the .vib folder | |
runtime_parameters_file="${{ needs.get-chart.outputs.chart }}/runtime-parameters.yaml" | |
fi | |
echo "verification_mode=${verification_mode}" >> $GITHUB_OUTPUT | |
echo "runtime_parameters_file=${runtime_parameters_file}" >> $GITHUB_OUTPUT | |
- uses: vmware-labs/vmware-image-builder-action@v0 | |
name: Verify ${{ needs.get-chart.outputs.chart }} | |
with: | |
pipeline: ${{ needs.get-chart.outputs.chart }}/vib-verify.json | |
verification-mode: ${{ steps.get-asset-vib-config.outputs.verification_mode }} | |
runtime-parameters-file: ${{ steps.get-asset-vib-config.outputs.runtime_parameters_file }} | |
env: | |
CSP_API_URL: https://console.cloud.vmware.com | |
CSP_API_TOKEN: ${{ secrets.CSP_API_TOKEN }} | |
VIB_PUBLIC_URL: https://cp.bromelia.vmware.com | |
# Target-Platform used by default | |
VIB_ENV_TARGET_PLATFORM: ${{ secrets.VIB_ENV_TARGET_PLATFORM }} | |
# Alternative Target-Platform to be used in case of incompatibilities | |
VIB_ENV_ALTERNATIVE_TARGET_PLATFORM: ${{ secrets.VIB_ENV_ALTERNATIVE_TARGET_PLATFORM }} | |
auto-pr-review: | |
runs-on: ubuntu-latest | |
needs: vib-verify | |
name: Reviewal for automated PRs | |
permissions: | |
pull-requests: write | |
# Job to be run only when the triage for automated PRs did as well, | |
# not taking into account whether 'VIB Verify' succeeded | |
if: | | |
always() && | |
contains(github.event.pull_request.labels.*.name, 'auto-merge') && | |
github.event.pull_request.user.login == 'bitnami-bot' | |
steps: | |
# Approve the CI's PR if the 'VIB Verify' job succeeded | |
# Approved by the 'github-actions' user; a PR can't be approved by its author | |
- name: PR approval | |
if: ${{ needs.vib-verify.result == 'success' }} | |
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea | |
with: | |
result-encoding: string | |
retries: 3 | |
script: | | |
github.rest.pulls.createReview({ | |
owner: context.repo.owner, | |
repo: context.repo.repo, | |
pull_number: context.issue.number, | |
event: 'APPROVE', | |
}); | |
- name: Merge | |
id: merge | |
if: ${{ needs.vib-verify.result == 'success' }} | |
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea | |
with: | |
result-encoding: string | |
retries: 3 | |
github-token: ${{ secrets.BITNAMI_BOT_TOKEN }} | |
script: | | |
github.rest.pulls.merge({ | |
pull_number: context.issue.number, | |
owner: context.repo.owner, | |
repo: context.repo.repo, | |
merge_method: 'squash' | |
}) | |
# If the CI did not succeed ('VIB Verify' failed or skipped), | |
# post a comment on the PR and assign a maintainer agent to review it | |
- name: Manual review required | |
if: ${{ always() && (needs.vib-verify.result != 'success' || steps.merge.outcome != 'success' ) }} | |
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea | |
env: | |
BODY: | | |
There has been an error during the automated release process. Manual revision is now required. | |
Please check the related [action_run#${{ github.run_id }}](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}) for more information. | |
with: | |
retries: 3 | |
# Necessary to trigger support workflows | |
github-token: ${{ secrets.BITNAMI_BOT_TOKEN }} | |
script: | | |
const {BODY} = process.env | |
github.rest.issues.createComment({ | |
issue_number: context.issue.number, | |
owner: context.repo.owner, | |
repo: context.repo.repo, | |
body: `${BODY}` | |
}) |