From efa641040dfce47882b6a435b29f4ee2b024e527 Mon Sep 17 00:00:00 2001 From: Jack Westbrook Date: Tue, 18 Apr 2023 10:19:37 +0200 Subject: [PATCH] Build: Improve NPM publishing (#65171) * chore(packages): remove redundant npm scripts for publishing packages * feat(packages): rewrite npm publishing script to work for manual and ci publishes * ci(drone): update release-canary-npm-packages step to use new script * docs(packages): update manual release instructions * wip(packages): attempt to validate packed npm package * fix(packages): release-canary-npm-packages should provide canary dist-tag * ci(packages): clean up npm package validation script * chore(devenv): add verdaccio config to allow anon publishing for easier dev npm testing * ci(packages): clean up publishing script * ci(drone): during build-frontend-packages, pack and validate packed tarballs * chore(codeowners): update for publish/validate npm packages scripts * ci(packages): fix esm loop bug matching e2e package * ci(npm-packages): fix failing regex * style(lib.star): run make format-drone * style(npm-packages): shellcheck fixes for validate-npm-packages script * docs(packages): update readme instructions for publishing locally and manually * refactor(npm-publish): use drone when to trigger canary releases * chore(drone): remove redundant trigger_npm_publish var * chore(npm-publish): remove redundant echo --- .drone.yml | 17 +- .github/CODEOWNERS | 2 + .gitignore | 2 +- devenv/local-npm/conf/config.yaml | 202 ++++++++++++++++++++++ devenv/local-npm/docker-compose.yaml | 2 +- package.json | 6 - packages/README.md | 37 ++-- scripts/circle-release-canary-packages.sh | 24 --- scripts/drone/steps/lib.star | 16 +- scripts/publish-npm-packages.sh | 44 +++++ scripts/validate-npm-packages.sh | 80 +++++++++ 11 files changed, 378 insertions(+), 54 deletions(-) create mode 100644 devenv/local-npm/conf/config.yaml delete mode 100755 scripts/circle-release-canary-packages.sh create mode 100755 scripts/publish-npm-packages.sh create mode 100755 scripts/validate-npm-packages.sh diff --git a/.drone.yml b/.drone.yml index 19ae07730d5..12c44b520d1 100644 --- a/.drone.yml +++ b/.drone.yml @@ -571,6 +571,8 @@ steps: name: build-frontend - commands: - ./bin/build build-frontend-packages --jobs 8 --edition oss --build-id ${DRONE_BUILD_NUMBER} + - yarn packages:pack + - ./scripts/validate-npm-packages.sh depends_on: - compile-build-cmd - yarn-install @@ -1458,6 +1460,8 @@ steps: name: build-frontend - commands: - ./bin/build build-frontend-packages --jobs 8 --edition oss --build-id ${DRONE_BUILD_NUMBER} + - yarn packages:pack + - ./scripts/validate-npm-packages.sh depends_on: - compile-build-cmd - yarn-install @@ -1734,7 +1738,7 @@ steps: repo: - grafana/grafana - commands: - - ./scripts/circle-release-canary-packages.sh + - ./scripts/publish-npm-packages.sh --dist-tag 'canary' --registry 'https://registry.npmjs.org/' depends_on: - end-to-end-tests-dashboards-suite - end-to-end-tests-panels-suite @@ -1746,6 +1750,9 @@ steps: image: grafana/build-container:1.7.3 name: release-canary-npm-packages when: + paths: + include: + - packages/** repo: - grafana/grafana - commands: @@ -4685,6 +4692,8 @@ steps: name: build-frontend - commands: - ./bin/build build-frontend-packages --jobs 8 --edition oss --build-id ${DRONE_BUILD_NUMBER} + - yarn packages:pack + - ./scripts/validate-npm-packages.sh depends_on: - compile-build-cmd - yarn-install @@ -5328,6 +5337,8 @@ steps: name: build-frontend - commands: - ./bin/build build-frontend-packages --jobs 8 --edition enterprise --build-id ${DRONE_BUILD_NUMBER} + - yarn packages:pack + - ./scripts/validate-npm-packages.sh depends_on: - compile-build-cmd - yarn-install @@ -6049,6 +6060,8 @@ steps: name: build-frontend - commands: - ./bin/build build-frontend-packages --jobs 8 --edition enterprise --build-id ${DRONE_BUILD_NUMBER} + - yarn packages:pack + - ./scripts/validate-npm-packages.sh depends_on: - compile-build-cmd - yarn-install @@ -6810,6 +6823,6 @@ kind: secret name: enterprise2_security_prefix --- kind: signature -hmac: d3567c954d0ac9f1f47d55bc85eb6594379c888fe591428f2dcd0146f2bd3ca2 +hmac: 7f282aaf4f3ba496f2d954241a16afd2facbf2cf1ef04dfb75cfec1b42fd39d1 ... diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 07c06825e28..2d551c7a4df 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -455,6 +455,8 @@ lerna.json @grafana/frontend-ops /scripts/check-breaking-changes.sh @grafana/plugins-platform-frontend /scripts/ci-* @grafana/grafana-delivery /scripts/circle-* @grafana/grafana-delivery +/scripts/publish-npm-packages.sh @grafana/grafana-delivery @grafana/plugins-platform-frontend +/scripts/validate-npm-packages.sh @grafana/grafana-delivery @grafana/plugins-platform-frontend /scripts/ci-frontend-metrics.sh @grafana/grafana-frontend-platform @grafana/plugins-platform-frontend @grafana/grafana-bi-squad /scripts/cli/ @grafana/grafana-frontend-platform /scripts/clean-git-or-error.sh @grafana/grafana-as-code diff --git a/.gitignore b/.gitignore index 39b7a1e2ae4..fbfb6a6396f 100644 --- a/.gitignore +++ b/.gitignore @@ -139,7 +139,7 @@ pkg/services/quota/quotaimpl/storage/storage.json /packages/**/package.tgz /packages/grafana-toolkit/sass ## CI places the packages in a different location -/npm-artifacts/*.tgz +/npm-artifacts # Ignore frontend build manifest manifest.json diff --git a/devenv/local-npm/conf/config.yaml b/devenv/local-npm/conf/config.yaml new file mode 100644 index 00000000000..26686016f46 --- /dev/null +++ b/devenv/local-npm/conf/config.yaml @@ -0,0 +1,202 @@ +# +# This is the default configuration file. It allows all users to do anything, +# please read carefully the documentation and best practices to +# improve security. +# +# Do not configure host and port under `listen` in this file +# as it will be ignored when using docker. +# see https://verdaccio.org/docs/en/docker#docker-and-custom-port-configuration +# +# Look here for more config file examples: +# https://github.com/verdaccio/verdaccio/tree/5.x/conf +# +# Read about the best practices +# https://verdaccio.org/docs/best + +# path to a directory with all packages +storage: /verdaccio/storage/data +# path to a directory with plugins to include +plugins: /verdaccio/plugins + +# https://verdaccio.org/docs/webui +web: + title: Verdaccio + # comment out to disable gravatar support + # gravatar: false + # by default packages are ordercer ascendant (asc|desc) + # sort_packages: asc + # convert your UI to the dark side + # darkMode: true + # html_cache: true + # by default all features are displayed + # login: true + # showInfo: true + # showSettings: true + # In combination with darkMode you can force specific theme + # showThemeSwitch: true + # showFooter: true + # showSearch: true + # showRaw: true + # showDownloadTarball: true + # HTML tags injected after manifest + # scriptsBodyAfter: + # - '' + # HTML tags injected before ends + # metaScripts: + # - '' + # - '' + # - '' + # HTML tags injected first child at + # bodyBefore: + # - '
html before webpack scripts
' + # Public path for template manifest scripts (only manifest) + # publicPath: http://somedomain.org/ + +# https://verdaccio.org/docs/configuration#authentication +auth: + htpasswd: + file: /verdaccio/storage/htpasswd + # Maximum amount of users allowed to register, defaults to "+infinity". + # You can set this to -1 to disable registration. + # max_users: 1000 + # Hash algorithm, possible options are: "bcrypt", "md5", "sha1", "crypt". + # algorithm: bcrypt # by default is crypt, but is recommended use bcrypt for new installations + # Rounds number for "bcrypt", will be ignored for other algorithms. + # rounds: 10 + +# https://verdaccio.org/docs/configuration#uplinks +# a list of other known repositories we can talk to +uplinks: + npmjs: + url: https://registry.npmjs.org/ + +# Learn how to protect your packages +# https://verdaccio.org/docs/protect-your-dependencies/ +# https://verdaccio.org/docs/configuration#packages +packages: + '@*/*': + # allow all users (including non-authenticated users) to read and + # publish scoped packages + access: $anonymous + publish: $anonymous + unpublish: $anonymous + proxy: npmjs + + '**': + # allow all users (including non-authenticated users) to read and + # publish all packages + # + # you can specify usernames/groupnames (depending on your auth plugin) + # and three keywords: "$all", "$anonymous", "$authenticated" + access: $anonymous + + # allow all known users to publish/publish packages + # (anyone can register by default, remember?) + publish: $anonymous + unpublish: $anonymous + + # if package is not available locally, proxy requests to 'npmjs' registry + proxy: npmjs + +# To improve your security configuration and avoid dependency confusion +# consider removing the proxy property for private packages +# https://verdaccio.org/docs/best#remove-proxy-to-increase-security-at-private-packages + +# https://verdaccio.org/docs/configuration#server +# You can specify HTTP/1.1 server keep alive timeout in seconds for incoming connections. +# A value of 0 makes the http server behave similarly to Node.js versions prior to 8.0.0, which did not have a keep-alive timeout. +# WORKAROUND: Through given configuration you can workaround following issue https://github.com/verdaccio/verdaccio/issues/301. Set to 0 in case 60 is not enough. +server: + keepAliveTimeout: 60 + # Allow `req.ip` to resolve properly when Verdaccio is behind a proxy or load-balancer + # See: https://expressjs.com/en/guide/behind-proxies.html + # trustProxy: '127.0.0.1' + +# https://verdaccio.org/docs/configuration#offline-publish +# publish: +# allow_offline: false + +# https://verdaccio.org/docs/configuration#url-prefix +# url_prefix: /verdaccio/ +# VERDACCIO_PUBLIC_URL='https://somedomain.org'; +# url_prefix: '/my_prefix' +# // url -> https://somedomain.org/my_prefix/ +# VERDACCIO_PUBLIC_URL='https://somedomain.org'; +# url_prefix: '/' +# // url -> https://somedomain.org/ +# VERDACCIO_PUBLIC_URL='https://somedomain.org/first_prefix'; +# url_prefix: '/second_prefix' +# // url -> https://somedomain.org/second_prefix/' + +# https://verdaccio.org/docs/configuration#security +# security: +# api: +# legacy: true +# jwt: +# sign: +# expiresIn: 29d +# verify: +# someProp: [value] +# web: +# sign: +# expiresIn: 1h # 1 hour by default +# verify: +# someProp: [value] + +# https://verdaccio.org/docs/configuration#user-rate-limit +# userRateLimit: +# windowMs: 50000 +# max: 1000 + +# https://verdaccio.org/docs/configuration#max-body-size +# max_body_size: 10mb + +# https://verdaccio.org/docs/configuration#listen-port +# listen: +# - localhost:4873 # default value +# - http://localhost:4873 # same thing +# - 0.0.0.0:4873 # listen on all addresses (INADDR_ANY) +# - https://example.org:4873 # if you want to use https +# - "[::1]:4873" # ipv6 +# - unix:/tmp/verdaccio.sock # unix socket + +# The HTTPS configuration is useful if you do not consider use a HTTP Proxy +# https://verdaccio.org/docs/configuration#https +# https: +# key: ./path/verdaccio-key.pem +# cert: ./path/verdaccio-cert.pem +# ca: ./path/verdaccio-csr.pem + +# https://verdaccio.org/docs/configuration#proxy +# http_proxy: http://something.local/ +# https_proxy: https://something.local/ + +# https://verdaccio.org/docs/configuration#notifications +# notify: +# method: POST +# headers: [{ "Content-Type": "application/json" }] +# endpoint: https://usagge.hipchat.com/v2/room/3729485/notification?auth_token=mySecretToken +# content: '{"color":"green","message":"New package published: * {{ name }}*","notify":true,"message_format":"text"}' + +middlewares: + audit: + enabled: true + +# https://verdaccio.org/docs/logger +# log settings +logs: { type: stdout, format: pretty, level: http } +#experiments: +# # support for npm token command +# token: false +# # enable tarball URL redirect for hosting tarball with a different server, the tarball_url_redirect can be a template string +# tarball_url_redirect: 'https://mycdn.com/verdaccio/${packageName}/${filename}' +# # the tarball_url_redirect can be a function, takes packageName and filename and returns the url, when working with a js configuration file +# tarball_url_redirect(packageName, filename) { +# const signedUrl = // generate a signed url +# return signedUrl; +# } + +# translate your registry, api i18n not available yet +# i18n: +# list of the available translations https://github.com/verdaccio/verdaccio/blob/master/packages/plugins/ui-theme/src/i18n/ABOUT_TRANSLATIONS.md +# web: en-US \ No newline at end of file diff --git a/devenv/local-npm/docker-compose.yaml b/devenv/local-npm/docker-compose.yaml index 1a0acdc8a25..be0ea5220ec 100644 --- a/devenv/local-npm/docker-compose.yaml +++ b/devenv/local-npm/docker-compose.yaml @@ -7,7 +7,7 @@ services: ports: - "4873:4873" volumes: - - verdaccio:/verdaccio + - ./conf:/verdaccio/conf volumes: verdaccio: diff --git a/package.json b/package.json index b525589d2e0..0e3fbdef90e 100644 --- a/package.json +++ b/package.json @@ -29,12 +29,6 @@ "packages:clean": "rimraf ./npm-artifacts && lerna run clean --parallel", "packages:prepare": "lerna version --no-push --no-git-tag-version --force-publish --exact", "packages:pack": "mkdir -p ./npm-artifacts && lerna exec --no-private -- yarn pack --out \"../../npm-artifacts/%s-%v.tgz\"", - "packages:publish": "lerna exec --no-private -- npm publish package.tgz", - "packages:publishCanary": "lerna exec --no-private -- npm publish package.tgz --tag canary", - "packages:publishLatest": "lerna exec --no-private -- npm publish package.tgz", - "packages:publishNext": "lerna exec --no-private -- npm publish package.tgz --tag next", - "packages:publishTest": "lerna exec --no-private -- npm publish package.tgz --tag test", - "packages:publishDev": "lerna exec --no-private -- npm publish package.tgz --tag dev --registry http://localhost:4873", "packages:typecheck": "lerna run typecheck", "precommit": "yarn run lint-staged", "prettier:check": "prettier --check --list-different=false --loglevel=warn \"**/*.{ts,tsx,scss,md,mdx}\"", diff --git a/packages/README.md b/packages/README.md index 4fe45149509..6fc9c3cd7b7 100644 --- a/packages/README.md +++ b/packages/README.md @@ -36,20 +36,21 @@ Every commit to main that has changes within the `packages` directory is a subje > All of the steps below must be performed on a release branch, according to Grafana Release Guide. -> Make sure you are logged in to npm in your terminal and that you are a part of Grafana org on npm. +> You must be logged in to NPM as part of Grafana NPM org before attempting to publish to the npm registery. -1. Run `yarn packages:prepare` script from the root directory. This performs tests on the packages and prompts for the version of the packages. The version should be the same as the one being released. +1. Run `yarn packages:clean` script from the root directory. This will delete any previous builds of the packages. +2. Run `yarn packages:prepare` script from the root directory. This performs tests on the packages and prompts for the version of the packages. The version should be the same as the one being released. - Make sure you use semver convention. So, _place a dot between prerelease id and prerelease number_, i.e. 6.3.0-alpha.1 - Make sure you confirm the version bump when prompted! -2. Run `yarn packages:build` script that compiles distribution code in `packages/grafana-*/dist`. -3. Run `yarn packages:pack` script to zip each package into `.tgz`. This is required for yarn berry to replace properties in the package.json files declared in `publishConfig`. -4. Depending whether or not it's a prerelease: +3. Run `yarn packages:build` script that compiles distribution code in `packages/grafana-*/dist`. +4. Run `yarn packages:pack` script to compress each package into `npm-artifacts/*.tgz` files. This is required for yarn to replace properties in the package.json files declared in the `publishConfig` property. +5. Depending on whether or not it's a prerelease: - - When releasing a prerelease run `packages:publishNext` to publish new versions. - - When releasing a stable version run `packages:publishLatest` to publish new versions. - - When releasing a test version run `packages:publishTest` to publish test versions. + - When releasing a prerelease run `./scripts/publish-npm-packages.sh --dist-tag 'next' --registry 'https://registry.npmjs.org/'` to publish new versions. + - When releasing a stable version run `./scripts/publish-npm-packages.sh --dist-tag 'latest' --registry 'https://registry.npmjs.org/'` to publish new versions. + - When releasing a test version run `./scripts/publish-npm-packages.sh --dist-tag 'test' --registry 'https://registry.npmjs.org/'` to publish test versions. -5. Push version commit to the release branch. +6. Revert any changes made by the `packages:prepare` script. ### Building individual packages @@ -72,21 +73,21 @@ In this guide you will set up [Verdaccio](https://verdaccio.org/) registry local From your terminal: 1. Navigate to `devenv/local-npm` directory. -2. Run `docker-compose up`. This will start your local npm registry, available at http://localhost:4873/ -3. Run `npm login --registry=http://localhost:4873 --scope=@grafana` . This will allow you to publish any @grafana/\* package into the local registry. -4. Run `npm config set @grafana:registry http://localhost:4873`. This will config your npm to install @grafana scoped packages from your local registry. +2. Run `docker-compose up`. This will start your local npm registry, available at http://localhost:4873/. Note the verdaccio config allows +3. To test `@grafana` packages published to your local npm registry uncomment `npmScopes` and `unsafeHttpWhitelist` properties in the `.yarnrc` file. #### Publishing packages to local npm registry -You need to follow [manual packages release procedure](#manual-release). The only difference is you need to run `yarn packages:publishDev` task in order to publish to you local registry. +You need to follow [manual packages release procedure](#manual-release). The only difference is the last command in order to publish to you local registry. From your terminal: -1. Run `yarn packages:prepare`. -2. Run `yarn packages:build`. -3. Run `yarn packages:pack`. -4. Run `yarn packages:publishDev`. -5. Navigate to http://localhost:4873 and verify that version was published +1. Run `yarn packages:clean`. +2. Run `yarn packages:prepare`. +3. Run `yarn packages:build`. +4. Run `yarn packages:pack`. +5. Run `./scripts/publish-npm-packages.sh`. +6. Navigate to http://localhost:4873 and verify the version was published Locally published packages will be published under `dev` channel, so in your plugin package.json file you can use that channel. For example: diff --git a/scripts/circle-release-canary-packages.sh b/scripts/circle-release-canary-packages.sh deleted file mode 100755 index 4487282a782..00000000000 --- a/scripts/circle-release-canary-packages.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env bash -set -eo pipefail - -# shellcheck source=./scripts/helpers/exit-if-fail.sh -source "$(dirname "$0")/helpers/exit-if-fail.sh" - -# check if there were any changes to packages between current and previous commit -count=$(git diff HEAD~1..HEAD --name-only -- packages | awk '{c++} END {print c}') - -if [ -z "$count" ]; then - echo "No changes in packages, skipping packages publishing" -else - echo "Changes detected in ${count} packages" - echo "Starting to release latest canary version" - - echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" >> ~/.npmrc - - echo $'\nPacking packages' - yarn packages:pack - - echo $'\nPublishing packages' - for file in ./npm-artifacts/*.tgz; do npm publish "$file" --tag canary; done - -fi diff --git a/scripts/drone/steps/lib.star b/scripts/drone/steps/lib.star index f6d448027f7..3cba0e8da70 100644 --- a/scripts/drone/steps/lib.star +++ b/scripts/drone/steps/lib.star @@ -567,6 +567,8 @@ def build_frontend_package_step(edition, ver_mode): cmds = [ "./bin/build build-frontend-packages --jobs 8 --edition {} ".format(edition) + "--build-id {}".format(build_no), + "yarn packages:pack", + "./scripts/validate-npm-packages.sh", ] return { @@ -1179,11 +1181,21 @@ def release_canary_npm_packages_step(trigger = None): "NPM_TOKEN": from_secret("npm_token"), }, "commands": [ - "./scripts/circle-release-canary-packages.sh", + "./scripts/publish-npm-packages.sh --dist-tag 'canary' --registry 'https://registry.npmjs.org/'", ], } if trigger: - step = dict(step, when = trigger) + step = dict( + step, + when = dict( + trigger, + paths = { + "include": [ + "packages/**", + ], + }, + ), + ) return step def enterprise2_suffix(edition): diff --git a/scripts/publish-npm-packages.sh b/scripts/publish-npm-packages.sh new file mode 100755 index 00000000000..2437403626d --- /dev/null +++ b/scripts/publish-npm-packages.sh @@ -0,0 +1,44 @@ +#!/bin/bash + +# Set default values for dist-tag and registry for local development +# to prevent running this script and accidentally publishing to npm +dist_tag="canary" +registry="http://localhost:4873" + +# shellcheck source=./scripts/helpers/exit-if-fail.sh +source "$(dirname "$0")/helpers/exit-if-fail.sh" + +if [ -z "$NPM_TOKEN" ]; then + echo "The NPM_TOKEN environment variable does not exist." + exit 1 +fi + +# Parse command line arguments +while [[ $# -gt 0 ]]; do + key="$1" + case $key in + --dist-tag) + dist_tag="$2" + shift # past argument + shift # past value + ;; + --registry) + registry="$2" + shift # past argument + shift # past value + ;; + *) # unknown option + echo "Unknown option: $1" + exit 1 + ;; + esac +done + +echo "Starting to release $dist_tag version" + +echo "$registry/:_authToken=${NPM_TOKEN}" >> ~/.npmrc + +# Loop over .tar files in directory and publish them to npm registry +for file in ./npm-artifacts/*.tgz; do + npm publish "$file" --tag "$dist_tag" --registry "$registry" +done diff --git a/scripts/validate-npm-packages.sh b/scripts/validate-npm-packages.sh new file mode 100755 index 00000000000..a07ebe5a662 --- /dev/null +++ b/scripts/validate-npm-packages.sh @@ -0,0 +1,80 @@ +#!/bin/bash + +# This script is used to validate the npm packages that are published to npmjs.org are in the correct format. +# It won't catch things like malformed JS or Types but it will assert that the package has +# the correct files and package.json properties. +ARTIFACTS_DIR="./npm-artifacts" + +for file in "$ARTIFACTS_DIR"/*.tgz; do + echo "🔍 Checking NPM package: $file" + # get filename then strip everything after package name. + dir_name=$(basename "$file" .tgz | sed 's/^@\(.*\)-[0-9]*[.]*[0-9]*[.]*[0-9]*-\([0-9]*[a-zA-Z]*\)/\1/') + mkdir -p "./npm-artifacts/$dir_name" + tar -xzf "$file" -C "./npm-artifacts/$dir_name" --strip-components=1 + + # Make sure the tar wasn't empty + if [ ! -d "./npm-artifacts/$dir_name" ]; then + echo -e "❌ Failed: Empty package $dir_name.\n" + exit 1 + fi + + # Navigate inside the new extracted directory + pushd "./npm-artifacts/$dir_name" || exit + + # Check for required files + check_files=("package.json" "README.md" "CHANGELOG.md" "LICENSE_APACHE2") + for check_file in "${check_files[@]}"; do + if [ ! -f "$check_file" ]; then + echo -e "❌ Failed: Missing required file $check_file in package $dir_name.\n" + exit 1 + fi + done + + # @grafana/toolkit structure is different to the other packages + if [[ "$dir_name" == "grafana-toolkit" ]]; then + if [ ! -d bin ] || [ ! -f bin/grafana-toolkit.js ]; then + echo -e "❌ Failed: Missing 'bin' directory or required files in package $dir_name.\n" + exit 1 + fi + + echo -e "✅ Passed: package checks for $file.\n" + popd || exit + continue + fi + + # Assert commonjs builds + if [ ! -d dist ] || [ ! -f dist/index.js ] || [ ! -f dist/index.d.ts ]; then + echo -e "❌ Failed: Missing 'dist' directory or required commonjs files in package $dir_name.\n" + exit 1 + fi + + if [ "$(jq -r '.main' package.json)" != "dist/index.js" ] || \ + [ "$(jq -r '.types' package.json)" != "dist/index.d.ts" ]; then + echo -e "❌ Failed: Incorrect package.json properties in package $dir_name.\n" + exit 1 + fi + + # Assert esm builds + esm_packages=("grafana-data" "grafana-ui" "grafana-runtime" "grafana-e2e-selectors" "grafana-schema") + for esm_package in "${esm_packages[@]}"; do + if [[ "$dir_name" == "$esm_package" ]]; then + if [ ! -d dist/esm ] || [ ! -f dist/esm/index.js ]; then + echo -e "❌ Failed: Missing 'dist/esm' directory or required esm files in package $dir_name.\n" + exit 1 + fi + + if [ "$(jq -r '.module' package.json)" != "dist/esm/index.js" ]; then + echo -e "❌ Failed: Incorrect package.json properties in package $dir_name.\n" + exit 1 + fi + fi + done + + echo -e "✅ Passed: package checks for $file.\n" + popd || exit + +done + +echo "🚀 All NPM package checks passed! 🚀" +rm -rf "${ARTIFACTS_DIR:?}/"*/ +exit 0