From 513fe02bebd6f1e71c5ff90bde35c14bc81f098a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20SZKIBA?= Date: Thu, 4 Jul 2024 14:33:56 +0200 Subject: [PATCH 1/7] docs: added examples using xk6-faker and xk6-sql --- .gitignore | 1 + .github/CONTRIBUTING.md => CONTRIBUTING.md | 0 examples/combined.js | 13 ++++++++ examples/device.js | 12 ------- examples/faker.js | 10 ++++++ examples/script.js | 11 ------- examples/sqlite.js | 24 ++++++++++++++ examples/user.js | 14 -------- script.js | 37 ++++++++++++++++++---- testdata/simple.js | 10 ------ testdata/simple/part-csv.js | 1 - testdata/simple/part-yaml.js | 1 - testdata/simple/parts.js | 4 --- 13 files changed, 79 insertions(+), 59 deletions(-) rename .github/CONTRIBUTING.md => CONTRIBUTING.md (100%) create mode 100644 examples/combined.js delete mode 100644 examples/device.js create mode 100644 examples/faker.js delete mode 100644 examples/script.js create mode 100644 examples/sqlite.js delete mode 100644 examples/user.js delete mode 100644 testdata/simple.js delete mode 100644 testdata/simple/part-csv.js delete mode 100644 testdata/simple/part-yaml.js delete mode 100644 testdata/simple/parts.js diff --git a/.gitignore b/.gitignore index 7334a4e..2687014 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ /k6x.exe /k6 /k6.exe +/test*.db diff --git a/.github/CONTRIBUTING.md b/CONTRIBUTING.md similarity index 100% rename from .github/CONTRIBUTING.md rename to CONTRIBUTING.md diff --git a/examples/combined.js b/examples/combined.js new file mode 100644 index 0000000..9703b4b --- /dev/null +++ b/examples/combined.js @@ -0,0 +1,13 @@ +"use k6 >= 0.50"; +"use k6 with k6/x/faker >= 0.3.0"; +"use k6 with k6/x/sql >= 0.4.0"; + +import faker from "./faker.js"; +import sqlite from "./sqlite.js"; + +export { setup, teardown } from "./sqlite.js"; + +export default () => { + faker(); + sqlite(); +}; diff --git a/examples/device.js b/examples/device.js deleted file mode 100644 index 3d1116c..0000000 --- a/examples/device.js +++ /dev/null @@ -1,12 +0,0 @@ -import { parse } from "k6/x/yaml"; - -const source = ` -- name: foo -- name: bar -`; - -const devices = parse(source); - -export function getDevice() { - return devices[0]; -} diff --git a/examples/faker.js b/examples/faker.js new file mode 100644 index 0000000..4f38927 --- /dev/null +++ b/examples/faker.js @@ -0,0 +1,10 @@ +// source: https://github.com/szkiba/xk6-faker/blob/v0.3.0/examples/custom-faker.js +import { Faker } from "k6/x/faker"; + +const faker = new Faker(11); + +export default function () { + console.log(faker.person.firstName()); +} + +// output: Josiah diff --git a/examples/script.js b/examples/script.js deleted file mode 100644 index fbe4595..0000000 --- a/examples/script.js +++ /dev/null @@ -1,11 +0,0 @@ -"use k6 >= 0.49"; -"use k6 with k6/x/faker >= 0.2.0"; - -import { newUser } from "./user.js"; -import { getDevice } from "./device.js"; - -export default () => { - const user = newUser("John"); - console.log(user); - console.log(getDevice()); -}; diff --git a/examples/sqlite.js b/examples/sqlite.js new file mode 100644 index 0000000..c17f93e --- /dev/null +++ b/examples/sqlite.js @@ -0,0 +1,24 @@ +// source: https://github.com/grafana/xk6-sql/blob/v0.4.0/examples/sqlite3_test.js +import sql from "k6/x/sql"; + +const db = sql.open("sqlite3", "./test.db"); + +export function setup() { + db.exec(`CREATE TABLE IF NOT EXISTS keyvalues ( + id integer PRIMARY KEY AUTOINCREMENT, + key varchar NOT NULL, + value varchar);`); +} + +export function teardown() { + db.close(); +} + +export default function () { + db.exec("INSERT INTO keyvalues (key, value) VALUES('plugin-name', 'k6-plugin-sql');"); + + let results = sql.query(db, "SELECT * FROM keyvalues WHERE key = $1;", "plugin-name"); + for (const row of results) { + console.log(`key: ${row.key}, value: ${row.value}`); + } +} diff --git a/examples/user.js b/examples/user.js deleted file mode 100644 index 7f48a41..0000000 --- a/examples/user.js +++ /dev/null @@ -1,14 +0,0 @@ -import "k6/x/faker"; - -class UserAccount { - constructor(name) { - this.name = name; - this.id = Math.floor(Math.random() * Number.MAX_SAFE_INTEGER); - } -} - -function newUser(name) { - return new UserAccount(name); -} - -export { newUser }; diff --git a/script.js b/script.js index 75b798e..d1eca9f 100644 --- a/script.js +++ b/script.js @@ -1,11 +1,36 @@ -"use k6 >= v0.50"; -"use k6 with k6/x/faker >= 0.3"; +import { Faker } from "k6/x/faker"; +import sql from "k6/x/sql"; -import http from "k6/http"; -import faker from "k6/x/faker"; +const db = sql.open("sqlite3", "./test-users.db"); + +export function setup() { + db.exec(` + CREATE TABLE IF NOT EXISTS users ( + sub varchar PRIMARY KEY, + name varchar NOT NULL, + email varchar NOT NULL + );`); + + const faker = new Faker(11); + + db.exec(` + INSERT OR REPLACE INTO users (sub, name, email) VALUES ( + '${faker.internet.username()}', + '${faker.person.firstName()} ${faker.person.lastName()}', + '${faker.person.email()}' + );`); +} + +export function teardown() { + db.close(); +} export default function () { - const user = faker.person.name(); + const results = sql.query(db, "SELECT * FROM users"); + + for (const row of results) { + const { sub, name, email } = row; - const resp = http.post("https://httpbin.test.k6.io/post", JSON.stringify(user)); + console.log({ sub, name, email }); + } } diff --git a/testdata/simple.js b/testdata/simple.js deleted file mode 100644 index 747006c..0000000 --- a/testdata/simple.js +++ /dev/null @@ -1,10 +0,0 @@ -"use k6 >= v0.50"; -"use k6 with k6/x/faker >= 0.3"; - -import faker from "k6/x/faker"; - -import parts from "./simple/parts.js"; - -export default function () { - let user = faker.person(); -} diff --git a/testdata/simple/part-csv.js b/testdata/simple/part-csv.js deleted file mode 100644 index c130ae6..0000000 --- a/testdata/simple/part-csv.js +++ /dev/null @@ -1 +0,0 @@ -import yaml from "k6/x/csv"; diff --git a/testdata/simple/part-yaml.js b/testdata/simple/part-yaml.js deleted file mode 100644 index aefdaf6..0000000 --- a/testdata/simple/part-yaml.js +++ /dev/null @@ -1 +0,0 @@ -import yaml from "k6/x/yaml"; diff --git a/testdata/simple/parts.js b/testdata/simple/parts.js deleted file mode 100644 index 84ed4a5..0000000 --- a/testdata/simple/parts.js +++ /dev/null @@ -1,4 +0,0 @@ -import csv from "./part-csv.js"; -import yaml from "./part-yaml.js"; - -export default function () {} From 3a2706f1d39e482a4896985490c866b802156be8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20SZKIBA?= Date: Thu, 4 Jul 2024 14:34:14 +0200 Subject: [PATCH 2/7] docs: moved to visible location --- CONTRIBUTING.md | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 13faf19..64acc21 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -72,13 +72,13 @@ For alternative ways of cloning the k6x repository, please refer to [GitHub's cl ### Tasks -This section contains a description of the tasks performed during development. Commands must be issued in the `k6x` base directory. If you have the [xc](https://github.com/joerdav/xc) command-line tool, individual tasks can be executed simply by using the `xc task-name` command in the `k6x` base directory. +This section contains a description of the tasks performed during development. Commands must be issued in the `k6x` base directory. #### readme Update documentation in README.md. -``` +```sh go run ./tools/gendoc README.md ``` @@ -88,7 +88,7 @@ Run the static analyzer. We make use of the [golangci-lint](https://github.com/golangci/golangci-lint) tool to lint the code in CI. The actual version you can find in our [`.golangci.yml`](https://github.com/grafana/k6x/blob/master/.golangci.yml#L1). -``` +```sh golangci-lint run ``` @@ -98,8 +98,7 @@ Run the tests. To exercise the entire test suite, please run the following command - -``` +```sh go test -count 1 -race -coverprofile=build/coverage.txt ./... ``` @@ -107,7 +106,7 @@ go test -count 1 -race -coverprofile=build/coverage.txt ./... View the test coverage report. -``` +```sh go tool cover -html=build/coverage.txt ``` @@ -117,7 +116,7 @@ Build the executable binary. This is the easiest way to create an executable binary (although the release process uses the goreleaser tool to create release versions). -``` +```sh go build -ldflags="-w -s" -o k6x . ``` @@ -127,7 +126,7 @@ Creating an executable binary with a snapshot version. The goreleaser command-line tool is used during the release process. During development, it is advisable to create binaries with the same tool from time to time. -``` +```sh goreleaser build --snapshot --clean --single-target -o k6x ``` @@ -137,14 +136,24 @@ Building a Docker image. Before building the image, it is advisable to perform a Requires: snapshot -``` +```sh docker build -t grafana/k6x -f Dockerfile.goreleaser . ``` +#### examples + +Run all scripts in the `examples` directory with a fresh build. + +Requires: clean, snapshot + +```sh +find examples -type f | xargs -n 1 ./k6x run +``` + #### clean Delete the build directory. -``` +```sh rm -rf build ``` From 67d9e7352b78a70e45458ba8c60faeeea3f19d2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20SZKIBA?= Date: Thu, 4 Jul 2024 14:35:21 +0200 Subject: [PATCH 3/7] docs: reorganize and improve documentation --- README.md | 239 +++++++++++++++++++++++++++++++++++++------ internal/cmd/cmd.go | 4 +- internal/cmd/help.md | 131 +++++++++++++++++++++++- main.go | 2 - tools/gendoc/main.go | 2 +- 5 files changed, 343 insertions(+), 35 deletions(-) diff --git a/README.md b/README.md index e3dbe44..9e08b1b 100644 --- a/README.md +++ b/README.md @@ -4,50 +4,159 @@ [![codecov](https://codecov.io/gh/grafana/k6x/graph/badge.svg?token=nQA0QAF85R)](https://codecov.io/gh/grafana/k6x) ![GitHub Downloads](https://img.shields.io/github/downloads/grafana/k6x/total) -

