k6 v0.45.0 is here 🎉! This release includes:

- Experimental gRPC streaming support.
- Update scripts in the cloud without running tests.
- JS Metadata API.
- A lot of internal changes and bugfixes.

## Breaking changes

* [#3066](https://github.com/grafana/k6/pull/3066) k6 will warn users about metric names [incompatible with OpenTelemetry or Prometheus](https://k6.io/docs/using-k6/metrics/#metric-name-restrictions). This is planned to [become an error](https://github.com/grafana/k6/issues/3065) with v0.48.0.
* [browser#851](https://github.com/grafana/xk6-browser/pull/851) Remove existing browser namespaced metrics. These have been deprecated in favor of Web Vitals metrics.

## New features

### Experimental gRPC module with streaming support [#3107](https://github.com/grafana/k6/pull/3107)

There is a new experimental module `k6/experimental/grpc`. It is a copy of the `k6/net/grpc` module with added stream support [#2020](https://github.com/grafana/k6/issues/2020). 


<details>
<summary> Expand to see an example of the new functionality.</summary>

This example shows server streaming:

```javascript
import { Client, Stream } from 'k6/experimental/grpc';
import { sleep } from 'k6';

const COORD_FACTOR = 1e7;
// to run this sample, you need to start the grpc server first.
// to start the grpc server, run the following command in k6 repository's root:
// go run -mod=mod examples/grpc_server/*.go
// (golang should be installed)
const GRPC_ADDR = __ENV.GRPC_ADDR || '127.0.0.1:10000';
const GRPC_PROTO_PATH = __ENV.GRPC_PROTO_PATH || '../../grpc_server/route_guide.proto';

let client = new Client();

client.load([], GRPC_PROTO_PATH);

export default () => {
  client.connect(GRPC_ADDR, { plaintext: true });

  const stream = new Stream(client, 'main.FeatureExplorer/ListFeatures', null);

  stream.on('data', function (feature) {
    console.log(
      'Found feature called "' +
        feature.name +
        '" at ' +
        feature.location.latitude / COORD_FACTOR +
        ', ' +
        feature.location.longitude / COORD_FACTOR
    );
  });

  stream.on('end', function () {
    // The server has finished sending
    client.close();
    console.log('All done');
  });

  stream.on('error', function (e) {
    // An error has occurred and the stream has been closed.
    console.log('Error: ' + JSON.stringify(e));
  });

  // send a message to the server
  stream.write({
    lo: {
      latitude: 400000000,
      longitude: -750000000,
    },
    hi: {
      latitude: 420000000,
      longitude: -730000000,
    },
  });

  sleep(0.5);
};
```
</details>

You can just replace `k6/net/grpc` import with `k6/experimental/grpc` to use the new functionality. Documentation for the module is available [here](https://k6.io/docs/javascript-api/k6-experimental/grpc/).

In the future, this functionality will be moved to the `k6/net/grpc` module.

### You can now only upload a test to the cloud without running it [#3030](https://github.com/grafana/k6/pull/3030)

For [years users have wanted](https://github.com/grafana/k6-cloud-feature-requests/issues/22) to be able to update the test that is saved in the cloud but *not* run it at this exact point.

This is now possible by adding `--upload-only` when invoking `k6 cloud` as in `k6 cloud --upload-only script.js`.

This is likely going to be most useful in a CI on the actual test script project. Now that CI can just run `k6 cloud --upload-only new-version-of-script.js` on "release".

And later on that newer version will be used. For example by a [scheduled run](https://k6.io/docs/cloud/manage/scheduled-tests/). 

### Setting sample metadata API [#3037](https://github.com/grafana/k6/pull/3037)

Support for high-cardinality metrics metadata was added in v0.41.0, but it wasn't accessible from test scripts. It's now possible to set or delete metadata for the whole VU with a similar API as used for tags:
```javascript
import exec from "k6/execution";

export default () => {
  exec.vu.metrics.metadata["my_cool_id"] = "a very unique value";
  // all metrics from here on will have this metadata set
  delete exec.vu.metrics.metadata["my_cool_id"];
  // all metrics from here on will *not* have the metadata set
}
```

This also introduces the sub-object `metrics` on the `vu` object.
Apart from `metadata` it has another property `tags`. This is meant to be the new way to set tags instead of using `exec.vu.tags`. 

There are no current plans to replace `exec.vu.tags` with `exec.vu.metrics.tags`.

### UX improvements and enhancements

- [#3099](https://github.com/grafana/k6/pull/3099) replace "breached" with "crossed" in logs around thresholds. Thanks to @MattDodsonEnglish 🙇.
- [#3102](https://github.com/grafana/k6/pull/3102) Better error message when SharedArray constructor is provided with an async function. This is not supported, but the original message wasn't very clear.
- [#3089](https://github.com/grafana/k6/pull/3089) Add Software Bill of Materials (SBOM) reports to k6 releases. Thanks to @SadFaceSmith 🙇.
- [goja#510](https://github.com/dop251/goja/pull/510) `JSON.parse` will now fail with a friendlier error message.

## Bug fixes

* [browser#852](https://github.com/grafana/xk6-browser/pull/852) Fix `Locator.WaitFor` for `detached` and `hidden` states.
* [browser#859](https://github.com/grafana/xk6-browser/pull/859) Fix remote object parsing when subtype is `null`.

## Maintenance and internal improvements

- [#2991](https://github.com/grafana/k6/pull/2991) Refactor JS modules system so that is usable in tests. Which allowed enabling the tc39 tests for modules [#3040](https://github.com/grafana/k6/pull/3040).
- [#3025](https://github.com/grafana/k6/pull/3025) Internally stop referring to afero and use an internal package to do all file system interaction. That package still uses afero.
- [#3036](https://github.com/grafana/k6/pull/3036) and [#3053](https://github.com/grafana/k6/pull/3053) Add options to `scenarios` for usage by browser module. 
* [#3058](https://github.com/grafana/k6/pull/3058) fix repetitive `the`. Thank you, @cuishuang 🙇.
- [#3064](https://github.com/grafana/k6/pull/3064), [#3070](https://github.com/grafana/k6/pull/3070),  [#3075](https://github.com/grafana/k6/pull/3075) and [#3106](https://github.com/grafana/k6/pull/3106) Go dependencies updates. 
- [#3067](https://github.com/grafana/k6/pull/3067) Add method to retrieve all registered metrics.
- [#3068](https://github.com/grafana/k6/pull/3068) Add metric Sink constructor.
- [#3078](https://github.com/grafana/k6/pull/3078) Pin base Docker builder image to Alpine 3.17. Thank you, @arukiidou 🙇.
- [#3086](https://github.com/grafana/k6/pull/3086) Fix downloading `.golangci.yml` for PRs from forks. 
- [#3088](https://github.com/grafana/k6/pull/3088) Make TestDNSResolver less flaky. 
- [#3094](https://github.com/grafana/k6/pull/3094) Fix example from the run command. Thanks to @rocktwotj 🙇.
- [#3095](https://github.com/grafana/k6/pull/3095) Maintenance update of `.golangci.yml`.
- [#3103](https://github.com/grafana/k6/pull/3103) Fix lint and logical issues in `k6/data` module tests.
- [#3045](https://github.com/grafana/k6/pull/3045), [#3049](https://github.com/grafana/k6/pull/3049), [#3073](https://github.com/grafana/k6/pull/3073) and [#3044](https://github.com/grafana/k6/pull/3044) New issues are now automatically assigned to maintainers, to improve response time on issues. Both new issue and new PR assignments are now not using external actions.
- [#3109](https://github.com/grafana/k6/pull/3109) Add a way to get the cloudapi Client's base URL. Thanks to @yorugac 🙇.

## Roadmap

We're excited to share [our public roadmap](https://github.com/orgs/grafana/projects/443/views/1), outlining the upcoming features and improvements we have planned.

We hope this updated roadmap provides a clear overview of our plans for k6's future development. As always, we welcome feedback, corrections, and suggestions to make this roadmap more comprehensive, accessible, and valuable for the k6 community.

### Cloud output v2

Work on a new version of the cloud output has been ongoing over this cycle.

While functionally it is now mostly complete, we feel like more testing is still needed and some smaller issues need to be ironed out.

Over the next cycle we will be testing it internally, and in v0.46.0 it will be generally available as the default Cloud output. It will still be possible to use the current version via an option, but we plan to gradually deprecate it.

The new output has some benefits over the previous one:
- Binary (protobuf) format instead of JSON [#2963](https://github.com/grafana/k6/pull/2963)
- Samples aggregation for every metric instead of only for HTTP ones [#3071](https://github.com/grafana/k6/pull/3071)
- HDR Histogram generation for trend-type metrics [#3027](https://github.com/grafana/k6/pull/3027)

This in general makes the payload sent for tests with a lot of samples much smaller, which also in most cases has turned out to lower the CPU and memory usage.

 Other related PRs: [#3041](https://github.com/grafana/k6/pull/3041), [#3061](https://github.com/grafana/k6/pull/3061), [#3063](https://github.com/grafana/k6/pull/3063), [#3072](https://github.com/grafana/k6/pull/3072), [#3082](https://github.com/grafana/k6/pull/3082), [#3083](https://github.com/grafana/k6/pull/3083), [#3085](https://github.com/grafana/k6/pull/3085), [#3098](https://github.com/grafana/k6/pull/3098), [#3105](https://github.com/grafana/k6/pull/3105)
