Skip to content

cloud: drop the run flags from k6 cloud help - #6208

Merged
joanlopez merged 8 commits into
masterfrom
fix-cloud-help
Jul 30, 2026
Merged

joanlopez merged 8 commits into
masterfrom
fix-cloud-help

Conversation

@dgzlopes

@dgzlopes dgzlopes commented Jul 24, 2026 •

Copy link
Copy Markdown
Member

What?

This PR drops the run flags (e.g. --vus) from the k6 cloud help command

Why?

Before, users could run k6 cloud script.js, but we deprecated this feature in k6 v2.

Behavior change

Previously, k6 cloud --vus 10 script.js accepted the run flags, printed the help text and exited 0.

Now it fails loudly with unknown flag: --vus and a non-zero exit code.

Users should use k6 cloud run --vus 10 script.js instead.

Checklist

  • I have performed a self-review of my code.
  • I have commented on my code, particularly in hard-to-understand areas.
  • I have added tests for my changes.
  • I have run linter and tests locally (make check) and all pass.

Checklist: Documentation (only for k6 maintainers and if relevant)

Please do not merge this PR until the following items are filled out.

  • I have added the correct milestone and labels to the PR.
  • I have updated the release notes: link
  • I have updated or added an issue to the k6-documentation: grafana/k6-docs#NUMBER if applicable
  • I have updated or added an issue to the TypeScript definitions: grafana/k6-DefinitelyTyped#NUMBER if applicable

Related PR(s)/Issue(s)

`k6 cloud` is a command group whose RunE only prints help, but it also
registered the full test execution flag set (`optionFlagSet` plus
`runtimeOptionFlagSet`, `--exit-on-running` and `--show-logs`). Those ~40
flags were parsed and discarded, so `k6 cloud --vus 50 script.js` silently
printed help instead of running anything, and `k6 cloud --help` was 90
lines of flags that do nothing. They belong to `k6 cloud run`, which builds
its own flag set. The registration is a leftover from when `k6 cloud
script.js` was the way to run a cloud test.

`k6 cloud --help` is now 29 lines, and an execution flag on the group is
rejected with "unknown flag" rather than being ignored.

TestConfigConsolidation exercised its cases against `k6 cloud`, relying on
those flags being present; it now uses `k6 cloud run`, the command that
actually owns them.
@dgzlopes
dgzlopes temporarily deployed to azure-trusted-signing July 24, 2026 22:31 — with GitHub Actions Inactive
@dgzlopes
dgzlopes temporarily deployed to azure-trusted-signing July 24, 2026 22:33 — with GitHub Actions Inactive
@dgzlopes
dgzlopes marked this pull request as ready for review July 24, 2026 22:36
@dgzlopes
dgzlopes requested a review from a team as a code owner July 24, 2026 22:36
@dgzlopes
dgzlopes requested review from inancgumus and janHildebrandt98 and removed request for a team July 24, 2026 22:36
@dgzlopes
dgzlopes requested a review from oleiade July 24, 2026 22:36
@dgzlopes
dgzlopes temporarily deployed to azure-trusted-signing July 24, 2026 22:42 — with GitHub Actions Inactive
@dgzlopes
dgzlopes temporarily deployed to azure-trusted-signing July 24, 2026 22:44 — with GitHub Actions Inactive
@dgzlopes
dgzlopes temporarily deployed to azure-trusted-signing July 27, 2026 13:51 — with GitHub Actions Inactive
@dgzlopes
dgzlopes temporarily deployed to azure-trusted-signing July 27, 2026 13:52 — with GitHub Actions Inactive
@dgzlopes
dgzlopes temporarily deployed to azure-trusted-signing July 28, 2026 14:13 — with GitHub Actions Inactive
@dgzlopes
dgzlopes temporarily deployed to azure-trusted-signing July 28, 2026 14:14 — with GitHub Actions Inactive

@inancgumus inancgumus left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice cleanup 👍 LGTM. Thanks for this! Some nice-to-have suggestions.

