diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 3e78adb40cb..13c155ac1af 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -835,6 +835,7 @@ embed.go @grafana/grafana-as-code /.github/workflows/i18n-crowdin-download.yml @grafana/grafana-frontend-platform /.github/workflows/i18n-crowdin-create-tasks.yml @grafana/grafana-frontend-platform /.github/workflows/i18n-verify.yml @grafana/grafana-frontend-platform +/.github/workflows/deploy-storybook-preview.yml @grafana/grafana-frontend-platform /.github/workflows/scripts/crowdin/create-tasks.ts @grafana/grafana-frontend-platform /.github/workflows/pr-go-workspace-check.yml @grafana/grafana-app-platform-squad /.github/workflows/pr-dependabot-update-go-workspace.yml @grafana/grafana-app-platform-squad diff --git a/.github/workflows/deploy-storybook-preview.yml b/.github/workflows/deploy-storybook-preview.yml new file mode 100644 index 00000000000..a1fecce67cb --- /dev/null +++ b/.github/workflows/deploy-storybook-preview.yml @@ -0,0 +1,93 @@ +name: Deploy Storybook preview + +on: + pull_request: + paths: + - 'packages/grafana-ui/**' + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +permissions: {} + +jobs: + deploy-storybook-preview: + name: Deploy Storybook preview + runs-on: ubuntu-latest + # Don't run from forks for the moment. If we find this useful we can do the workflow_run dance + # to make it work for forks. + if: github.event.pull_request.head.repo.fork == false + permissions: + contents: read + id-token: write + + env: + BUCKET_NAME: grafana-storybook-previews + + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + persist-credentials: false + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version-file: '.nvmrc' + cache: 'yarn' + + - name: Cache node_modules + uses: actions/cache@v4 + with: + path: | + node_modules + key: node_modules-${{ hashFiles('yarn.lock') }} + restore-keys: | + node_modules- + + - name: Install dependencies + env: + # If the PR isn't from a fork then don't use the slower yarn checks + YARN_ENABLE_HARDENED_MODE: ${{ github.event.pull_request.head.repo.fork == false && '1' || '0' }} + run: yarn install --immutable + + - name: Build storybook + run: yarn storybook:build + + # Create the GCS folder name for the preview. Creates a consistent name for all deploys for the PR. + # Matches format of `pr__`. + # Where `SANITIZED_BRANCH` is the branch name with only alphanumeric and hyphens, limited to 30 characters. + - name: Create deploy name + id: create-deploy-name + env: + BRANCH_NAME: ${{ github.event.pull_request.head.ref }} + PR_NUMBER: ${{ github.event.pull_request.number }} + run: | + # Convert branch name to only contain alphanumeric and hyphens + SANITIZED_BRANCH=$(echo "$BRANCH_NAME" | tr -cs "[:alnum:]-" "-" | sed "s/^-//;s/-$//") + + # Check if SANITIZED_BRANCH is empty and fail if it is + if [ -z "$SANITIZED_BRANCH" ]; then + echo "Error: Branch name resulted in empty string after sanitization" + exit 1 + fi + + echo "deploy-name=pr_${PR_NUMBER}_${SANITIZED_BRANCH:0:30}" >> "$GITHUB_OUTPUT" + + - name: Upload Storybook + uses: grafana/shared-workflows/actions/push-to-gcs@main + with: + environment: prod + bucket: ${{ env.BUCKET_NAME }} + bucket_path: ${{ steps.create-deploy-name.outputs.deploy-name }} + path: packages/grafana-ui/dist/storybook + service_account: github-gf-storybook-preview@grafanalabs-workload-identity.iam.gserviceaccount.com + parent: false + + - name: Write summary + env: + DEPLOY_NAME: ${{ steps.create-deploy-name.outputs.deploy-name }} + run: | + echo "## Storybook preview deployed! 🚀" >> $GITHUB_STEP_SUMMARY + echo "Check it out at https://storage.googleapis.com/${BUCKET_NAME}/${DEPLOY_NAME}/index.html" >> $GITHUB_STEP_SUMMARY diff --git a/packages/grafana-ui/.storybook/preview.ts b/packages/grafana-ui/.storybook/preview.ts index 41311f34244..93892fae443 100644 --- a/packages/grafana-ui/.storybook/preview.ts +++ b/packages/grafana-ui/.storybook/preview.ts @@ -52,6 +52,7 @@ if (process.env.NODE_ENV === 'development') { initialize({ onUnhandledRequest: 'bypass', serviceWorker: { + // Important! The path must be relative to work when we deploy storybook to subpaths (e.g. /ui/canary) url: 'mockServiceWorker.js', }, });