feat(analytics): add new granularities with support for FF [MA-2149] #9982
Workflow file for this run
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
name: CI | |
on: | |
push: | |
branches: | |
- main | |
pull_request: | |
types: | |
- opened | |
- synchronize | |
- reopened | |
- labeled | |
branches: | |
- main | |
concurrency: | |
group: ${{ github.ref }}-${{ github.workflow }} | |
cancel-in-progress: ${{ github.event_name == 'pull_request' }} | |
jobs: | |
build: | |
name: Build And Test | |
runs-on: ubuntu-latest | |
timeout-minutes: 20 | |
outputs: | |
filter: ${{steps.changed_packages.outputs.filter}} | |
unitTestFilter: ${{steps.changed_packages.outputs.unitTestFilter}} | |
unitTestMatrix: ${{steps.changed_packages.outputs.unitTestMatrix}} | |
componentTestFilter: ${{steps.changed_packages.outputs.componentTestFilter}} | |
componentTestMatrix: ${{steps.changed_packages.outputs.componentTestMatrix}} | |
env: | |
GH_TOKEN: ${{ secrets.KONGPONENTS_BOT_PAT }} | |
steps: | |
# if previous run did create comment with the reference to PR preview package | |
# this comment is removed in this step | |
- name: Remove preview consumption comment | |
if: ${{ env.GH_TOKEN != '' }} | |
uses: marocchino/sticky-pull-request-comment@v2 | |
with: | |
header: pr_preview_consumption | |
delete: true | |
GITHUB_TOKEN: ${{ env.GH_TOKEN }} | |
- name: Checkout Source Code | |
uses: actions/checkout@v4 | |
with: | |
fetch-depth: 0 | |
# When running on push, we compare the state of PR and main branches. If they are | |
# identical - we will skip test execution as those were already executed on same code in PR branch | |
# see 'run-test' step and variable bellow | |
- name: Check if PR Up to Date | |
id: 'up-to-date' | |
if: ${{ github.event_name == 'push' }} | |
uses: Kong/public-shared-actions/pr-previews/up-to-date@main | |
with: | |
github_token: ${{ env.GH_TOKEN }} | |
- name: Setup PNPM with Dependencies | |
uses: ./.github/actions/setup-pnpm-with-dependencies/ | |
with: | |
force-install: true | |
# see the comment for `up-to-date` action | |
- name: Need to run tests | |
id: 'run-tests' | |
run: | | |
echo "run-tests=${{ (github.event_name == 'push' && steps.up-to-date.outputs.status == 'true') && 'false' || 'true' }}" | |
echo "run-tests=${{ (github.event_name == 'push' && steps.up-to-date.outputs.status == 'true') && 'false' || 'true' }}" >> $GITHUB_OUTPUT | |
# If we detect changes in any of the config files (e.g. lockfile, shared cypress configs, etc.), we need to build every package | |
# See 'changed_packages' below | |
- name: Check for config file changes | |
id: config-files-changed | |
uses: tj-actions/changed-files@v44 | |
with: | |
files: | | |
./vite.config.shared.ts | |
./cypress.config.ts | |
./cypress/** | |
./pnpm-lock.yaml | |
./eslintrc.cjs | |
./.stylelintrc.js | |
- name: Verify no packages are in the wrong scope and have the correct publishConfig.access | |
run: | | |
# Verify no packages are in the wrong scope and have the correct publishConfig.access | |
# Utilize the lerna command to determine the packages that were added/updated | |
# we execute lerna changed to grab all the packages changed | |
lernaCommand="changed" | |
# if config-files-changed detects the change of pnpm-lock.yaml file - we will grab all the packages | |
if [[ "${{ steps.config-files-changed.outputs.any_modified }}" == "true" ]]; then | |
lernaCommand="ls" | |
fi | |
echo "lernaCommand: ${lernaCommand}" | |
# Verify no packages exist from the `@kong-ui` scope; if yes, then exit with error | |
for packageLocation in $(pnpm --silent lerna ${lernaCommand} --l --json | jq -r '.[].location') | |
do | |
packageName=$(jq -r '.name' "$packageLocation"/package.json) | |
publishConfigAccess=$(jq -r '.publishConfig.access' "$packageLocation"/package.json) | |
# Check if package.json name contains the wrong scope | |
if [[ "$packageName" == *"@kong-ui/"* ]]; then | |
echo "::error::The '""$packageName""' package.json contains an incorrect npm scope '""@kong-ui""'. This repository requires packages to have the npm scope of '""@kong-ui-public""'." | |
exit 1 | |
fi | |
# Check if the package.json publishConfig.access is incorrect for this repo | |
if [[ "$publishConfigAccess" != "public" ]]; then | |
echo "::error::The '""$packageName""' package.json contains the publishConfig.access of '""$publishConfigAccess""'. This repository requires packages to have a publishConfig.access of '""public""'." | |
exit 1 | |
fi | |
done | |
- name: Getting changed packages | |
id: changed_packages | |
run: | | |
# we execute lerna changed to grab all the packages changed | |
lernaCommand="changed" | |
# if config-files-changed detects the change of pnpm-lock.yaml file - we will grab all the packages | |
if [[ "${{ steps.config-files-changed.outputs.any_modified }}" == "true" ]]; then | |
lernaCommand="ls" | |
fi | |
echo "lernaCommand: ${lernaCommand}" | |
filter="" | |
unitTestFilter="" | |
unitTestMatrix="" | |
componentTestFilter="" | |
componentTestMatrix="" | |
# get the list of changed packages, grab the location | |
for pkgFolder in $(pnpm --silent lerna ${lernaCommand} --l --json|jq -r '.[].location') | |
do | |
# remove current folder from the location path | |
pkgFolder="${pkgFolder/$(pwd)\//}" | |
# add package path to pnpm filter | |
filter="${filter}${pkgFolder}|" | |
# if there is cypress tests in the package, add package path to cypress spec | |
findRes=$(find "${pkgFolder}" -name "*.cy.ts" || true) | |
if [[ -n "${findRes}" ]]; then | |
componentTestFilter="${componentTestFilter}${pkgFolder}," | |
componentTestMatrix="${componentTestMatrix}\"${pkgFolder}\"," | |
fi | |
# we will keep the list of packages that do require unit tests based on the fact that we | |
# detecting UT files | |
findRes=$(find "${pkgFolder}" -name "*.spec.ts" || true) | |
if [[ -n "${findRes}" ]]; then | |
unitTestFilter="${unitTestFilter}${pkgFolder}|" | |
fi | |
done | |
# remove trailing '|' from pnpm filter | |
filter="{("$(echo "${filter}" | sed 's/|$//')")}" | |
if [[ "${filter}" == "{()}" ]]; then | |
filter="" | |
fi | |
echo "filter=${filter}" | |
unitTestFilter="{("$(echo "${unitTestFilter}" | sed 's/|$//')")}" | |
if [[ "${{steps.run-tests.outputs.run-tests}}" != "true" || "${unitTestFilter}" == "{()}" ]]; then | |
unitTestFilter="" | |
fi | |
echo "unitTestFilter=${unitTestFilter}" | |
unitTestMatrix=$(echo "${unitTestFilter}"| sed 's/{(/\[\"/'| sed 's/)}/\"\]'/|sed 's/|/\"\,\"/g'| sed 's/packages\///g') | |
echo "unitTestMatrix=${unitTestMatrix}" | |
# remove trailing ',' from cypress spec filter | |
componentTestFilter=$(echo "${componentTestFilter}" | sed 's/,$//') | |
if [[ "${{steps.run-tests.outputs.run-tests}}" != "true" ]]; then | |
componentTestFilter="" | |
fi | |
echo "componentTestFilter=${componentTestFilter}" | |
# remove trailing ',' from cypress spec matrix | |
componentTestMatrix="[$(echo "${componentTestMatrix}" | sed 's/,$//')]" | |
if [[ "${{steps.run-tests.outputs.run-tests}}" != "true" || "${componentTestFilter}" == "" ]]; then | |
componentTestMatrix="" | |
fi | |
echo "componentTestMatrix=${componentTestMatrix}" | |
# this is to pass to `pnpm --filter` to run pnpm command on all changed packages | |
echo "filter=${filter}" >> $GITHUB_OUTPUT | |
# this is changed packages that do have unit tests - to be passed to `pnpm test:unit` | |
echo "unitTestFilter=${unitTestFilter}" >> $GITHUB_OUTPUT | |
# this is unit tests in the format json.parse understands | |
echo "unitTestMatrix=${unitTestMatrix}" >> $GITHUB_OUTPUT | |
# this is changed packages that do have component tests - to be passed to `pnpm test:component` | |
echo "unitTestFilter=${unitTestFilter}" >> $GITHUB_OUTPUT | |
# this is component tests in the format json.parse understands | |
echo "componentTestMatrix=${componentTestMatrix}" >> $GITHUB_OUTPUT | |
- name: Stylelint Packages | |
if: ${{ steps.changed_packages.outputs.filter != '' }} | |
run: pnpm --parallel --stream --filter "${{steps.changed_packages.outputs.filter}}" run stylelint | |
- name: Lint Packages | |
if: ${{ steps.changed_packages.outputs.filter != '' }} | |
run: pnpm --parallel --stream --filter "${{steps.changed_packages.outputs.filter}}" run lint | |
- name: Build Packages | |
if: ${{ steps.changed_packages.outputs.filter != '' }} | |
# The `...` syntax tells pnpm to include dependent packages | |
run: pnpm --stream --filter "...${{steps.changed_packages.outputs.filter}}..." run build | |
- name: Check dist bundle size against max-limit | |
uses: Kong/github-action-dist-size-checker@main | |
- name: Publish Previews | |
if: ${{ github.event_name == 'pull_request' && steps.changed_packages.outputs.filter != '' && (github.actor != 'renovate[bot]' || contains(github.event.pull_request.labels.*.name, 'create preview package')) && env.GH_TOKEN != '' }} | |
run: | | |
git config user.email "[email protected]" | |
git config user.name "Kong UI Bot" | |
preid="pr.${{ github.event.pull_request.number }}.$(git rev-parse --short ${{ github.event.pull_request.head.sha }})" | |
tag="pr-${{ github.event.pull_request.number }}" | |
echo "preid=${preid}" | |
git checkout ${{ github.head_ref }} | |
pnpm --silent lerna version prerelease --preid ${preid} --allow-branch ${{ github.head_ref }} --conventional-prerelease --yes --amend || true | |
echo "//registry.npmjs.org/:_authToken=${NODE_AUTH_TOKEN}" > .npmrc | |
pnpmPublish=$(pnpm --stream --filter "${{steps.changed_packages.outputs.filter}}" publish --no-git-checks --access public --report-summary --tag "${tag}") | |
if [[ ! -z $(echo "${pnpmPublish}"|grep "There are no new packages that should be published") ]]; then | |
echo "There are no new packages that should be published" | |
exit 0 | |
fi | |
npm_instructions="" | |
for pkg in $(echo "${pnpmPublish}" | grep "+ "| sed 's/+ //') | |
do | |
pkg="@$(echo ${pkg}|cut -d'@' -f2)@${tag}" | |
if [ "${npm_instructions}" != "" ]; then | |
npm_instructions="${npm_instructions}\n" | |
fi | |
npm_instructions="${npm_instructions}${pkg}" | |
done | |
if [[ -z "${npm_instructions}" ]]; then | |
echo "Error creating preview instructions" | |
exit -1 | |
fi | |
echo "npm_instructions<<EOF" >> $GITHUB_ENV | |
echo -e "$npm_instructions" >> $GITHUB_ENV | |
echo "EOF" >> $GITHUB_ENV | |
env: | |
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN_PUBLIC_PUBLISH }} | |
- name: Provide preview link info | |
if: ${{ env.npm_instructions != '' && env.GH_TOKEN != '' }} | |
uses: marocchino/sticky-pull-request-comment@v2 | |
with: | |
header: pr_preview_consumption | |
message: | | |
## ***Preview*** components from this PR in consuming application | |
In consuming application project install preview versions of shared packages generated by this PR: | |
``` | |
${{env.npm_instructions}} | |
``` | |
GITHUB_TOKEN: ${{ env.GH_TOKEN }} | |
- name: Run Unit Tests | |
if: ${{ steps.changed_packages.outputs.unitTestFilter != '' }} | |
run: pnpm --parallel --stream --filter "${{steps.changed_packages.outputs.unitTestFilter}}" run test:unit | |
- name: Save Build Artifacts | |
if: ${{ steps.changed_packages.outputs.filter != '' }} | |
uses: actions/upload-artifact@v4 | |
with: | |
name: package-dist-artifacts | |
path: packages/*/*/dist | |
component-tests: | |
name: Component tests | |
needs: [build] | |
runs-on: ubuntu-latest | |
if: ${{ needs.build.outputs.componentTestMatrix != ''}} | |
timeout-minutes: 20 | |
continue-on-error: false | |
strategy: | |
fail-fast: false | |
matrix: | |
container: ${{ fromJSON(needs.build.outputs.componentTestMatrix) }} | |
steps: | |
- name: Checkout Source Code | |
uses: actions/checkout@v4 | |
- name: Setup PNPM with Dependencies | |
uses: ./.github/actions/setup-pnpm-with-dependencies/ | |
- name: Prepare Cypress | |
run: pnpm cypress install | |
- name: Download build artifacts | |
uses: actions/download-artifact@v4 | |
with: | |
name: package-dist-artifacts | |
path: packages/ | |
- name: Run Component Tests | |
uses: cypress-io/github-action@v4 | |
with: | |
install: false | |
command: pnpm run test:component:ci --spec ${{ matrix.container }} | |
- name: Normalize test results artifact name | |
continue-on-error: true | |
if: failure() | |
id: normalize-name | |
shell: bash | |
run: | | |
packageName=$(echo ${{ matrix.container }} | sed 's/\//-/g') | |
echo "artifactName=component-test-failures-${packageName}" >> $GITHUB_OUTPUT | |
- name: Upload Component Test Results | |
uses: actions/upload-artifact@v4 | |
continue-on-error: true | |
if: failure() | |
with: | |
name: ${{ steps.normalize-name.outputs.artifactName }} | |
path: | | |
cypress/videos/ | |
cypress/screenshots/ | |
finish-test-and-publish: | |
name: Collect Test Results And Publish | |
needs: [build, component-tests] | |
runs-on: ubuntu-latest | |
continue-on-error: true | |
timeout-minutes: 20 | |
if: ${{ always() && needs.build.outputs.filter != '' }} | |
env: | |
NPM_TOKEN: ${{ secrets.NPM_TOKEN }} | |
GH_TOKEN: ${{ secrets.KONGPONENTS_BOT_PAT }} | |
steps: | |
- name: Successful tests | |
if: ${{ !(contains(needs.*.result, 'failure')) }} | |
run: exit 0 | |
- name: Failing tests | |
if: ${{ contains(needs.*.result, 'failure') }} | |
run: exit 1 | |
- name: Checkout Source Code | |
if: ${{ github.event_name == 'push' }} | |
uses: actions/checkout@v4 | |
with: | |
fetch-depth: 0 | |
token: ${{ secrets.KONGPONENTS_BOT_PAT }} | |
- name: Setup PNPM with Dependencies | |
if: ${{ github.event_name == 'push' }} | |
uses: ./.github/actions/setup-pnpm-with-dependencies/ | |
- name: Download build artifacts | |
if: ${{ github.event_name == 'push' }} | |
uses: actions/download-artifact@v4 | |
with: | |
name: package-dist-artifacts | |
path: packages/ | |
# for lerna version we use: | |
# --force-git-tag - if tag was already created it will be recreated instead of command failing and entire CI failing | |
# --yes - so CI doesn't wait for the confirmation keyboard import | |
# --create-release - so that release is created in github when version is changed | |
# --conventional-commits - so that package's version changed following semantic releases | |
# | |
# we shall ignore lerna version error as pnpm publish will fail or not publish in case of such error | |
- name: Update package versions | |
if: ${{ github.event_name == 'push' }} | |
run: | | |
git config user.email "[email protected]" | |
git config user.name "Kong UI Bot" | |
pnpm --silent lerna version --conventional-commits --create-release github --yes --force-git-tag || true | |
- name: Publish packages to NPM | |
if: ${{ github.event_name == 'push' }} | |
run: | | |
echo "//registry.npmjs.org/:_authToken=${NODE_AUTH_TOKEN}" > .npmrc | |
pnpm --stream --filter "${{needs.build.outputs.filter}}" publish --no-git-checks --access public | |
env: | |
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN_PUBLIC_PUBLISH }} | |
notify-slack: | |
name: Slack Notification | |
if: ${{ always() && github.event_name == 'push' }} | |
runs-on: ubuntu-latest | |
timeout-minutes: 20 | |
needs: | |
- finish-test-and-publish | |
steps: | |
- name: Checkout Source Code | |
uses: actions/checkout@v4 | |
- name: Get aggregate Workflow status | |
uses: technote-space/workflow-conclusion-action@v3 | |
- name: Post Slack notification | |
uses: Kong/public-shared-actions/slack-actions/workflow-notification@v2 | |
with: | |
slack-webhook-url: ${{ env.WORKFLOW_CONCLUSION == 'failure' && secrets.SLACK_WEBHOOK_URL_ALERT || secrets.SLACK_WEBHOOK_URL_NOTIFY }} | |
status: ${{ env.WORKFLOW_CONCLUSION == 'failure' && 'failure' || 'success' }} |