Comment thread internal/cmd/cloud.go
Comment thread internal/cmd/config_consolidation_test.go
inancgumus
inancgumus previously approved these changes Jul 28, 2026
dgzlopes added 2 commits July 29, 2026 09:47
Pins the new behavior so re-adding the run flag set to the parent
`cloud` command is caught by tests.
@dgzlopes
dgzlopes temporarily deployed to azure-trusted-signing July 29, 2026 07:54 — with GitHub Actions Inactive
@dgzlopes
dgzlopes temporarily deployed to azure-trusted-signing July 29, 2026 07:56 — with GitHub Actions Inactive
@dgzlopes
dgzlopes requested a review from inancgumus July 29, 2026 07:56
@dgzlopes
dgzlopes temporarily deployed to azure-trusted-signing July 29, 2026 08:03 — with GitHub Actions Inactive
@dgzlopes
dgzlopes temporarily deployed to azure-trusted-signing July 29, 2026 08:05 — with GitHub Actions Inactive
@dgzlopes
dgzlopes temporarily deployed to azure-trusted-signing July 30, 2026 13:02 — with GitHub Actions Inactive
@dgzlopes
dgzlopes temporarily deployed to azure-trusted-signing July 30, 2026 13:03 — with GitHub Actions Inactive
@joanlopez joanlopez added this to the v2.2.0 milestone Jul 30, 2026
@joanlopez
joanlopez merged commit 1db22ef into master Jul 30, 2026
58 checks passed
@joanlopez
joanlopez deleted the fix-cloud-help branch July 30, 2026 14:24
moko-poi added a commit to moko-poi/k6 that referenced this pull request Aug 2, 2026
Brings the branch up to date with master (5880ca9) and resolves the
overlap with the cloud changes that landed in the meantime:

- grafana#6142 added `k6 cloud load-zone`, whose constructor took the `*cmdCloud`
  this branch removes. `getCmdCloudLoadZone` now takes a `*state.GlobalState`,
  like the `project` and `test` constructors already do here.
- grafana#6208 dropped the run flag set from the parent `k6 cloud` command and pinned
  that with a test. This branch had bound those flags to throwaway values to
  keep the help output unchanged, which is now both unnecessary and wrong, so
  that block is gone.
- grafana#6171 added `--no-cloud-logs`. Its validation stays in `cmdCloudRun.preRun`,
  followed by `applyCloudEnvOverrides` instead of the parent's `preRun`.
- master's new `newCloudV6ClientFromConfig` and `cloudStackName` helpers are
  kept as they are.

No behaviour change beyond what the merged commits already do.
moko-poi added a commit to moko-poi/k6 that referenced this pull request Aug 2, 2026
The comment claimed the flag set was shared by cloud run/upload, but
cloud upload builds its own flag set without --exit-on-running and
--show-logs. Since grafana#6208 the parent cloud command no longer registers
it either, leaving cloud run as the only user.
inancgumus pushed a commit that referenced this pull request Aug 20, 2026
…6209)

* refactor(cmd): decouple cloud subcommands from the parent cmdCloud

The `k6 cloud` command no longer executes a test directly - it is a pure
coordinator that prints help and delegates to `cloud run` / `cloud upload`
/ `cloud project` / `cloud test`. Despite that, the subcommands still
reached into a shared `cmdCloud` instance to borrow its `run`, `preRun`
and `flagSet` methods, which meant the parent carried per-run flag state
(`showCloudLogs`, `exitOnRunning`, `uploadOnly`) on behalf of its
children, and `cloud upload` mutated that shared state before invoking
the parent's run method.

Replace the struct with package-level functions that take their inputs
explicitly:

  cmdCloud.preRun         -> applyCloudEnvOverrides(gs, cmd, showCloudLogs, exitOnRunning)
  cmdCloud.run            -> runCloudTest(gs, cmd, args, showCloudLogs, exitOnRunning, uploadOnly)
  cmdCloud.printTestStatus -> printCloudTestStatus(gs, status)
  cmdCloud.flagSet        -> cloudCmdFlagSet(showCloudLogs, exitOnRunning)