k6x

- > [!Important] > The k6x is under refactor. This documentation is about the refactored code. Previous documentation is marked with the [before-grafana](https://github.com/grafana/k6x/tree/before-grafana) git tag. The last release before the refactor is [v0.4.0](https://github.com/grafana/k6x/releases/tag/v0.4.0). -**Run k6 with extensions** + +# k6x -k6x is a [k6](https://k6.io) launcher that automatically provides k6 with the [extensions](https://k6.io/docs/extensions/) used by the test. In order to do this, it analyzes the script arguments of the `run` and `archive` subcommands, detects the extensions to be used and their version constraints. +Run k6 with extensions -## Install +## Synopsis -Precompiled binaries can be downloaded and installed from the [Releases](https://github.com/grafana/k6x/releases) page. +Run k6 with a seamless extension user experience. -If you have a go development environment, the installation can also be done with the following command: +`k6x` is a [k6] launcher that automatically provides [k6] with the [extensions] used by the test. In order to do this, it analyzes the script arguments of the `run` and `archive` subcommands, detects the extensions to be used and their version constraints. + +The launcher acts as a drop-in replacement for the `k6` command. For more convenient use, it is advisable to create an alias or shell script called `k6` for the launcher. The alias can be used in exactly the same way as the `k6` command, with the difference that it generates the real `k6` on the fly based on the extensions you want to use. + +The launcher will always run the k6 test script with the appropriate k6 binary, which contains the extensions used by the script. In order to do this, it analyzes the script arguments of the "run" and "archive" subcommands, detects the extensions to be used and their version constraints. + +Any k6 command can be used. Use the `help` command to list the available k6 commands. + +Any number of `"use k6"` pragmas can be used. +### Pragma + +Version constraints can be specified using the JavaScript `"use ..."` pragma syntax for k6 and extensions. Put the following lines at the beginning of the test script: + +```js +"use k6 >= v0.52"; +"use k6 with k6/x/faker > 0.2"; ``` -go install github.com/grafana/k6x@latest + +> **Note** +> The use of pragmas is completely optional for JavaScript type extensions, it is only necessary if you want to specify version constraints. + +The pragma syntax can also be used to specify an extension dependency that is not referenced in an import expression. A typical example of this is the Output type extension such as [xk6-top]: + +```js +"use k6 with top >= 0.1"; ``` -The launcher acts as a drop-in replacement for the k6 command. For more convenient use, it is advisable to create an alias or shell script called k6 for the launcher. The alias can be used in exactly the same way as the k6 command, with the difference that it generates the real k6 on the fly based on the extensions you want to use. +Read the version constraints syntax in the [Version Constraints](#version-constraints) section -## Usage +### Environment - -## k6x +The extensions to be used and optionally their version constraints can also be specified in the `K6_DEPENDENCIES` environment variable. The value of the `K6_DEPENDENCIES` environment variable is a comma-separated list of elements. Each element specifies an extension (or k6 itself) and optionally its version constraint. -Lanch k6 with extensions +``` +k6>=0.52;k6/x/faker>=0.3;k6/x/sql>=0.4 +``` -### Synopsis +### Manifest -Launch k6 with a seamless extension user experience. +The manifest file is a JSON file, the `dependencies` property of which can specify extension dependencies and version constraints. The value of the `dependencies` property is a JSON object. The property names of this object are the extension names (or k6) and the values ​​are the version constraints. -The launcher acts as a drop-in replacement for the `k6` command. For more convenient use, it is advisable to create an alias or shell script called `k6` for the launcher. The alias can be used in exactly the same way as the `k6` command, with the difference that it generates the real `k6` on the fly based on the extensions you want to use. +```json +{ + "dependencies": { + "k6": ">=0.52", + "k6/x/faker": ">=0.3", + "k6/x/sql": ">=0.4" + } +} +``` -The launcher will always run the k6 test script with the appropriate k6 binary, which contains the extensions used by the script. In order to do this, it analyzes the script arguments of the "run" and "archive" subcommands, detects the extensions to be used and their version constraints. +The manifest file is a file named `package.json`, which is located closest to the k6 test script or the current directory, depending on whether the given subcommand has a test script argument (e.g. run, archive) or not (e.g. version). The `package.json` file is searched for up to the root of the directory hierarchy. + +### Limitations + +Version constraints can be specified in several sources ([pragma](#pragma), [environment](#environment), [manifest](#manifest)) but cannot be overwritten. That is, for a given extension, the version constraints from different sources must either be equal, or only one source can contain a version constraint. + +### Version Constraints + +*This section is based on the [Masterminds/semver] documentation.* + +#### Basic Comparisons + +There are two elements to the comparisons. First, a comparison string is a list +of space or comma separated AND comparisons. These are then separated by || (OR) +comparisons. For example, `">= 1.2 < 3.0.0 || >= 4.2.3"` is looking for a +comparison that's greater than or equal to 1.2 and less than 3.0.0 or is +greater than or equal to 4.2.3. + +The basic comparisons are: + +* `=`: equal (aliased to no operator) +* `!=`: not equal +* `>`: greater than +* `<`: less than +* `>=`: greater than or equal to +* `<=`: less than or equal to + +#### Hyphen Range Comparisons + +There are multiple methods to handle ranges and the first is hyphens ranges. +These look like: + +* `1.2 - 1.4.5` which is equivalent to `>= 1.2 <= 1.4.5` +* `2.3.4 - 4.5` which is equivalent to `>= 2.3.4 <= 4.5` + +#### Wildcards In Comparisons + +The `x`, `X`, and `*` characters can be used as a wildcard character. This works +for all comparison operators. When used on the `=` operator it falls +back to the patch level comparison (see tilde below). For example, + +* `1.2.x` is equivalent to `>= 1.2.0, < 1.3.0` +* `>= 1.2.x` is equivalent to `>= 1.2.0` +* `<= 2.x` is equivalent to `< 3` +* `*` is equivalent to `>= 0.0.0` + +#### Tilde Range Comparisons (Patch) + +The tilde (`~`) comparison operator is for patch level ranges when a minor +version is specified and major level changes when the minor number is missing. +For example, + +* `~1.2.3` is equivalent to `>= 1.2.3, < 1.3.0` +* `~1` is equivalent to `>= 1, < 2` +* `~2.3` is equivalent to `>= 2.3, < 2.4` +* `~1.2.x` is equivalent to `>= 1.2.0, < 1.3.0` +* `~1.x` is equivalent to `>= 1, < 2` + +#### Caret Range Comparisons (Major) + +The caret (`^`) comparison operator is for major level changes once a stable +(1.0.0) release has occurred. Prior to a 1.0.0 release the minor versions acts +as the API stability level. This is useful when comparisons of API versions as a +major change is API breaking. For example, + +* `^1.2.3` is equivalent to `>= 1.2.3, < 2.0.0` +* `^1.2.x` is equivalent to `>= 1.2.0, < 2.0.0` +* `^2.3` is equivalent to `>= 2.3, < 3` +* `^2.x` is equivalent to `>= 2.0.0, < 3` +* `^0.2.3` is equivalent to `>=0.2.3 <0.3.0` +* `^0.2` is equivalent to `>=0.2.0 <0.3.0` +* `^0.0.3` is equivalent to `>=0.0.3 <0.0.4` +* `^0.0` is equivalent to `>=0.0.0 <0.1.0` +* `^0` is equivalent to `>=0.0.0 <1.0.0` -Any k6 command can be used. Use the `help` command to list the available k6 commands. + +**References** + +- [k6]: https://k6.io +- [extensions]: https://grafana.com/docs/k6/latest/extensions/ +- [Masterminds/semver]: https://github.com/Masterminds/semver +- [xk6-top]: https://github.com/szkiba/xk6-top ``` k6x [flags] [command] ``` -### Flags +## Flags ``` --build-service-url string URL of the k6 build service to be used @@ -61,9 +170,72 @@ k6x [flags] [command] +## Example + +```bash +k6x run script.js +``` + +That's all! + +
script.js + +```js file=script.js +import { Faker } from "k6/x/faker"; +import sql from "k6/x/sql"; + +const db = sql.open("sqlite3", "./test-users.db"); + +export function setup() { + db.exec(` + CREATE TABLE IF NOT EXISTS users ( + sub varchar PRIMARY KEY, + name varchar NOT NULL, + email varchar NOT NULL + );`); + + const faker = new Faker(11); + + db.exec(` + INSERT OR REPLACE INTO users (sub, name, email) VALUES ( + '${faker.internet.username()}', + '${faker.person.firstName()} ${faker.person.lastName()}', + '${faker.person.email()}' + );`); +} + +export function teardown() { + db.close(); +} + +export default function () { + const results = sql.query(db, "SELECT * FROM users"); + + for (const row of results) { + const { sub, name, email } = row; + + console.log({ sub, name, email }); + } +} +``` + +
+ +## Install + +Precompiled binaries can be downloaded and installed from the [Releases](https://github.com/grafana/k6x/releases) page. + +If you have a go development environment, the installation can also be done with the following command: + +``` +go install github.com/grafana/k6x@latest +``` + +The launcher acts as a drop-in replacement for the k6 command. For more convenient use, it is advisable to create an alias or shell script called k6 for the launcher. The alias can be used in exactly the same way as the k6 command, with the difference that it generates the real k6 on the fly based on the extensions you want to use. + ## Contributing -If you want to contribute, please read the [CONTRIBUTING.md](.github/CONTRIBUTING.md) file. +If you want to contribute, please read the [CONTRIBUTING.md](CONTRIBUTING.md) file. ### Tasks @@ -75,7 +247,7 @@ This section contains a description of the tasks performed during development. C Update documentation in README.md. -``` +```sh go run ./tools/gendoc README.md ``` @@ -85,7 +257,7 @@ Run the static analyzer. We make use of the [golangci-lint](https://github.com/golangci/golangci-lint) tool to lint the code in CI. The actual version you can find in our [`.golangci.yml`](https://github.com/grafana/k6x/blob/master/.golangci.yml#L1). -``` +```sh golangci-lint run ``` @@ -95,8 +267,7 @@ Run the tests. To exercise the entire test suite, please run the following command - -``` +```sh go test -count 1 -race -coverprofile=build/coverage.txt ./... ``` @@ -104,7 +275,7 @@ go test -count 1 -race -coverprofile=build/coverage.txt ./... View the test coverage report. -``` +```sh go tool cover -html=build/coverage.txt ``` @@ -114,7 +285,7 @@ Build the executable binary. This is the easiest way to create an executable binary (although the release process uses the goreleaser tool to create release versions). -``` +```sh go build -ldflags="-w -s" -o k6x . ``` @@ -124,7 +295,7 @@ Creating an executable binary with a snapshot version. The goreleaser command-line tool is used during the release process. During development, it is advisable to create binaries with the same tool from time to time. -``` +```sh goreleaser build --snapshot --clean --single-target -o k6x ``` @@ -134,15 +305,25 @@ Building a Docker image. Before building the image, it is advisable to perform a Requires: snapshot -``` +```sh docker build -t grafana/k6x -f Dockerfile.goreleaser . ``` +#### examples + +Run all scripts in the `examples` directory with a fresh build. + +Requires: clean, snapshot + +```sh +find examples -type f | xargs -n 1 ./k6x run +``` + #### clean Delete the build directory. -``` +```sh rm -rf build ``` diff --git a/internal/cmd/cmd.go b/internal/cmd/cmd.go index 66a2bdc..a0f49c6 100644 --- a/internal/cmd/cmd.go +++ b/internal/cmd/cmd.go @@ -16,8 +16,8 @@ func New(levelVar *slog.LevelVar) *cobra.Command { state := newState(levelVar) root := &cobra.Command{ - Use: "exec [flags] [command]", - Short: "Lanch k6 with extensions", + Use: "k6x [flags] [command]", + Short: "Run k6 with extensions", Long: help, SilenceUsage: true, SilenceErrors: true, diff --git a/internal/cmd/help.md b/internal/cmd/help.md index 38c23d1..86541b9 100644 --- a/internal/cmd/help.md +++ b/internal/cmd/help.md @@ -1,7 +1,136 @@ -Launch k6 with a seamless extension user experience. +Run k6 with a seamless extension user experience. + +`k6x` is a [k6] launcher that automatically provides [k6] with the [extensions] used by the test. In order to do this, it analyzes the script arguments of the `run` and `archive` subcommands, detects the extensions to be used and their version constraints. The launcher acts as a drop-in replacement for the `k6` command. For more convenient use, it is advisable to create an alias or shell script called `k6` for the launcher. The alias can be used in exactly the same way as the `k6` command, with the difference that it generates the real `k6` on the fly based on the extensions you want to use. The launcher will always run the k6 test script with the appropriate k6 binary, which contains the extensions used by the script. In order to do this, it analyzes the script arguments of the "run" and "archive" subcommands, detects the extensions to be used and their version constraints. Any k6 command can be used. Use the `help` command to list the available k6 commands. + +Any number of `"use k6"` pragmas can be used. + +### Pragma + +Version constraints can be specified using the JavaScript `"use ..."` pragma syntax for k6 and extensions. Put the following lines at the beginning of the test script: + +```js +"use k6 >= v0.52"; +"use k6 with k6/x/faker > 0.2"; +``` + +> **Note** +> The use of pragmas is completely optional for JavaScript type extensions, it is only necessary if you want to specify version constraints. + +The pragma syntax can also be used to specify an extension dependency that is not referenced in an import expression. A typical example of this is the Output type extension such as [xk6-top]: + +```js +"use k6 with top >= 0.1"; +``` + +Read the version constraints syntax in the [Version Constraints](#version-constraints) section + +### Environment + +The extensions to be used and optionally their version constraints can also be specified in the `K6_DEPENDENCIES` environment variable. The value of the `K6_DEPENDENCIES` environment variable is a comma-separated list of elements. Each element specifies an extension (or k6 itself) and optionally its version constraint. + +``` +k6>=0.52;k6/x/faker>=0.3;k6/x/sql>=0.4 +``` + +### Manifest + +The manifest file is a JSON file, the `dependencies` property of which can specify extension dependencies and version constraints. The value of the `dependencies` property is a JSON object. The property names of this object are the extension names (or k6) and the values ​​are the version constraints. + +```json +{ + "dependencies": { + "k6": ">=0.52", + "k6/x/faker": ">=0.3", + "k6/x/sql": ">=0.4" + } +} +``` + +The manifest file is a file named `package.json`, which is located closest to the k6 test script or the current directory, depending on whether the given subcommand has a test script argument (e.g. run, archive) or not (e.g. version). The `package.json` file is searched for up to the root of the directory hierarchy. + +### Limitations + +Version constraints can be specified in several sources ([pragma](#pragma), [environment](#environment), [manifest](#manifest)) but cannot be overwritten. That is, for a given extension, the version constraints from different sources must either be equal, or only one source can contain a version constraint. + +### Version Constraints + +*This section is based on the [Masterminds/semver] documentation.* + +#### Basic Comparisons + +There are two elements to the comparisons. First, a comparison string is a list +of space or comma separated AND comparisons. These are then separated by || (OR) +comparisons. For example, `">= 1.2 < 3.0.0 || >= 4.2.3"` is looking for a +comparison that's greater than or equal to 1.2 and less than 3.0.0 or is +greater than or equal to 4.2.3. + +The basic comparisons are: + +* `=`: equal (aliased to no operator) +* `!=`: not equal +* `>`: greater than +* `<`: less than +* `>=`: greater than or equal to +* `<=`: less than or equal to + +#### Hyphen Range Comparisons + +There are multiple methods to handle ranges and the first is hyphens ranges. +These look like: + +* `1.2 - 1.4.5` which is equivalent to `>= 1.2 <= 1.4.5` +* `2.3.4 - 4.5` which is equivalent to `>= 2.3.4 <= 4.5` + +#### Wildcards In Comparisons + +The `x`, `X`, and `*` characters can be used as a wildcard character. This works +for all comparison operators. When used on the `=` operator it falls +back to the patch level comparison (see tilde below). For example, + +* `1.2.x` is equivalent to `>= 1.2.0, < 1.3.0` +* `>= 1.2.x` is equivalent to `>= 1.2.0` +* `<= 2.x` is equivalent to `< 3` +* `*` is equivalent to `>= 0.0.0` + +#### Tilde Range Comparisons (Patch) + +The tilde (`~`) comparison operator is for patch level ranges when a minor +version is specified and major level changes when the minor number is missing. +For example, + +* `~1.2.3` is equivalent to `>= 1.2.3, < 1.3.0` +* `~1` is equivalent to `>= 1, < 2` +* `~2.3` is equivalent to `>= 2.3, < 2.4` +* `~1.2.x` is equivalent to `>= 1.2.0, < 1.3.0` +* `~1.x` is equivalent to `>= 1, < 2` + +#### Caret Range Comparisons (Major) + +The caret (`^`) comparison operator is for major level changes once a stable +(1.0.0) release has occurred. Prior to a 1.0.0 release the minor versions acts +as the API stability level. This is useful when comparisons of API versions as a +major change is API breaking. For example, + +* `^1.2.3` is equivalent to `>= 1.2.3, < 2.0.0` +* `^1.2.x` is equivalent to `>= 1.2.0, < 2.0.0` +* `^2.3` is equivalent to `>= 2.3, < 3` +* `^2.x` is equivalent to `>= 2.0.0, < 3` +* `^0.2.3` is equivalent to `>=0.2.3 <0.3.0` +* `^0.2` is equivalent to `>=0.2.0 <0.3.0` +* `^0.0.3` is equivalent to `>=0.0.3 <0.0.4` +* `^0.0` is equivalent to `>=0.0.0 <0.1.0` +* `^0` is equivalent to `>=0.0.0 <1.0.0` + + +**References** + +- [k6]: https://k6.io +- [extensions]: https://grafana.com/docs/k6/latest/extensions/ +- [Masterminds/semver]: https://github.com/Masterminds/semver +- [xk6-top]: https://github.com/szkiba/xk6-top diff --git a/main.go b/main.go index 019633d..3bc6bf8 100644 --- a/main.go +++ b/main.go @@ -6,7 +6,6 @@ import ( "log/slog" "os" "os/signal" - "strings" "time" "github.com/briandowns/spinner" @@ -42,7 +41,6 @@ func main() { func newCmd(args []string, levelVar *slog.LevelVar) *cobra.Command { cmd := cmd.New(levelVar) - cmd.Use = strings.Replace(cmd.Use, cmd.Name(), appname, 1) cmd.Version = version if len(args) == 1 && (args[0] == "-h" || args[0] == "--help") { diff --git a/tools/gendoc/main.go b/tools/gendoc/main.go index 86bb27b..b00d26e 100644 --- a/tools/gendoc/main.go +++ b/tools/gendoc/main.go @@ -12,5 +12,5 @@ import ( func main() { root := cmd.New(nil) root.Use = strings.ReplaceAll(root.Use, "exec", "k6x") - clireadme.Main(root, 1) + clireadme.Main(root, 0) } From 959e284b57acfe24e980f0edecfd69779e80ecf3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20SZKIBA?= Date: Thu, 4 Jul 2024 14:55:51 +0200 Subject: [PATCH 4/7] docs: removed invisible references --- README.md | 12 ++++-------- internal/cmd/help.md | 11 ++++------- 2 files changed, 8 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 9e08b1b..7f12ec3 100644 --- a/README.md +++ b/README.md @@ -143,14 +143,10 @@ major change is API breaking. For example, * `^0.0` is equivalent to `>=0.0.0 <0.1.0` * `^0` is equivalent to `>=0.0.0 <1.0.0` - -**References** - -- [k6]: https://k6.io -- [extensions]: https://grafana.com/docs/k6/latest/extensions/ -- [Masterminds/semver]: https://github.com/Masterminds/semver -- [xk6-top]: https://github.com/szkiba/xk6-top - +[k6]: https://k6.io +[extensions]: https://grafana.com/docs/k6/latest/extensions/ +[xk6-top]: https://github.com/szkiba/xk6-top +[Masterminds/semver]: https://github.com/Masterminds/semver ``` k6x [flags] [command] diff --git a/internal/cmd/help.md b/internal/cmd/help.md index 86541b9..3fc2b2b 100644 --- a/internal/cmd/help.md +++ b/internal/cmd/help.md @@ -127,10 +127,7 @@ major change is API breaking. For example, * `^0.0` is equivalent to `>=0.0.0 <0.1.0` * `^0` is equivalent to `>=0.0.0 <1.0.0` - -**References** - -- [k6]: https://k6.io -- [extensions]: https://grafana.com/docs/k6/latest/extensions/ -- [Masterminds/semver]: https://github.com/Masterminds/semver -- [xk6-top]: https://github.com/szkiba/xk6-top +[k6]: https://k6.io +[extensions]: https://grafana.com/docs/k6/latest/extensions/ +[xk6-top]: https://github.com/szkiba/xk6-top +[Masterminds/semver]: https://github.com/Masterminds/semver From 6a0acf4cc79d5aa09a32250daf75bf6b14994512 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20SZKIBA?= Date: Thu, 4 Jul 2024 15:03:02 +0200 Subject: [PATCH 5/7] docs: fix section moving --- README.md | 5 +++-- internal/cmd/help.md | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 7f12ec3..162aafb 100644 --- a/README.md +++ b/README.md @@ -24,8 +24,6 @@ The launcher will always run the k6 test script with the appropriate k6 binary, Any k6 command can be used. Use the `help` command to list the available k6 commands. -Any number of `"use k6"` pragmas can be used. - ### Pragma Version constraints can be specified using the JavaScript `"use ..."` pragma syntax for k6 and extensions. Put the following lines at the beginning of the test script: @@ -35,6 +33,8 @@ Version constraints can be specified using the JavaScript `"use ..."` pragma syn "use k6 with k6/x/faker > 0.2"; ``` +Any number of `"use k6"` pragmas can be used. + > **Note** > The use of pragmas is completely optional for JavaScript type extensions, it is only necessary if you want to specify version constraints. @@ -148,6 +148,7 @@ major change is API breaking. For example, [xk6-top]: https://github.com/szkiba/xk6-top [Masterminds/semver]: https://github.com/Masterminds/semver + ``` k6x [flags] [command] ``` diff --git a/internal/cmd/help.md b/internal/cmd/help.md index 3fc2b2b..497bec3 100644 --- a/internal/cmd/help.md +++ b/internal/cmd/help.md @@ -8,8 +8,6 @@ The launcher will always run the k6 test script with the appropriate k6 binary, Any k6 command can be used. Use the `help` command to list the available k6 commands. -Any number of `"use k6"` pragmas can be used. - ### Pragma Version constraints can be specified using the JavaScript `"use ..."` pragma syntax for k6 and extensions. Put the following lines at the beginning of the test script: @@ -19,6 +17,8 @@ Version constraints can be specified using the JavaScript `"use ..."` pragma syn "use k6 with k6/x/faker > 0.2"; ``` +Any number of `"use k6"` pragmas can be used. + > **Note** > The use of pragmas is completely optional for JavaScript type extensions, it is only necessary if you want to specify version constraints. From ebcbd61ad1770ffdd7795d16d9e28ea61b52ef3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20SZKIBA?= Date: Thu, 4 Jul 2024 15:05:47 +0200 Subject: [PATCH 6/7] docs: fix colon-semicolon mistake --- README.md | 2 +- internal/cmd/help.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 162aafb..18308a7 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ Read the version constraints syntax in the [Version Constraints](#version-constr ### Environment -The extensions to be used and optionally their version constraints can also be specified in the `K6_DEPENDENCIES` environment variable. The value of the `K6_DEPENDENCIES` environment variable is a comma-separated list of elements. Each element specifies an extension (or k6 itself) and optionally its version constraint. +The extensions to be used and optionally their version constraints can also be specified in the `K6_DEPENDENCIES` environment variable. The value of the environment variable K6_DEPENDENCIES is a list of elements separated by semicolons. Each element specifies an extension (or k6 itself) and optionally its version constraint. ``` k6>=0.52;k6/x/faker>=0.3;k6/x/sql>=0.4 diff --git a/internal/cmd/help.md b/internal/cmd/help.md index 497bec3..ff0f486 100644 --- a/internal/cmd/help.md +++ b/internal/cmd/help.md @@ -32,7 +32,7 @@ Read the version constraints syntax in the [Version Constraints](#version-constr ### Environment -The extensions to be used and optionally their version constraints can also be specified in the `K6_DEPENDENCIES` environment variable. The value of the `K6_DEPENDENCIES` environment variable is a comma-separated list of elements. Each element specifies an extension (or k6 itself) and optionally its version constraint. +The extensions to be used and optionally their version constraints can also be specified in the `K6_DEPENDENCIES` environment variable. The value of the environment variable K6_DEPENDENCIES is a list of elements separated by semicolons. Each element specifies an extension (or k6 itself) and optionally its version constraint. ``` k6>=0.52;k6/x/faker>=0.3;k6/x/sql>=0.4 From 1553b48c6bf7b5efc9821fcc8988ce595177a66e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20SZKIBA?= Date: Thu, 4 Jul 2024 16:12:48 +0200 Subject: [PATCH 7/7] docs: added section about build modes --- README.md | 24 ++++++++++++++++++++++-- internal/cmd/help.md | 24 ++++++++++++++++++++++-- 2 files changed, 44 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 18308a7..6a01022 100644 --- a/README.md +++ b/README.md @@ -20,10 +20,30 @@ Run k6 with a seamless extension user experience. The launcher acts as a drop-in replacement for the `k6` command. For more convenient use, it is advisable to create an alias or shell script called `k6` for the launcher. The alias can be used in exactly the same way as the `k6` command, with the difference that it generates the real `k6` on the fly based on the extensions you want to use. -The launcher will always run the k6 test script with the appropriate k6 binary, which contains the extensions used by the script. In order to do this, it analyzes the script arguments of the "run" and "archive" subcommands, detects the extensions to be used and their version constraints. - Any k6 command can be used. Use the `help` command to list the available k6 commands. +Since k6x tries to emulate the `k6` command line, the `help` command or the `--help` flag cannot be used to display help from `k6x` command itself. The `k6x` help can be displayed using the `--usage` flag: + + k6x --usage + +### Prerequisites + +k6x tries to provide the appropriate k6 executable after detecting the extension dependencies. This can be done using a build service or a native builder. + +#### Build Service + +No additional installation is required to use the build service, just provide the build service URL. + +The build service URL can be specified in the `K6_BUILD_SERVICE_URL` environment variable or by using the `--build-service-url` flag. + +There is no default URL for the build service, otherwise k6x will automatically provide k6 with the native builder. + +#### Native Builder + +To use the native builder, you only need to install the [Go language toolkit](https://go.dev/doc/install). + +The native builder uses a k6 extension catalog to resolve extension URLs and versions. The extension catalog URL has a default value. A different extension catalog URL can be specified in the `K6_EXTENSION_CATALOG_URL` environment variable or by using the `--extension-catalog-url` flag. + ### Pragma Version constraints can be specified using the JavaScript `"use ..."` pragma syntax for k6 and extensions. Put the following lines at the beginning of the test script: diff --git a/internal/cmd/help.md b/internal/cmd/help.md index ff0f486..c0296d3 100644 --- a/internal/cmd/help.md +++ b/internal/cmd/help.md @@ -4,10 +4,30 @@ Run k6 with a seamless extension user experience. The launcher acts as a drop-in replacement for the `k6` command. For more convenient use, it is advisable to create an alias or shell script called `k6` for the launcher. The alias can be used in exactly the same way as the `k6` command, with the difference that it generates the real `k6` on the fly based on the extensions you want to use. -The launcher will always run the k6 test script with the appropriate k6 binary, which contains the extensions used by the script. In order to do this, it analyzes the script arguments of the "run" and "archive" subcommands, detects the extensions to be used and their version constraints. - Any k6 command can be used. Use the `help` command to list the available k6 commands. +Since k6x tries to emulate the `k6` command line, the `help` command or the `--help` flag cannot be used to display help from `k6x` command itself. The `k6x` help can be displayed using the `--usage` flag: + + k6x --usage + +### Prerequisites + +k6x tries to provide the appropriate k6 executable after detecting the extension dependencies. This can be done using a build service or a native builder. + +#### Build Service + +No additional installation is required to use the build service, just provide the build service URL. + +The build service URL can be specified in the `K6_BUILD_SERVICE_URL` environment variable or by using the `--build-service-url` flag. + +There is no default URL for the build service, otherwise k6x will automatically provide k6 with the native builder. + +#### Native Builder + +To use the native builder, you only need to install the [Go language toolkit](https://go.dev/doc/install). + +The native builder uses a k6 extension catalog to resolve extension URLs and versions. The extension catalog URL has a default value. A different extension catalog URL can be specified in the `K6_EXTENSION_CATALOG_URL` environment variable or by using the `--extension-catalog-url` flag. + ### Pragma Version constraints can be specified using the JavaScript `"use ..."` pragma syntax for k6 and extensions. Put the following lines at the beginning of the test script: