From 653ee392d65a4e3186f49eda79940628e945f639 Mon Sep 17 00:00:00 2001 From: bonnywelsford-source Date: Tue, 28 Jul 2026 11:18:39 -0400 Subject: [PATCH 1/3] Harden Stack ID guidance and remove em dashes in automate-k6-cicd-lj. Treat K6_CLOUD_STACK_ID as required for k6 v2 / latest images in the CI examples, and replace em dashes with standard punctuation. Co-authored-by: Cursor --- automate-k6-cicd-lj/content.json | 2 +- automate-k6-cicd-lj/end-journey/content.json | 2 +- automate-k6-cicd-lj/handle-exit-code/content.json | 2 +- .../run-first-automated-test/content.json | 2 +- .../stream-results-cloud/content.json | 14 +++++++------- .../understand-performance-gates/content.json | 2 +- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/automate-k6-cicd-lj/content.json b/automate-k6-cicd-lj/content.json index 04c6aefb..9ecd6f95 100644 --- a/automate-k6-cicd-lj/content.json +++ b/automate-k6-cicd-lj/content.json @@ -4,7 +4,7 @@ "blocks": [ { "type": "markdown", - "content": "Welcome to the Grafana learning path that shows you how to automate k6 performance tests in your CI/CD pipelines. Running k6 manually gives you performance data when you think to ask for it. Automating k6 in your pipeline gives you performance data on every deploy, with the ability to block releases that don't meet your standards.\n\nThis path guides you from a manually run k6 script to a CI/CD performance gate. You'll verify that thresholds produce the right exit codes, parameterize your script for multiple environments, add k6 to GitHub Actions or GitLab CI, and stream results to Grafana Cloud k6. By the end, performance testing is part of the daily workflow \u2014 not a laptop-only habit.\n\n## Here's what to expect\n\nWhen you complete this path, you'll be able to:\n\n- Explain what a CI/CD performance gate is and why exit codes matter\n- Verify that k6 thresholds pass and fail with the correct exit codes\n- Parameterize a script with `__ENV` so one script runs across environments\n- Add k6 to GitHub Actions or GitLab CI\n- Treat threshold breaches as pipeline failures that block merges or deploys\n- Stream automated test results to Grafana Cloud k6\n\n## Before you begin\n\nBefore you automate k6 in your CI/CD pipeline, ensure that you have:\n\n- A Grafana Cloud account. To create an account, refer to [Grafana Cloud](https://grafana.com/signup/cloud/connect-account).\n- k6 installed on your machine. To install k6, refer to [k6 installation](https://grafana.com/docs/k6/latest/get-started/installation/).\n- A k6 test script with thresholds. If you don't have one yet, complete [Run your first k6 performance test](https://grafana.com/docs/learning-paths/run-first-k6-test/) and [Establish a performance baseline with k6](https://grafana.com/docs/learning-paths/establish-k6-baseline/) first.\n- A code editor such as [Visual Studio Code](https://code.visualstudio.com/) or [Cursor](https://www.cursor.com/).\n- Access to a terminal or command line interface.\n- Access to a CI/CD platform such as GitHub Actions or GitLab CI.\n- Basic familiarity with your CI/CD platform's YAML configuration.\n\n## Troubleshooting\n\nIf you get stuck, we've got your back! Where appropriate, troubleshooting information is just a click away.\n\n## More to explore\n\nWe understand you might want to explore other capabilities not strictly on this path. We'll provide you opportunities where it makes sense." + "content": "Welcome to the Grafana learning path that shows you how to automate k6 performance tests in your CI/CD pipelines. Running k6 manually gives you performance data when you think to ask for it. Automating k6 in your pipeline gives you performance data on every deploy, with the ability to block releases that don't meet your standards.\n\nThis path guides you from a manually run k6 script to a CI/CD performance gate. You'll verify that thresholds produce the right exit codes, parameterize your script for multiple environments, add k6 to GitHub Actions or GitLab CI, and stream results to Grafana Cloud k6. By the end, performance testing is part of the daily workflow, not a laptop-only habit.\n\n## Here's what to expect\n\nWhen you complete this path, you'll be able to:\n\n- Explain what a CI/CD performance gate is and why exit codes matter\n- Verify that k6 thresholds pass and fail with the correct exit codes\n- Parameterize a script with `__ENV` so one script runs across environments\n- Add k6 to GitHub Actions or GitLab CI\n- Treat threshold breaches as pipeline failures that block merges or deploys\n- Stream automated test results to Grafana Cloud k6\n\n## Before you begin\n\nBefore you automate k6 in your CI/CD pipeline, ensure that you have:\n\n- A Grafana Cloud account. To create an account, refer to [Grafana Cloud](https://grafana.com/signup/cloud/connect-account).\n- k6 installed on your machine. To install k6, refer to [k6 installation](https://grafana.com/docs/k6/latest/get-started/installation/).\n- A k6 test script with thresholds. If you don't have one yet, complete [Run your first k6 performance test](https://grafana.com/docs/learning-paths/run-first-k6-test/) and [Establish a performance baseline with k6](https://grafana.com/docs/learning-paths/establish-k6-baseline/) first.\n- A code editor such as [Visual Studio Code](https://code.visualstudio.com/) or [Cursor](https://www.cursor.com/).\n- Access to a terminal or command line interface.\n- Access to a CI/CD platform such as GitHub Actions or GitLab CI.\n- Basic familiarity with your CI/CD platform's YAML configuration.\n\n## Troubleshooting\n\nIf you get stuck, we've got your back! Where appropriate, troubleshooting information is just a click away.\n\n## More to explore\n\nWe understand you might want to explore other capabilities not strictly on this path. We'll provide you opportunities where it makes sense." } ] } diff --git a/automate-k6-cicd-lj/end-journey/content.json b/automate-k6-cicd-lj/end-journey/content.json index 8a125412..00527eeb 100644 --- a/automate-k6-cicd-lj/end-journey/content.json +++ b/automate-k6-cicd-lj/end-journey/content.json @@ -4,7 +4,7 @@ "blocks": [ { "type": "markdown", - "content": "Congratulations on completing this learning path! Job well done!\n\nYou've accomplished the following:\n\n- Learned what CI/CD performance gates are and how exit codes turn k6 thresholds into automated deploy decisions\n- Verified that your k6 thresholds produce the correct exit codes for pipeline integration\n- Parameterized your script with `__ENV` variables so a single script runs against multiple environments\n- Added k6 as an automated step in GitHub Actions or GitLab CI\n- Configured your pipeline to treat k6 threshold breaches as build failures that block merges and deployments\n- Streamed automated test results to Grafana Cloud k6 for persistent storage and team visibility\n\n### What's next\n\nk6 is now in the daily workflow. Next you can operationalize the gate further \u2014 environment-specific thresholds, regression tracking, and failure notifications \u2014 and expand coverage to browser tests and Core Web Vitals for full-stack teams." + "content": "Congratulations on completing this learning path! Job well done!\n\nYou've accomplished the following:\n\n- Learned what CI/CD performance gates are and how exit codes turn k6 thresholds into automated deploy decisions\n- Verified that your k6 thresholds produce the correct exit codes for pipeline integration\n- Parameterized your script with `__ENV` variables so a single script runs against multiple environments\n- Added k6 as an automated step in GitHub Actions or GitLab CI\n- Configured your pipeline to treat k6 threshold breaches as build failures that block merges and deployments\n- Streamed automated test results to Grafana Cloud k6 for persistent storage and team visibility\n\n### What's next\n\nk6 is now in the daily workflow. Next you can operationalize the gate further with environment-specific thresholds, regression tracking, and failure notifications, and expand coverage to browser tests and Core Web Vitals for full-stack teams." } ] } diff --git a/automate-k6-cicd-lj/handle-exit-code/content.json b/automate-k6-cicd-lj/handle-exit-code/content.json index 2cbb755e..7fb137e1 100644 --- a/automate-k6-cicd-lj/handle-exit-code/content.json +++ b/automate-k6-cicd-lj/handle-exit-code/content.json @@ -4,7 +4,7 @@ "blocks": [ { "type": "markdown", - "content": "k6 uses exit codes to communicate test results to the pipeline. Exit code `0` means all thresholds passed. A non-zero exit code means the test failed \u2014 for threshold breaches, k6 commonly returns `99`. Most CI/CD platforms treat any non-zero exit code as a job failure by default, but you still need to confirm that nothing in your job swallows that signal.\n\nTo ensure your pipeline correctly handles the k6 exit code, complete the following steps:\n\n1. Verify that your CI platform fails the job on a non-zero exit code. In GitHub Actions, each step fails the job by default when the command returns a non-zero exit code. `grafana/run-k6-action` preserves this behavior, so no additional configuration is needed if you used the setup from the previous milestone.\n\n1. If you run k6 using a shell script or Docker command in your pipeline, ensure the exit code propagates. A common mistake is wrapping k6 in a script that doesn't forward the exit code:\n\n ```bash\n # Wrong \u2014 the echo succeeds and masks a k6 failure\n docker run --rm grafana/k6:latest run /tests/test.js\n echo \"Test complete\"\n ```\n\n The `echo` command returns exit code `0` regardless of the k6 result. Instead, ensure k6 is the last command, or capture the exit code explicitly:\n\n ```bash\n docker run --rm grafana/k6:latest run /tests/test.js\n K6_EXIT=$?\n echo \"Test complete with exit code $K6_EXIT\"\n exit $K6_EXIT\n ```\n\n1. Test the gate by temporarily setting a threshold that will fail, as you did in the verify-thresholds milestone. Push the change and confirm the pipeline marks the job as failed.\n\n In GitHub Actions, a failed job shows a red X next to the step. In GitLab CI, the job status changes to `failed`. The pipeline log shows which k6 thresholds were breached.\n\n1. Revert the threshold to its passing value and push again. Confirm the pipeline passes.\n\n> **Tip:** For pull request workflows, configure your repository to require the k6 job to pass before merging. In GitHub, go to **Settings** > **Branches** > **Branch protection rules** and add your performance test job to the required status checks. In GitLab, keep the job in a stage that blocks the pipeline by default.\n\n1. Confirm the full cycle: a passing test allows the pipeline to continue, and a failing test blocks the merge or deploy. This is your performance gate.\n\nIn the next milestone, you trigger a full pipeline run and verify the automated results end to end." + "content": "k6 uses exit codes to communicate test results to the pipeline. Exit code `0` means all thresholds passed. A non-zero exit code means the test failed. For threshold breaches, k6 commonly returns `99`. Most CI/CD platforms treat any non-zero exit code as a job failure by default, but you still need to confirm that nothing in your job swallows that signal.\n\nTo ensure your pipeline correctly handles the k6 exit code, complete the following steps:\n\n1. Verify that your CI platform fails the job on a non-zero exit code. In GitHub Actions, each step fails the job by default when the command returns a non-zero exit code. `grafana/run-k6-action` preserves this behavior, so no additional configuration is needed if you used the setup from the previous milestone.\n\n1. If you run k6 using a shell script or Docker command in your pipeline, ensure the exit code propagates. A common mistake is wrapping k6 in a script that doesn't forward the exit code:\n\n ```bash\n # Wrong: the echo succeeds and masks a k6 failure\n docker run --rm grafana/k6:latest run /tests/test.js\n echo \"Test complete\"\n ```\n\n The `echo` command returns exit code `0` regardless of the k6 result. Instead, ensure k6 is the last command, or capture the exit code explicitly:\n\n ```bash\n docker run --rm grafana/k6:latest run /tests/test.js\n K6_EXIT=$?\n echo \"Test complete with exit code $K6_EXIT\"\n exit $K6_EXIT\n ```\n\n1. Test the gate by temporarily setting a threshold that will fail, as you did in the verify-thresholds milestone. Push the change and confirm the pipeline marks the job as failed.\n\n In GitHub Actions, a failed job shows a red X next to the step. In GitLab CI, the job status changes to `failed`. The pipeline log shows which k6 thresholds were breached.\n\n1. Revert the threshold to its passing value and push again. Confirm the pipeline passes.\n\n> **Tip:** For pull request workflows, configure your repository to require the k6 job to pass before merging. In GitHub, go to **Settings** > **Branches** > **Branch protection rules** and add your performance test job to the required status checks. In GitLab, keep the job in a stage that blocks the pipeline by default.\n\n1. Confirm the full cycle: a passing test allows the pipeline to continue, and a failing test blocks the merge or deploy. This is your performance gate.\n\nIn the next milestone, you trigger a full pipeline run and verify the automated results end to end." } ] } diff --git a/automate-k6-cicd-lj/run-first-automated-test/content.json b/automate-k6-cicd-lj/run-first-automated-test/content.json index fca17dde..18cff776 100644 --- a/automate-k6-cicd-lj/run-first-automated-test/content.json +++ b/automate-k6-cicd-lj/run-first-automated-test/content.json @@ -4,7 +4,7 @@ "blocks": [ { "type": "markdown", - "content": "You've configured k6 as a pipeline step with exit code handling. Now trigger a clean automated run and confirm the gate behaves as expected end to end. At this stage, results live in your CI logs. In the next milestone, you'll stream those results to Grafana Cloud k6 for history and team visibility.\n\nTo run your first automated test, complete the following steps:\n\n1. Confirm your workflow file is committed and your test script path matches the workflow `path` (or GitLab `script`) value.\n\n1. Trigger a pipeline run. The simplest way is to push an empty commit or open a pull request:\n\n ```bash\n git commit --allow-empty -m \"Trigger k6 performance pipeline\"\n git push\n ```\n\n1. Open the workflow run in your CI platform and watch the k6 job. Confirm that:\n\n - The job checks out your repository\n - k6 starts and prints the test summary\n - The job finishes green when thresholds pass\n\n1. Optionally force a controlled failure one more time (tighten a threshold, push, confirm red, then revert). This is the moment the team can trust the gate: green means within budget, red means stop and investigate.\n\n1. Save a link to a successful run in your team's runbook or Definition of Done notes. From here, performance is no longer \"run it when you remember\" \u2014 it's a pipeline dependency.\n\nIn the next milestone, you stream results to Grafana Cloud k6 so automated runs persist beyond CI log retention." + "content": "You've configured k6 as a pipeline step with exit code handling. Now trigger a clean automated run and confirm the gate behaves as expected end to end. At this stage, results live in your CI logs. In the next milestone, you'll stream those results to Grafana Cloud k6 for history and team visibility.\n\nTo run your first automated test, complete the following steps:\n\n1. Confirm your workflow file is committed and your test script path matches the workflow `path` (or GitLab `script`) value.\n\n1. Trigger a pipeline run. The simplest way is to push an empty commit or open a pull request:\n\n ```bash\n git commit --allow-empty -m \"Trigger k6 performance pipeline\"\n git push\n ```\n\n1. Open the workflow run in your CI platform and watch the k6 job. Confirm that:\n\n - The job checks out your repository\n - k6 starts and prints the test summary\n - The job finishes green when thresholds pass\n\n1. Optionally force a controlled failure one more time (tighten a threshold, push, confirm red, then revert). This is the moment the team can trust the gate: green means within budget, red means stop and investigate.\n\n1. Save a link to a successful run in your team's runbook or Definition of Done notes. From here, performance is no longer \"run it when you remember.\" It's a pipeline dependency.\n\nIn the next milestone, you stream results to Grafana Cloud k6 so automated runs persist beyond CI log retention." } ] } diff --git a/automate-k6-cicd-lj/stream-results-cloud/content.json b/automate-k6-cicd-lj/stream-results-cloud/content.json index ba6014fe..c3d7b83a 100644 --- a/automate-k6-cicd-lj/stream-results-cloud/content.json +++ b/automate-k6-cicd-lj/stream-results-cloud/content.json @@ -47,7 +47,7 @@ }, { "type": "interactive", - "content": "Under **Access**, click **Stack ID**, then copy the ID to a temporary location for later use.\n\nIn k6 v1.6.0 and later, you can pass this value with K6_CLOUD_STACK_ID or options.cloud.stackID. Stack information is optional today, but Grafana recommends setting it now because future k6 versions will require it. Skip this step only if you are not ready to set stack information yet. For how to pass the value, refer to [Use the CLI](https://grafana.com/docs/grafana-cloud/testing/k6/author-run/use-the-cli/).", + "content": "Under **Access**, click **Stack ID**, then copy the ID to a temporary location for later use.\n\nPass this value with `K6_CLOUD_STACK_ID` or `options.cloud.stackID` (available in k6 v1.6.0 and later). k6 v2 requires stack information for cloud commands, and `grafana/k6:latest` may already be v2, so set it in your CI secrets now. For how to pass the value, refer to [Use the CLI](https://grafana.com/docs/grafana-cloud/testing/k6/author-run/use-the-cli/).", "requirements": [ "exists-reftarget", "on-page:/a/k6-app/settings" @@ -83,7 +83,7 @@ }, { "type": "markdown", - "content": "You now have the Cloud credentials to store as CI secrets." + "content": "You now have the Grafana Cloud credentials to store as CI secrets." }, { "type": "markdown", @@ -91,23 +91,23 @@ }, { "type": "markdown", - "content": "Add secrets in your CI platform:\n\n- GitHub Actions: **Settings** > **Secrets and variables** > **Actions** > **New repository secret**. Create `K6_CLOUD_TOKEN` and `K6_CLOUD_PROJECT_ID`.\n- GitLab CI: **Settings** > **CI/CD** > **Variables**. Add the same names and mark `K6_CLOUD_TOKEN` as **Masked**." + "content": "Add secrets in your CI platform:\n\n- GitHub Actions: **Settings** > **Secrets and variables** > **Actions** > **New repository secret**. Create `K6_CLOUD_TOKEN`, `K6_CLOUD_PROJECT_ID`, and `K6_CLOUD_STACK_ID`.\n- GitLab CI: **Settings** > **CI/CD** > **Variables**. Add the same names and mark `K6_CLOUD_TOKEN` as **Masked**." }, { "type": "markdown", - "content": "Update your GitHub Actions job to pass the cloud environment variables. With `grafana/run-k6-action`, providing `K6_CLOUD_TOKEN` and `K6_CLOUD_PROJECT_ID` streams results by default (local execution with cloud output):\n\n```yaml\n- name: Setup k6\n uses: grafana/setup-k6-action@v1\n\n- name: Run k6 test\n uses: grafana/run-k6-action@v1\n env:\n K6_CLOUD_TOKEN: ${{ secrets.K6_CLOUD_TOKEN }}\n K6_CLOUD_PROJECT_ID: ${{ secrets.K6_CLOUD_PROJECT_ID }}\n with:\n path: tests/performance/test.js\n flags: --env BASE_URL=https://staging.example.com\n```\n\nReplace `https://staging.example.com` with your environment URL. For k6 v2+, you may also need stack information via `K6_CLOUD_STACK_ID` or `options.cloud.stackID` in the script. Refer to [Authenticate on the CLI](https://grafana.com/docs/grafana-cloud/testing/k6/author-run/tokens-and-cli-authentication/) and your action logs if authentication fails." + "content": "Update your GitHub Actions job to pass the cloud environment variables. With `grafana/run-k6-action`, providing `K6_CLOUD_TOKEN` and `K6_CLOUD_PROJECT_ID` streams results by default (local execution with cloud output). Include `K6_CLOUD_STACK_ID` so the job works with k6 v2:\n\n```yaml\n- name: Setup k6\n uses: grafana/setup-k6-action@v1\n\n- name: Run k6 test\n uses: grafana/run-k6-action@v1\n env:\n K6_CLOUD_TOKEN: ${{ secrets.K6_CLOUD_TOKEN }}\n K6_CLOUD_PROJECT_ID: ${{ secrets.K6_CLOUD_PROJECT_ID }}\n K6_CLOUD_STACK_ID: ${{ secrets.K6_CLOUD_STACK_ID }}\n with:\n path: tests/performance/test.js\n flags: --env BASE_URL=https://staging.example.com\n```\n\nReplace `https://staging.example.com` with your environment URL. If authentication fails, re-check the three secrets. Refer to [Authenticate on the CLI](https://grafana.com/docs/grafana-cloud/testing/k6/author-run/tokens-and-cli-authentication/)." }, { "type": "markdown", - "content": "For GitLab CI (or any Docker-based runner), authenticate with the token and stream with `k6 cloud run --local-execution`:\n\n```yaml\nperformance-test:\n image:\n name: grafana/k6:latest\n entrypoint: ['']\n stage: test\n variables:\n K6_CLOUD_TOKEN: $K6_CLOUD_TOKEN\n K6_CLOUD_PROJECT_ID: $K6_CLOUD_PROJECT_ID\n script:\n - k6 cloud run --local-execution -e BASE_URL=https://staging.example.com tests/performance/test.js\n```\n\nReplace the sample `BASE_URL` with your environment URL." + "content": "For GitLab CI (or any Docker-based runner), authenticate with the token and stream with `k6 cloud run --local-execution`. Include `K6_CLOUD_STACK_ID` because `grafana/k6:latest` may be k6 v2, which requires stack information:\n\n```yaml\nperformance-test:\n image:\n name: grafana/k6:latest\n entrypoint: ['']\n stage: test\n variables:\n K6_CLOUD_TOKEN: $K6_CLOUD_TOKEN\n K6_CLOUD_PROJECT_ID: $K6_CLOUD_PROJECT_ID\n K6_CLOUD_STACK_ID: $K6_CLOUD_STACK_ID\n script:\n - k6 cloud run --local-execution -e BASE_URL=https://staging.example.com tests/performance/test.js\n```\n\nReplace the sample `BASE_URL` with your environment URL." }, { "type": "markdown", - "content": "Push the updated configuration and open the new pipeline run. In the job logs, k6 prints a cloud URL for the test run.\n\nOpen that URL, or in Grafana Cloud go to **Testing & synthetics** > **Performance**, and confirm the run appears with latency, error rate, and throughput metrics.\n\nIf the job fails with an auth error, re-check `K6_CLOUD_TOKEN`, `K6_CLOUD_PROJECT_ID`, and (for k6 v2+) `K6_CLOUD_STACK_ID`.\n\n> **Note:** Streaming results consumes Grafana Cloud k6 usage (VUH or test runs) according to your plan. Refer to [Grafana Cloud k6](https://grafana.com/docs/k6/latest/results-output/real-time/cloud/) for streaming vs cloud execution modes.\n\nYou've moved k6 from a local laptop tool to a team dependency in CI/CD, with shared results in Grafana Cloud." + "content": "Push the updated configuration and open the new pipeline run. In the job logs, k6 prints a cloud URL for the test run.\n\nOpen that URL, or in Grafana Cloud go to **Testing & synthetics** > **Performance**, and confirm the run appears with latency, error rate, and throughput metrics.\n\nIf the job fails with an auth error, re-check `K6_CLOUD_TOKEN`, `K6_CLOUD_PROJECT_ID`, and `K6_CLOUD_STACK_ID`.\n\n> **Note:** Streaming results consumes Grafana Cloud k6 usage (VUH or test runs) according to your plan. Refer to [Grafana Cloud k6](https://grafana.com/docs/k6/latest/results-output/real-time/cloud/) for streaming vs cloud execution modes.\n\nYou've moved k6 from a local laptop tool to a team dependency in CI/CD, with shared results in Grafana Cloud." }, { "type": "markdown", - "content": "In the next milestone, you wrap up and see where to go next for operationalizing gates and expanding coverage." + "content": "In the next milestone, you wrap up and choose where to go next for operationalizing gates and expanding coverage." } ] } diff --git a/automate-k6-cicd-lj/understand-performance-gates/content.json b/automate-k6-cicd-lj/understand-performance-gates/content.json index b422deea..e0aa1ab1 100644 --- a/automate-k6-cicd-lj/understand-performance-gates/content.json +++ b/automate-k6-cicd-lj/understand-performance-gates/content.json @@ -4,7 +4,7 @@ "blocks": [ { "type": "markdown", - "content": "When you run k6 manually, performance testing happens only when someone remembers to do it. Tests run on local machines against whatever environment is convenient, results live in terminal output or scattered dashboards, and there's no mechanism to prevent a slow release from reaching production. Manual testing gives you information. It doesn't give you enforcement.\n\nA CI/CD performance gate changes this. A performance gate is a k6 test that runs automatically as a pipeline step. It uses [thresholds](https://grafana.com/docs/k6/latest/using-k6/thresholds/) \u2014 the same thresholds you define in your k6 script \u2014 to produce a pass or fail result. When all thresholds pass, k6 exits with code `0` and the pipeline continues. When any threshold is breached, k6 exits with a non-zero exit code, and the pipeline treats this as a job failure. The merge or deploy can be blocked.\n\nPerformance gates provide the following advantages:\n\n- **Consistent enforcement** \u2014 Every deploy is tested against the same performance criteria, regardless of who triggered it or when.\n- **Shift-left feedback** \u2014 Developers discover performance regressions in their pull request or staging deploy, not after a production incident.\n- **Automated decision-making** \u2014 The pipeline decides whether performance is acceptable based on thresholds, removing ad-hoc judgment from the deploy process.\n- **Regression prevention** \u2014 A change that degrades response times or increases error rates is caught before it reaches users.\n- **Audit trail** \u2014 Every test run is recorded, creating a history of performance across deploys that you can use for trend analysis.\n\nThe two technical enablers that make this work are exit codes and environment parameterization. Exit codes let the pipeline act on test results. Environment parameterization lets the same script run in dev, staging, and production without code changes. You'll work with both throughout this path.\n\nFor broader planning guidance (which tests to automate, which environments, and how often), refer to [Automated performance testing](https://grafana.com/docs/k6/latest/testing-guides/automated-performance-testing/).\n\nIn the next milestone, you verify that your k6 thresholds are ready to function as pipeline gates." + "content": "When you run k6 manually, performance testing happens only when someone remembers to do it. Tests run on local machines against whatever environment is convenient, results live in terminal output or scattered dashboards, and there's no mechanism to prevent a slow release from reaching production. Manual testing gives you information. It doesn't give you enforcement.\n\nA CI/CD performance gate changes this. A performance gate is a k6 test that runs automatically as a pipeline step. It uses [thresholds](https://grafana.com/docs/k6/latest/using-k6/thresholds/), the same thresholds you define in your k6 script, to produce a pass or fail result. When all thresholds pass, k6 exits with code `0` and the pipeline continues. When any threshold is breached, k6 exits with a non-zero exit code, and the pipeline treats this as a job failure. The merge or deploy can be blocked.\n\nPerformance gates provide the following advantages:\n\n- **Consistent enforcement**: Every deploy is tested against the same performance criteria, regardless of who triggered it or when.\n- **Shift-left feedback**: Developers discover performance regressions in their pull request or staging deploy, not after a production incident.\n- **Automated decision-making**: The pipeline decides whether performance is acceptable based on thresholds, removing ad-hoc judgment from the deploy process.\n- **Regression prevention**: A change that degrades response times or increases error rates is caught before it reaches users.\n- **Audit trail**: Every test run is recorded, creating a history of performance across deploys that you can use for trend analysis.\n\nThe two technical enablers that make this work are exit codes and environment parameterization. Exit codes let the pipeline act on test results. Environment parameterization lets the same script run in dev, staging, and production without code changes. You'll work with both throughout this path.\n\nFor broader planning guidance (which tests to automate, which environments, and how often), refer to [Automated performance testing](https://grafana.com/docs/k6/latest/testing-guides/automated-performance-testing/).\n\nIn the next milestone, you verify that your k6 thresholds are ready to function as pipeline gates." } ] } From b6dfb12c256d7a3a3037e4fce5a49d675364c5d5 Mon Sep 17 00:00:00 2001 From: bonnywelsford-source Date: Tue, 28 Jul 2026 11:25:45 -0400 Subject: [PATCH 2/3] Tighten Stack ID and destination copy for Writers' Toolkit. Split long sentences and replace jargon so the polish PR reads closer to Grafana style guidance. Co-authored-by: Cursor --- automate-k6-cicd-lj/end-journey/content.json | 2 +- automate-k6-cicd-lj/stream-results-cloud/content.json | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/automate-k6-cicd-lj/end-journey/content.json b/automate-k6-cicd-lj/end-journey/content.json index 00527eeb..408b5935 100644 --- a/automate-k6-cicd-lj/end-journey/content.json +++ b/automate-k6-cicd-lj/end-journey/content.json @@ -4,7 +4,7 @@ "blocks": [ { "type": "markdown", - "content": "Congratulations on completing this learning path! Job well done!\n\nYou've accomplished the following:\n\n- Learned what CI/CD performance gates are and how exit codes turn k6 thresholds into automated deploy decisions\n- Verified that your k6 thresholds produce the correct exit codes for pipeline integration\n- Parameterized your script with `__ENV` variables so a single script runs against multiple environments\n- Added k6 as an automated step in GitHub Actions or GitLab CI\n- Configured your pipeline to treat k6 threshold breaches as build failures that block merges and deployments\n- Streamed automated test results to Grafana Cloud k6 for persistent storage and team visibility\n\n### What's next\n\nk6 is now in the daily workflow. Next you can operationalize the gate further with environment-specific thresholds, regression tracking, and failure notifications, and expand coverage to browser tests and Core Web Vitals for full-stack teams." + "content": "Congratulations on completing this learning path! Job well done!\n\nYou've accomplished the following:\n\n- Learned what CI/CD performance gates are and how exit codes turn k6 thresholds into automated deploy decisions\n- Verified that your k6 thresholds produce the correct exit codes for pipeline integration\n- Parameterized your script with `__ENV` variables so a single script runs against multiple environments\n- Added k6 as an automated step in GitHub Actions or GitLab CI\n- Configured your pipeline to treat k6 threshold breaches as build failures that block merges and deployments\n- Streamed automated test results to Grafana Cloud k6 for persistent storage and team visibility\n\n### What's next\n\nk6 is now in the daily workflow. Next, you can extend the gate with environment-specific thresholds, regression tracking, and failure notifications. You can also expand coverage to browser tests and Core Web Vitals." } ] } diff --git a/automate-k6-cicd-lj/stream-results-cloud/content.json b/automate-k6-cicd-lj/stream-results-cloud/content.json index c3d7b83a..a0ce92fb 100644 --- a/automate-k6-cicd-lj/stream-results-cloud/content.json +++ b/automate-k6-cicd-lj/stream-results-cloud/content.json @@ -47,7 +47,7 @@ }, { "type": "interactive", - "content": "Under **Access**, click **Stack ID**, then copy the ID to a temporary location for later use.\n\nPass this value with `K6_CLOUD_STACK_ID` or `options.cloud.stackID` (available in k6 v1.6.0 and later). k6 v2 requires stack information for cloud commands, and `grafana/k6:latest` may already be v2, so set it in your CI secrets now. For how to pass the value, refer to [Use the CLI](https://grafana.com/docs/grafana-cloud/testing/k6/author-run/use-the-cli/).", + "content": "Under **Access**, click **Stack ID**, then copy the ID to a temporary location for later use.\n\nPass this value with `K6_CLOUD_STACK_ID` or `options.cloud.stackID` (available in k6 v1.6.0 and later). k6 v2 requires stack information for cloud commands. `grafana/k6:latest` may already be v2, so set the Stack ID in your CI secrets now. For how to pass the value, refer to [Use the CLI](https://grafana.com/docs/grafana-cloud/testing/k6/author-run/use-the-cli/).", "requirements": [ "exists-reftarget", "on-page:/a/k6-app/settings" @@ -99,7 +99,7 @@ }, { "type": "markdown", - "content": "For GitLab CI (or any Docker-based runner), authenticate with the token and stream with `k6 cloud run --local-execution`. Include `K6_CLOUD_STACK_ID` because `grafana/k6:latest` may be k6 v2, which requires stack information:\n\n```yaml\nperformance-test:\n image:\n name: grafana/k6:latest\n entrypoint: ['']\n stage: test\n variables:\n K6_CLOUD_TOKEN: $K6_CLOUD_TOKEN\n K6_CLOUD_PROJECT_ID: $K6_CLOUD_PROJECT_ID\n K6_CLOUD_STACK_ID: $K6_CLOUD_STACK_ID\n script:\n - k6 cloud run --local-execution -e BASE_URL=https://staging.example.com tests/performance/test.js\n```\n\nReplace the sample `BASE_URL` with your environment URL." + "content": "For GitLab CI or any Docker-based runner, authenticate with the token and stream with `k6 cloud run --local-execution`. Include `K6_CLOUD_STACK_ID` because `grafana/k6:latest` may be k6 v2:\n\n```yaml\nperformance-test:\n image:\n name: grafana/k6:latest\n entrypoint: ['']\n stage: test\n variables:\n K6_CLOUD_TOKEN: $K6_CLOUD_TOKEN\n K6_CLOUD_PROJECT_ID: $K6_CLOUD_PROJECT_ID\n K6_CLOUD_STACK_ID: $K6_CLOUD_STACK_ID\n script:\n - k6 cloud run --local-execution -e BASE_URL=https://staging.example.com tests/performance/test.js\n```\n\nReplace the sample `BASE_URL` with your environment URL." }, { "type": "markdown", From 726ede7d75562625d446481498d4249919ae122d Mon Sep 17 00:00:00 2001 From: bonnywelsford-source Date: Tue, 28 Jul 2026 12:00:41 -0400 Subject: [PATCH 3/3] Simplify stream-results-cloud credential steps after Block Editor testing. Shorten the Stack ID copy, and make Project ID markdown-only so Show me does not highlight the guide step. Co-authored-by: Cursor --- .../stream-results-cloud/content.json | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/automate-k6-cicd-lj/stream-results-cloud/content.json b/automate-k6-cicd-lj/stream-results-cloud/content.json index a0ce92fb..a532af1c 100644 --- a/automate-k6-cicd-lj/stream-results-cloud/content.json +++ b/automate-k6-cicd-lj/stream-results-cloud/content.json @@ -47,7 +47,7 @@ }, { "type": "interactive", - "content": "Under **Access**, click **Stack ID**, then copy the ID to a temporary location for later use.\n\nPass this value with `K6_CLOUD_STACK_ID` or `options.cloud.stackID` (available in k6 v1.6.0 and later). k6 v2 requires stack information for cloud commands. `grafana/k6:latest` may already be v2, so set the Stack ID in your CI secrets now. For how to pass the value, refer to [Use the CLI](https://grafana.com/docs/grafana-cloud/testing/k6/author-run/use-the-cli/).", + "content": "Under **Access**, click **Stack ID**, then copy the ID to a temporary location for later use.", "requirements": [ "exists-reftarget", "on-page:/a/k6-app/settings" @@ -66,18 +66,7 @@ }, { "type": "markdown", - "content": "Open the project you want to use for CI runs.\n\nThe project ID is on the project overview, under the project name, not on this list." - }, - { - "type": "interactive", - "content": "Under the project name, find **Project id**, then copy it to a temporary location for later use.\n\nYou'll store it as a CI secret with your token in the next part of this milestone. For token details, refer to [Authenticate on the CLI](https://grafana.com/docs/grafana-cloud/testing/k6/author-run/tokens-and-cli-authentication/).", - "requirements": [ - "exists-reftarget", - "on-page:/a/k6-app/projects" - ], - "reftarget": "div:has(> button [data-testid='icon-clipboard-alt'])", - "action": "highlight", - "skippable": true + "content": "Open a project, then under the project name copy **Project id**.\n\nYou'll store it as a CI secret in the next part of this milestone." } ] },