Each subcommand constructor now takes a *state.GlobalState instead of a
*cmdCloud, and `cloud run` owns the flag values it binds. `cloud upload`
calls runCloudTest with uploadOnly=true rather than flipping a field on a
shared object. The parent `k6 cloud` keeps advertising --show-logs and
--exit-on-running in its usage output, bound to throwaway values, so the
help text is unchanged.

No user-visible behaviour change.

* refactor(cmd): split cloud env var parsing from flag application

Review feedback on #6209: cloud upload's preRun only needs the
K6_SHOW_CLOUD_LOGS / K6_EXIT_ON_RUNNING validation half of
applyCloudEnvOverrides, since the command defines neither flag, so it
had to supply throwaway bool variables just to give the overrides
somewhere to land.

Extract parseCloudEnvOverrides, which parses and validates the two env
variables and reports each value as a nil-able pointer.
applyCloudEnvOverrides becomes a thin wrapper that applies the parsed
values unless the corresponding CLI flag was explicitly set, and cloud
upload calls the parse function directly, dropping the placeholders.

Behaviour is unchanged: same error messages, same flag-over-env
precedence, and upload keeps rejecting invalid values as before.

* refactor(cmd): group runCloudTest's flag values into an options struct

Review feedback on #6209: three positional bools in a row are easy to
mix up, and a call like runCloudTest(gs, cmd, args, false, false, true)
doesn't tell the reader which value is which.

Introduce cloudTestRunOptions so call sites name what they set:
cloud run passes {showCloudLogs, exitOnRunning} and cloud upload passes
{uploadOnly: true}.

* docs(cmd): correct which commands use cloudCmdFlagSet

The comment claimed the flag set was shared by cloud run/upload, but
cloud upload builds its own flag set without --exit-on-running and
--show-logs. Since #6208 the parent cloud command no longer registers
it either, leaving cloud run as the only user.

* test(cmd): cover cloud env var overrides and flag precedence

Review feedback on #6209: the refactoring moved the
K6_SHOW_CLOUD_LOGS / K6_EXIT_ON_RUNNING handling, but no test set
K6_EXIT_ON_RUNNING, and none set an env variable together with its
flag, so the cmd.Flags().Changed precedence was uncovered too.

Add subtests for cloud run: the env variable alone triggers
exit-on-running, an explicitly set flag wins over the env value, and an
invalid value fails the command. Also cover cloud upload, which defines
neither flag but still validates the variables.
social4hyq pushed a commit to social4hyq/homebrew-core that referenced this pull request Sep 20, 2026
k6 2.2.0

Created-by: HarmonybrewBot
Commit-by: HarmonybrewBot
Merged-by: HarmonybrewBot
Description: Created by `brew bump`

---

Created with `brew bump-formula-pr`.<details>
  <summary>release notes</summary>
  <pre>k6 `v2.2.0` is here 🎉! This release includes:

- `k6 cloud run --local-execution` now streams k6's logs to Grafana Cloud, so the test run's log view works for local execution too.
- `chromium.connectOverCDP()`, which connects browser tests to an already-running Chromium instance.
- `TextEncoder` and `TextDecoder` available as globals, and `WritableStream` support in `k6/experimental/streams`.
- A `k6 cloud load-zone list` command.
- Two new experimental feature flags: `merge-run-tags` and `freeze-env`.

## Breaking changes

There are no breaking changes in this release.

## New features

### `k6 cloud run --local-execution` streams logs to Grafana Cloud [#6171](grafana/k6#6171)

When a cloud test runs locally with `k6 cloud run --local-execution`, k6's logs now stream to the Grafana Cloud test run, so the run's log view is populated the same way it is for cloud execution. Previously, local-execution logs stayed on the machine running k6 and never reached the cloud. Work with Grafana's secrets management to safely work with secrets and redact them if they're accidentally leaked into logs are pushed. Use the new `--no-cloud-logs` flag opts out to opt out of streaming of logs when working with `--local-execution`:

```shell
k6 cloud run --local-execution script.js
k6 cloud run --local-execution --no-cloud-logs script.js
```

### Connect to a running browser with `chromium.connectOverCDP()` [#6165](grafana/k6#6165)

The browser module can now attach to an existing Chromium-based browser over the Chrome DevTools Protocol, mirroring Playwright's `browserType.connectOverCDP()`. Pass the browser's WebSocket endpoint and k6 manages the returned browser's connection — it's auto-closed at the end of the iteration, though you can call `close()` earlier to release the connection on demand.

```js
import { chromium } from 'k6/browser';

export default async function () {
  const browser = await chromium.connectOverCDP('ws://localhost:9222/devtools/browser/<id>');
  const page = await browser.newPage();

  try {
    await page.goto('https://quickpizza.grafana.com/');
  } finally {
    await page.close();
    await browser.close();
  }
}
```

Unlike the `K6_BROWSER_WS_URL` environment variable, the endpoint is a runtime value — you can, for example, request a fresh session URL from a browser provider's API in `setup()` and connect to it from the iterations.

### `TextEncoder` and `TextDecoder` globals [#6182](grafana/k6#6182)

`TextEncoder` and `TextDecoder` are now available as standard globals in both the init and VU contexts, no import required — matching how they are exposed in browsers and other JavaScript runtimes.

```js
const encoded = new TextEncoder().encode('Hello, world!');
const decoded = new TextDecoder().decode(encoded);
```

### `WritableStream` in `k6/experimental/streams` [#6132](grafana/k6#6132)

The experimental streams module now implements `WritableStream` and `WritableStreamDefaultWriter` following the WHATWG Streams specification, complementing the existing `ReadableStream` and paving the way for a future `TransformStream` implementation.

```js
import { WritableStream } from 'k6/experimental/streams';

export default async function () {
  const stream = new WritableStream({
    write(chunk) {
      console.log(`wrote ${chunk}`);
    },
  });

  const writer = stream.getWriter();
  await writer.write('hello');
  await writer.close();
}
```

### `k6 cloud load-zone list` command [#6142](grafana/k6#6142)

A new `k6 cloud load-zone list` subcommand lists the load zones — public and private — available in the configured Grafana Cloud k6 stack, mirroring the existing `k6 cloud project list` command. Output defaults to a human-readable table; pass `--json` to emit a JSON array instead.

```console
$ k6 cloud load-zone list
Load zones for https://example.grafana.net:

ID                     NAME                     TYPE      AVAILABLE
amazon:us:ashburn      Ashburn, US (Amazon)     public    yes
amazon:sa:cape town    Cape Town, SA (Amazon)   public    yes
```

### Configurable `handleSummary()` timeout [#5854](grafana/k6#5854)

The time budget for the `handleSummary()` callback — previously hardcoded to 120 seconds — is now configurable through the `handleSummaryTimeout` option or the `K6_HANDLE_SUMMARY_TIMEOUT` environment variable, so long-running tests with heavy summaries no longer fail with `handleSummary() execution timed out`. Thanks, @LBaronceli!

```js
export const options = {
  handleSummaryTimeout: '5m',
};
```

### New experimental feature flags: `merge-run-tags` and `freeze-env`

Two new experimental flags join the feature-flag system introduced in v2.1.0:

- [#5714](grafana/k6#5714) `merge-run-tags` merges run tags per key across config layers, so `options.tags` in a script is no longer silently discarded when `--tag` or `K6_TAGS` is also used — higher-priority layers win on conflicting keys instead of replacing the whole map. Thanks, @yordis!
- [#6032](grafana/k6#6032) `freeze-env` freezes the `__ENV` object, so modifications from script code throw a `TypeError` (in strict mode) instead of silently persisting across iterations and scenarios. Thanks, @lohitkolluri!

```shell
k6 run --features merge-run-tags,freeze-env script.js
```

## UX improvements and enhancements

- [#5631](grafana/k6#5631) Makes the browser module's header accessors — `response.allHeaders()`, `headerValue()`, `headerValues()`, and `headersArray()` — return the raw wire headers (including `Set-Cookie` and security-related headers), correctly paired with each hop of a redirect chain instead of Chrome's provisional headers. As part of this, `headerValues()` now matches header names case-insensitively and splits repeated values on newlines rather than commas, and the `browser_data_sent`/`browser_data_received` metrics now include the raw header bytes and no longer vary run-to-run with CDP event ordering.
- [#6208](grafana/k6#6208) Makes `k6 cloud` reject the run flags (for example, `--vus`) with an `unknown flag` error and a non-zero exit code. Previously `k6 cloud --vus 10 script.js` accepted the flags, printed the help text, and exited 0 — running tests with `k6 cloud` directly was deprecated in v2.0.0 in favor of `k6 cloud run`.
- [#6096](grafana/k6#6096) Points the cloud secrets error at `K6_CLOUD_SECRETS_TOKEN` and `K6_CLOUD_SECRETS_ENDPOINT` when a test run is reused via `K6_CLOUD_PUSH_REF_ID` under `--local-execution`, instead of suggesting the `--local-execution` flag the user is already using.
- [#6196](grafana/k6#6196) Adds `catch` blocks to the browser examples so a failing iteration reports the original error instead of a subsequent `page.close()` failure. Thanks, @locker95!

## Bug fixes

- [#6234](grafana/k6#6234) Classifies HTTP/2 errors by message so the `error_code` metric tag stays correct when k6 is built with Go 1.27 (whose `x/net/http2` delegates to the standard library), and explicitly enables HTTP/2 negotiation on VU transports.
- [#6232](grafana/k6#6232) Drains queued log entries in the Loki hook at shutdown so `--out loki` and cloud log streaming no longer lose the final batch, and emits a `k6 dropped N log messages` warning when the cloud log buffer overflows instead of dropping logs silently.
- [#6125](grafana/k6#6125) Serializes the first concurrent open of a file in the caching filesystem so parallel `fs.open()` calls on the same file no longer read zero or truncated bytes.
- [#6147](grafana/k6#6147) Fixes a data race and inconsistent request-interception state when browser routes are added or removed concurrently. Thanks, @somak2kai!
- [#6070](grafana/k6#6070) Flushes buffered file log output once per second so recent logs aren't lost when k6 is killed before shutdown. Thanks, @rohan-patnaik!
- [#6205](grafana/k6#6205) Stops sending an invalid `Sec-WebSocket-Protocol` header when tailing Grafana Cloud logs; spec-strict servers rejected the handshake with `websocket: bad handshake`.
- [#6200](grafana/k6#6200) Leaves a counter's `rate` unset when the observed duration is zero, instead of computing `+Inf` and spuriously failing `rate` thresholds. Thanks, @samarth70!
- [#6195](grafana/k6#6195) Initializes a gauge's maximum from the first sample so all-negative gauge series no longer report `max=0`. Thanks, @Solaris-star!
- [#6145](grafana/k6#6145) Prevents the OpenTelemetry output from panicking at startup when basic auth is configured without `K6_OTEL_HEADERS`. Thanks, @lukdz!
- [#6140](grafana/k6#6140) Stops `SharedArray` deep-freezing JS primitives, which needlessly wrapped large strings in `String` objects — cutting memory usage in the reported reproduction from roughly 1 GB to 100 MB.

## Maintenance and internal improvements

- [#6126](grafana/k6#6126), [#6224](grafana/k6#6224), [#6229](grafana/k6#6229) Adds anonymous extension usage to the k6 usage report: a run reports the Go module path, version, and type of registry-cataloged extensions it actually uses (imported `k6/x/` modules, output extensions selected with `--out`, and `k6 x` subcommands). Private and unlisted extensions are never reported, and the existing `--no-usage-report` opt-out covers it.
- [#6183](grafana/k6#6183), [#6218](grafana/k6#6218) Updates Sobek and regexp2, making `W

See merge request: Harmonybrew/homebrew-core!16299

This branch was previously deployed

1 inactive deployment
azure-trusted-signing — 64f1b8b3 Deployed Jul 30, 2026 by dgzlopes via sign-packages #10195
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants