mmt-mcp 1.45.3 → 1.46.0-pre

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (25) hide show
  1. package/dist/examples/examples-index.json +17 -0
  2. package/dist/examples/intermediate/12_dynamic_values/README.md +6 -2
  3. package/dist/examples/intermediate/12_dynamic_values/api/current.mmt +15 -1
  4. package/dist/examples/intermediate/12_dynamic_values/current_test.mmt +9 -1
  5. package/dist/examples/professional/01_report_generation/README.md +19 -10
  6. package/dist/examples/professional/01_report_generation/multimeter.mmt +3 -0
  7. package/dist/examples/professional/01_report_generation/reports/results.mmt +44 -0
  8. package/dist/examples/professional/01_report_generation/suite.mmt +11 -1
  9. package/dist/examples/professional/01_report_generation/test/skip_test.mmt +14 -0
  10. package/dist/examples/professional/11_token_resolution/README.md +5 -5
  11. package/dist/examples/professional/11_token_resolution/api/current_header.mmt +19 -1
  12. package/dist/examples/professional/11_token_resolution/api/current_json_body.mmt +22 -1
  13. package/dist/examples/professional/11_token_resolution/api/current_query.mmt +19 -1
  14. package/dist/examples/professional/11_token_resolution/api/current_urlencoded_body.mmt +19 -1
  15. package/dist/examples/professional/11_token_resolution/api/current_xml_body.mmt +19 -1
  16. package/dist/examples/professional/11_token_resolution/test/current_header_test.mmt +8 -1
  17. package/dist/examples/professional/11_token_resolution/test/current_json_body_test.mmt +9 -1
  18. package/dist/examples/professional/11_token_resolution/test/current_query_test.mmt +8 -1
  19. package/dist/examples/professional/11_token_resolution/test/current_urlencoded_body_test.mmt +8 -1
  20. package/dist/examples/professional/11_token_resolution/test/current_xml_body_test.mmt +8 -1
  21. package/dist/guides/general.md +1 -0
  22. package/dist/guides/generate-api.md +1 -1
  23. package/dist/server.cjs +541 -59
  24. package/dist/server.js +541 -59
  25. package/package.json +1 -1
@@ -1151,6 +1151,17 @@
1151
1151
  "category": "professional",
1152
1152
  "title": "Echo API"
1153
1153
  },
1154
+ {
1155
+ "path": "professional/01_report_generation/multimeter.mmt",
1156
+ "type": "env",
1157
+ "category": "professional",
1158
+ "title": "Report Generation Example"
1159
+ },
1160
+ {
1161
+ "path": "professional/01_report_generation/reports/results.mmt",
1162
+ "type": "report",
1163
+ "category": "professional"
1164
+ },
1154
1165
  {
1155
1166
  "path": "professional/01_report_generation/suite.mmt",
1156
1167
  "type": "suite",
@@ -1169,6 +1180,12 @@
1169
1180
  "category": "professional",
1170
1181
  "title": "Passing Test"
1171
1182
  },
1183
+ {
1184
+ "path": "professional/01_report_generation/test/skip_test.mmt",
1185
+ "type": "test",
1186
+ "category": "professional",
1187
+ "title": "Skipped Test"
1188
+ },
1172
1189
  {
1173
1190
  "path": "professional/02_tls_certificates/api/secure_echo.mmt",
1174
1191
  "type": "api",
@@ -13,7 +13,7 @@ Random tokens are split by kind. Current tokens live in their own test. Nearby r
13
13
  │ ├── random_network.mmt # Network r: tokens
14
14
  │ ├── random_identity.mmt # People, place, business, and text r: tokens
15
15
  │ ├── random_time.mmt # Calendar and epoch r: tokens plus current times
16
- │ └── current.mmt # c: clock and locale tokens
16
+ │ └── current.mmt # c: clock, locale, and git tokens
17
17
  ├── random_types_test.mmt
18
18
  ├── random_network_test.mmt
19
19
  ├── random_identity_test.mmt
@@ -31,7 +31,7 @@ Random tokens are split by kind. Current tokens live in their own test. Nearby r
31
31
  | `api/random_network.mmt` | `r:domain`, `r:url`, `r:mac`, `r:ip`, `r:hostname`, `r:user_agent` |
32
32
  | `api/random_identity.mmt` | `r:email`, names, address, company, and text tokens |
33
33
  | `api/random_time.mmt` | Ranged and near-now datetimes/epochs, plus `c:` times for proximity |
34
- | `api/current.mmt` | `c:utc_datetime`, offsets such as `(+2s)` / `(+1h)`, date, time, epoch, timezone |
34
+ | `api/current.mmt` | `c:utc_datetime`, offsets, date/time/epoch/timezone, plus `c:git_*` (branch, commit, tag, describe, dirty) |
35
35
  | `*_test.mmt` | Calls the matching API and validates the echoed values |
36
36
  | `suite.mmt` | Runs every dynamic-values test together |
37
37
 
@@ -46,6 +46,9 @@ body:
46
46
  datetime_near_now: r:utc_datetime_now(2s)
47
47
  created_utc: c:utc_datetime
48
48
  created_utc_plus_2s: c:utc_datetime(+2s)
49
+ git_commit: c:git_commit
50
+ git_branch: c:git_branch
51
+ git_dirty: c:git_dirty
49
52
  ```
50
53
 
51
54
  ```yaml
@@ -61,6 +64,7 @@ body:
61
64
  - **Local vs UTC** — `r:datetime` / `c:datetime` use local time; `r:utc_datetime` / `c:utc_datetime` use UTC and end in `Z`.
62
65
  - **Ranges around now** accept combined durations such as `2s` or `1h1m`.
63
66
  - **Current offsets** use a signed duration: `c:utc_datetime(+2s)`, `c:date(+7d)`.
67
+ - **Git currents** — `c:git_branch`, `c:git_commit` (short), `c:git_commit_hash`, `c:git_tag`, `c:git_describe`, `c:git_dirty`. Short aliases: `c:branch`, `c:commit`, `c:tag`. Empty / `false` when git is unavailable.
64
68
  - **Time comparison** — `=5s~` / `!5s~` check that two times differ by at most (or more than) the velocity. A duration is required; bare `=~` is the deprecated as-string operator.
65
69
  - **No JS required** — tokens can be used directly in API `body`, `headers`, `query`, `cookies`, `url`, and input defaults.
66
70
 
@@ -1,6 +1,6 @@
1
1
  type: api
2
2
  title: Current values
3
- description: "Sends c: clock and locale tokens, including offsets, and extracts the echoed values"
3
+ description: "Sends c: clock, locale, and git tokens, including offsets, and extracts the echoed values"
4
4
  outputs:
5
5
  created_utc: body.body.created_utc
6
6
  created_utc_plus_2s: body.body.created_utc_plus_2s
@@ -12,6 +12,13 @@ outputs:
12
12
  timezone: body.body.timezone
13
13
  utc_offset: body.body.utc_offset
14
14
  year: body.body.year
15
+ git_branch: body.body.git_branch
16
+ git_commit: body.body.git_commit
17
+ git_commit_hash: body.body.git_commit_hash
18
+ git_tag: body.body.git_tag
19
+ git_describe: body.body.git_describe
20
+ git_dirty: body.body.git_dirty
21
+ commit_alias: body.body.commit_alias
15
22
  request_method: body.method
16
23
  url: https://test.mmt.dev/echo
17
24
  method: post
@@ -26,3 +33,10 @@ body:
26
33
  timezone: c:timezone
27
34
  utc_offset: c:utc_offset
28
35
  year: c:year
36
+ git_branch: c:git_branch
37
+ git_commit: c:git_commit
38
+ git_commit_hash: c:git_commit_hash
39
+ git_tag: c:git_tag
40
+ git_describe: c:git_describe
41
+ git_dirty: c:git_dirty
42
+ commit_alias: c:commit
@@ -1,6 +1,6 @@
1
1
  type: test
2
2
  title: Current values
3
- description: "Calls an API that uses c: tokens and checks nearby times with =5s~"
3
+ description: "Calls an API that uses c: tokens (clock, locale, git) and checks nearby times with =5s~"
4
4
  import:
5
5
  currentValues: ./api/current.mmt
6
6
  steps:
@@ -18,5 +18,13 @@ steps:
18
18
  timezone: != null
19
19
  utc_offset: != null
20
20
  year: >= 2026
21
+ git_branch: != null
22
+ git_commit: =* ^([0-9a-f]{8})?$
23
+ git_commit_hash: =* ^([0-9a-f]{7,40})?$
24
+ git_tag: != null
25
+ git_describe: != null
26
+ git_dirty: != null
27
+ commit_alias: c:git_commit
21
28
  - check: ${result.created_utc} =5s~ ${result.created_utc_plus_2s}
22
29
  - check: ${result.created_utc} !5s~ ${result.created_utc_plus_1h}
30
+ - check: ${result.commit_alias} == ${result.git_commit}
@@ -1,18 +1,22 @@
1
1
  # Report Generation
2
2
 
3
- Demonstrates how to generate **test reports** in JUnit XML, HTML, Markdown, and MMT YAML formats — both via CLI flags and via the suite `export` field.
3
+ Demonstrates how to generate **test reports** in JUnit XML, HTML, Markdown, and MMT YAML formats — both via CLI flags and via the suite `export` field. Includes a **skipped** test (via suite tag filter) so reports show skipped results.
4
4
 
5
5
  ## Structure
6
6
 
7
7
  ```
8
8
  01_report_generation/
9
+ ├── multimeter.mmt # Project root marker (enables +/ paths in reports)
9
10
  ├── api/
10
11
  │ └── echo.mmt # Simple echo API
11
12
  ├── test/
12
13
  │ ├── pass_test.mmt # A test that passes
13
- │ └── fail_test.mmt # A test with a deliberate failure (for demo)
14
+ │ ├── fail_test.mmt # A test with a deliberate failure (for demo)
15
+ │ └── skip_test.mmt # Tagged skip-demo; suite filter skips it
14
16
  ├── suite.mmt # Suite with export field for auto-report
15
- ├── reports/ # Generated reports appear here
17
+ ├── reports/ # Static + git-structured exports land here
18
+ │ ├── results.* # Fixed overwrite targets
19
+ │ └── branch/…/ or tags/…/ # From <<c:report_folder>>
16
20
  └── README.md
17
21
  ```
18
22
 
@@ -20,17 +24,18 @@ Demonstrates how to generate **test reports** in JUnit XML, HTML, Markdown, and
20
24
 
21
25
  | File | Description |
22
26
  |---|---|
23
- | `api/echo.mmt` | Echo API used by both tests |
27
+ | `api/echo.mmt` | Echo API used by the tests |
24
28
  | `test/pass_test.mmt` | Calls the echo API and asserts status 200 — should pass |
25
29
  | `test/fail_test.mmt` | Calls the echo API and checks for status 999 — deliberately fails |
26
- | `suite.mmt` | Suite with `export` field that auto-generates JUnit XML and HTML reports |
30
+ | `test/skip_test.mmt` | Tagged `skip-demo`; suite `filter.skip` marks it skipped in reports |
31
+ | `suite.mmt` | Suite with `export`: fixed `./reports/results.*` plus `./reports/<<c:report_folder>>/…` |
27
32
 
28
33
  ## Report formats
29
34
 
30
35
  | Format | Flag | Default file | Description |
31
36
  |--------|------|--------------|-------------|
32
37
  | JUnit XML | `--report junit` | `test-results.xml` | CI/CD standard (GitHub Actions, Jenkins, etc.) |
33
- | HTML | `--report html` | `test-results.html` | Self-contained page with pass/fail indicators |
38
+ | HTML | `--report html` | `test-results.html` | Self-contained page with pass/fail/skipped indicators |
34
39
  | Markdown | `--report md` | `test-results.md` | GitHub-flavored tables, great for PRs |
35
40
  | MMT YAML | `--report mmt` | `test-results.mmt` | Native format, can be viewed in Multimeter |
36
41
 
@@ -38,8 +43,11 @@ Demonstrates how to generate **test reports** in JUnit XML, HTML, Markdown, and
38
43
 
39
44
  - **`--report FORMAT`** — CLI flag to generate a report after a test/suite run.
40
45
  - **`--report-file PATH`** — custom output path for the report.
41
- - **Suite `export`** — list of file paths in the suite file. Reports are auto-generated after the suite completes, with the format inferred from the file extension.
46
+ - **Suite `export`** — list of file paths in the suite file. Reports are auto-generated after the suite completes, with the format inferred from the file extension (`.xml`, `.html`, `.md`, `.mmt`).
47
+ - **`c:` in export paths** — any current token expands at write time. This suite writes both fixed `./reports/results.*` and git-structured `./reports/<<c:report_folder>>/results.*` (`tags/<tag>`, `branch/<branch>/<commit>`, `detached/<commit>`, or `local`).
48
+ - **`filter.skip`** — tag filter that skips matching tests; skipped items appear in reports with `result: skipped`.
42
49
  - **`report` on checks** — controls reporting level: `all` (pass + fail), `fails` (only failures), `none` (silent).
50
+ - **`+/` file paths** — exported reports store source files as `+/…` relative to `multimeter.mmt` (portable; Ctrl+click in MMT reports opens from that root).
43
51
 
44
52
  ## How to use
45
53
 
@@ -48,10 +56,11 @@ Demonstrates how to generate **test reports** in JUnit XML, HTML, Markdown, and
48
56
  1. Open `suite.mmt` and click **Run**.
49
57
  2. After the run completes, click the **Export** button in the toolbar.
50
58
  3. Choose a format (JUnit XML, HTML, Markdown, or MMT YAML).
59
+ 4. Or open `reports/results.mmt` in Multimeter to view the native report.
51
60
 
52
61
  ### With the CLI
53
62
 
54
- Run the suite with automatic export (uses the `export` field):
63
+ Run the suite with automatic export (static `reports/results.*` plus `reports/<c:report_folder>/results.*`):
55
64
 
56
65
  ```sh
57
66
  npx testlight run examples/professional/01_report_generation/suite.mmt
@@ -73,11 +82,11 @@ npx testlight run examples/professional/01_report_generation/suite.mmt --report
73
82
  npx testlight run examples/professional/01_report_generation/suite.mmt --report mmt
74
83
  ```
75
84
 
76
- Custom output path:
85
+ Custom output path (also accepts `c:` tokens; quote for the shell):
77
86
 
78
87
  ```sh
79
88
  npx testlight run examples/professional/01_report_generation/suite.mmt \
80
- --report junit --report-file ./my-reports/output.xml
89
+ --report junit --report-file './reports/<<c:report_folder>>/cli-output.xml'
81
90
  ```
82
91
 
83
92
  Run a single test with a report:
@@ -0,0 +1,3 @@
1
+ type: env
2
+ title: Report Generation Example
3
+ description: Project root marker so report exports use +/ paths
@@ -0,0 +1,44 @@
1
+ type: report
2
+ kind: functional
3
+ name: Report Generation Suite
4
+ overview:
5
+ started_at: 2026-10-14T15:51:12.118Z
6
+ finished_at: 2026-10-14T15:51:12.460Z
7
+ duration: 342ms
8
+ passed: 1
9
+ failed: 1
10
+ errors: 0
11
+ skipped: 1
12
+ checks: 2
13
+ checks:
14
+ - name: Skipped Test
15
+ type: test
16
+ file: +/test/skip_test.mmt
17
+ result: skipped
18
+ - name: Passing Test
19
+ type: test
20
+ file: +/test/pass_test.mmt
21
+ result: passed
22
+ checks:
23
+ - name: Assert
24
+ type: check
25
+ result: passed
26
+ step: assert
27
+ - name: Failing Test
28
+ type: test
29
+ file: +/test/fail_test.mmt
30
+ result: failed
31
+ checks:
32
+ - name: Check
33
+ type: check
34
+ result: failed
35
+ expects:
36
+ - comparison: result.status_code == 999
37
+ result: failed
38
+ actual: "200"
39
+ expected: "999"
40
+ failure:
41
+ message: "result.status_code == 999: expected 999 got 200"
42
+ actual: "200"
43
+ expected: "999"
44
+ operator: result.status_code == 999
@@ -1,12 +1,22 @@
1
1
  type: suite
2
2
  title: Report Generation Suite
3
- description: Runs passing and failing tests to demonstrate report output
3
+ description: Runs passing, failing, and skipped tests to demonstrate report output
4
4
  tags:
5
5
  - example
6
6
  - reports
7
+ filter:
8
+ skip:
9
+ - skip-demo
7
10
  export:
11
+ # Fixed paths (always overwrite the same files)
8
12
  - ./reports/results.xml
9
13
  - ./reports/results.html
14
+ - ./reports/results.mmt
15
+ # Git-structured tree: tags/<tag> | branch/<branch>/<commit> | detached/<commit> | local
16
+ - ./reports/<<c:report_folder>>/results.xml
17
+ - ./reports/<<c:report_folder>>/results.html
18
+ - ./reports/<<c:report_folder>>/results.mmt
10
19
  items:
11
20
  - test/pass_test.mmt
12
21
  - test/fail_test.mmt
22
+ - test/skip_test.mmt
@@ -0,0 +1,14 @@
1
+ type: test
2
+ title: Skipped Test
3
+ description: Tagged so the suite filter skips it — appears as skipped in reports
4
+ tags:
5
+ - skip-demo
6
+ import:
7
+ echo: ../api/echo.mmt
8
+ steps:
9
+ - call: echo
10
+ id: result
11
+ inputs:
12
+ message: skip test
13
+ expect:
14
+ status_code: 200
@@ -57,11 +57,11 @@ JSON is the only format here that still shows `plan_code` as the number `10` and
57
57
  | `api/random_urlencoded_body.mmt` | `r:` as form text |
58
58
  | `api/random_header.mmt` | `r:` as header text (`r:color` stays a name) |
59
59
  | `api/random_query.mmt` | `r:` as query text |
60
- | `api/current_json_body.mmt` | `c:day` and `c:city` text, `c:epoch` number |
61
- | `api/current_xml_body.mmt` | `c:` as XML text |
62
- | `api/current_urlencoded_body.mmt` | `c:` as form text |
63
- | `api/current_header.mmt` | `c:` as header text |
64
- | `api/current_query.mmt` | `c:` as query text |
60
+ | `api/current_json_body.mmt` | `c:day` / `c:city` text, `c:epoch` number, `c:git_*` (dirty boolean) |
61
+ | `api/current_xml_body.mmt` | `c:` (incl. git) as XML text |
62
+ | `api/current_urlencoded_body.mmt` | `c:` (incl. git) as form text |
63
+ | `api/current_header.mmt` | `c:` (incl. git) as header text |
64
+ | `api/current_query.mmt` | `c:` (incl. git) as query text |
65
65
 
66
66
  Each API lists `outputs` for the echoed fields and a no-input `examples` entry (`id: defaults`) with the same `expect` checks as its matching test, so you can validate outputs from the API tester. Matching tests live under `test/` (`env_json_body_test.mmt` for `api/env_json_body.mmt`, and so on). `suite.mmt` runs all twenty.
67
67
 
@@ -1,10 +1,16 @@
1
1
  type: api
2
2
  title: Current tokens in headers
3
- description: "Header values are strings. c:epoch is sent as digits, not a JSON number."
3
+ description: "Header values are strings. c:epoch and c:git_dirty are sent as text digits / true|false."
4
4
  outputs:
5
5
  day_name: body[headers][x-day-name]
6
6
  epoch_seconds: body[headers][x-epoch-seconds]
7
7
  city: body[headers][x-city]
8
+ git_branch: body[headers][x-git-branch]
9
+ git_commit: body[headers][x-git-commit]
10
+ git_commit_hash: body[headers][x-git-commit-hash]
11
+ git_describe: body[headers][x-git-describe]
12
+ git_dirty: body[headers][x-git-dirty]
13
+ commit_alias: body[headers][x-commit-alias]
8
14
  missing_token: body[headers][x-missing-token]
9
15
  literal_token: body[headers][x-literal-token]
10
16
  literal_omit: body[headers][x-literal-omit]
@@ -24,6 +30,12 @@ headers:
24
30
  X-Day-Name: c:day
25
31
  X-Epoch-Seconds: c:epoch
26
32
  X-City: c:city
33
+ X-Git-Branch: c:git_branch
34
+ X-Git-Commit: c:git_commit
35
+ X-Git-Commit-Hash: c:git_commit_hash
36
+ X-Git-Describe: c:git_describe
37
+ X-Git-Dirty: c:git_dirty
38
+ X-Commit-Alias: c:commit
27
39
  X-Missing-Token: c:not_a_token
28
40
  X-Literal-Token: "c:day"
29
41
  X-Literal-Omit: "omit"
@@ -44,6 +56,12 @@ examples:
44
56
  day_name: c:day
45
57
  epoch_seconds: != null
46
58
  city: c:city
59
+ git_branch: c:git_branch
60
+ git_commit: c:git_commit
61
+ git_commit_hash: c:git_commit_hash
62
+ git_describe: c:git_describe
63
+ git_dirty: c:git_dirty
64
+ commit_alias: c:commit
47
65
  missing_token: "c:not_a_token"
48
66
  literal_token: "c:day"
49
67
  literal_omit: "omit"
@@ -1,10 +1,17 @@
1
1
  type: api
2
2
  title: Current tokens in a JSON body
3
- description: "A whole-field c: value keeps the generator type. The example expects c:day and c:city. c:epoch is a number that changes, so the example checks the range."
3
+ description: "A whole-field c: value keeps the generator type. c:epoch is a number; c:git_dirty is a boolean. Git strings and clock/locale tokens stay text."
4
4
  outputs:
5
5
  day_name: body.body.day_name
6
6
  epoch_seconds: body.body.epoch_seconds
7
7
  city: body.body.city
8
+ git_branch: body.body.git_branch
9
+ git_commit: body.body.git_commit
10
+ git_commit_hash: body.body.git_commit_hash
11
+ git_tag: body.body.git_tag
12
+ git_describe: body.body.git_describe
13
+ git_dirty: body.body.git_dirty
14
+ commit_alias: body.body.commit_alias
8
15
  missing_token: body.body.missing_token
9
16
  literal_token: body.body.literal_token
10
17
  literal_omit: body.body.literal_omit
@@ -26,6 +33,13 @@ body:
26
33
  day_name: c:day
27
34
  epoch_seconds: c:epoch
28
35
  city: c:city
36
+ git_branch: c:git_branch
37
+ git_commit: c:git_commit
38
+ git_commit_hash: c:git_commit_hash
39
+ git_tag: c:git_tag
40
+ git_describe: c:git_describe
41
+ git_dirty: c:git_dirty
42
+ commit_alias: c:commit
29
43
  missing_token: c:not_a_token
30
44
  literal_token: "c:day"
31
45
  removed_note: omit
@@ -47,6 +61,13 @@ examples:
47
61
  day_name: c:day
48
62
  epoch_seconds: > 1700000000
49
63
  city: c:city
64
+ git_branch: c:git_branch
65
+ git_commit: c:git_commit
66
+ git_commit_hash: c:git_commit_hash
67
+ git_tag: c:git_tag
68
+ git_describe: c:git_describe
69
+ git_dirty: c:git_dirty
70
+ commit_alias: c:commit
50
71
  missing_token: "c:not_a_token"
51
72
  literal_token: "c:day"
52
73
  literal_omit: "omit"
@@ -1,10 +1,16 @@
1
1
  type: api
2
2
  title: Current tokens in the query string
3
- description: "Query values are strings. c:epoch is sent as digits, not a JSON number."
3
+ description: "Query values are strings. c:epoch and c:git_dirty are sent as text."
4
4
  outputs:
5
5
  day_name: body.query.day_name
6
6
  epoch_seconds: body.query.epoch_seconds
7
7
  city: body.query.city
8
+ git_branch: body.query.git_branch
9
+ git_commit: body.query.git_commit
10
+ git_commit_hash: body.query.git_commit_hash
11
+ git_describe: body.query.git_describe
12
+ git_dirty: body.query.git_dirty
13
+ commit_alias: body.query.commit_alias
8
14
  missing_token: body.query.missing_token
9
15
  literal_token: body.query.literal_token
10
16
  literal_omit: body.query.literal_omit
@@ -23,6 +29,12 @@ query:
23
29
  day_name: c:day
24
30
  epoch_seconds: c:epoch
25
31
  city: c:city
32
+ git_branch: c:git_branch
33
+ git_commit: c:git_commit
34
+ git_commit_hash: c:git_commit_hash
35
+ git_describe: c:git_describe
36
+ git_dirty: c:git_dirty
37
+ commit_alias: c:commit
26
38
  missing_token: c:not_a_token
27
39
  literal_token: "c:day"
28
40
  literal_omit: "omit"
@@ -44,6 +56,12 @@ examples:
44
56
  day_name: c:day
45
57
  epoch_seconds: != null
46
58
  city: c:city
59
+ git_branch: c:git_branch
60
+ git_commit: c:git_commit
61
+ git_commit_hash: c:git_commit_hash
62
+ git_describe: c:git_describe
63
+ git_dirty: c:git_dirty
64
+ commit_alias: c:commit
47
65
  missing_token: "c:not_a_token"
48
66
  literal_token: "c:day"
49
67
  literal_omit: "omit"
@@ -1,10 +1,16 @@
1
1
  type: api
2
2
  title: Current tokens in a form body
3
- description: "Urlencoded fields are strings. c:epoch is sent as digits."
3
+ description: "Urlencoded fields are strings. c:epoch and c:git_dirty are sent as text."
4
4
  outputs:
5
5
  day_name: body.body.day_name
6
6
  epoch_seconds: body.body.epoch_seconds
7
7
  city: body.body.city
8
+ git_branch: body.body.git_branch
9
+ git_commit: body.body.git_commit
10
+ git_commit_hash: body.body.git_commit_hash
11
+ git_describe: body.body.git_describe
12
+ git_dirty: body.body.git_dirty
13
+ commit_alias: body.body.commit_alias
8
14
  missing_token: body.body.missing_token
9
15
  literal_token: body.body.literal_token
10
16
  literal_omit: body.body.literal_omit
@@ -25,6 +31,12 @@ body:
25
31
  day_name: c:day
26
32
  epoch_seconds: c:epoch
27
33
  city: c:city
34
+ git_branch: c:git_branch
35
+ git_commit: c:git_commit
36
+ git_commit_hash: c:git_commit_hash
37
+ git_describe: c:git_describe
38
+ git_dirty: c:git_dirty
39
+ commit_alias: c:commit
28
40
  missing_token: c:not_a_token
29
41
  literal_token: "c:day"
30
42
  literal_omit: "omit"
@@ -45,6 +57,12 @@ examples:
45
57
  day_name: c:day
46
58
  epoch_seconds: != null
47
59
  city: c:city
60
+ git_branch: c:git_branch
61
+ git_commit: c:git_commit
62
+ git_commit_hash: c:git_commit_hash
63
+ git_describe: c:git_describe
64
+ git_dirty: c:git_dirty
65
+ commit_alias: c:commit
48
66
  missing_token: "c:not_a_token"
49
67
  literal_token: "c:day"
50
68
  literal_omit: "omit"
@@ -1,10 +1,16 @@
1
1
  type: api
2
2
  title: Current tokens in an XML body
3
- description: "XML element text is always a string, including c:epoch."
3
+ description: "XML element text is always a string, including c:epoch and c:git_dirty."
4
4
  outputs:
5
5
  day_name: body.echo.body.body.day_name
6
6
  epoch_seconds: body.echo.body.body.epoch_seconds
7
7
  city: body.echo.body.body.city
8
+ git_branch: body.echo.body.body.git_branch
9
+ git_commit: body.echo.body.body.git_commit
10
+ git_commit_hash: body.echo.body.body.git_commit_hash
11
+ git_describe: body.echo.body.body.git_describe
12
+ git_dirty: body.echo.body.body.git_dirty
13
+ commit_alias: body.echo.body.body.commit_alias
8
14
  missing_token: body.echo.body.body.missing_token
9
15
  literal_token: body.echo.body.body.literal_token
10
16
  literal_omit: body.echo.body.body.literal_omit
@@ -25,6 +31,12 @@ body:
25
31
  day_name: c:day
26
32
  epoch_seconds: c:epoch
27
33
  city: c:city
34
+ git_branch: c:git_branch
35
+ git_commit: c:git_commit
36
+ git_commit_hash: c:git_commit_hash
37
+ git_describe: c:git_describe
38
+ git_dirty: c:git_dirty
39
+ commit_alias: c:commit
28
40
  missing_token: c:not_a_token
29
41
  literal_token: "c:day"
30
42
  literal_omit: "omit"
@@ -44,6 +56,12 @@ examples:
44
56
  day_name: c:day
45
57
  epoch_seconds: != null
46
58
  city: c:city
59
+ git_branch: c:git_branch
60
+ git_commit: c:git_commit
61
+ git_commit_hash: c:git_commit_hash
62
+ git_describe: c:git_describe
63
+ git_dirty: c:git_dirty
64
+ commit_alias: c:commit
47
65
  missing_token: "c:not_a_token"
48
66
  literal_token: "c:day"
49
67
  literal_omit: "omit"
@@ -1,6 +1,6 @@
1
1
  type: test
2
2
  title: Current token resolution (header)
3
- description: "Echoes c: values as header text."
3
+ description: "Echoes c: clock, locale, and git values as header text."
4
4
  import:
5
5
  api: ../api/current_header.mmt
6
6
  steps:
@@ -11,6 +11,12 @@ steps:
11
11
  day_name: != null
12
12
  epoch_seconds: != null
13
13
  city: != null
14
+ git_branch: != null
15
+ git_commit: =* ^([0-9a-f]{8})?$
16
+ git_commit_hash: =* ^([0-9a-f]{7,40})?$
17
+ git_describe: != null
18
+ git_dirty: =* ^(true|false)$
19
+ commit_alias: c:git_commit
14
20
  missing_token: "c:not_a_token"
15
21
  literal_token: "c:day"
16
22
  literal_omit: "omit"
@@ -23,3 +29,4 @@ steps:
23
29
  curly_whole: "!= null"
24
30
  text_slice: "=# 1"
25
31
  missing_embed: "xc:not_a_tokeny"
32
+ - check: ${call.commit_alias} == ${call.git_commit}
@@ -1,6 +1,6 @@
1
1
  type: test
2
2
  title: Current token resolution (JSON body)
3
- description: "Echoes c: values in JSON. c:epoch stays a number. c:day and c:city stay text."
3
+ description: "Echoes c: values in JSON. c:epoch stays a number. c:git_dirty stays a boolean. Clock, locale, and git strings stay text."
4
4
  import:
5
5
  api: ../api/current_json_body.mmt
6
6
  steps:
@@ -11,6 +11,13 @@ steps:
11
11
  day_name: != null
12
12
  epoch_seconds: > 1700000000
13
13
  city: != null
14
+ git_branch: != null
15
+ git_commit: =* ^([0-9a-f]{8})?$
16
+ git_commit_hash: =* ^([0-9a-f]{7,40})?$
17
+ git_tag: != null
18
+ git_describe: != null
19
+ git_dirty: != null
20
+ commit_alias: c:git_commit
14
21
  missing_token: "c:not_a_token"
15
22
  literal_token: "c:day"
16
23
  literal_omit: "omit"
@@ -24,3 +31,4 @@ steps:
24
31
  curly_whole: "!= null"
25
32
  text_slice: "=# 1"
26
33
  missing_embed: "xc:not_a_tokeny"
34
+ - check: ${call.commit_alias} == ${call.git_commit}
@@ -1,6 +1,6 @@
1
1
  type: test
2
2
  title: Current token resolution (query)
3
- description: "Echoes c: values as query text."
3
+ description: "Echoes c: clock, locale, and git values as query text."
4
4
  import:
5
5
  api: ../api/current_query.mmt
6
6
  steps:
@@ -11,6 +11,12 @@ steps:
11
11
  day_name: != null
12
12
  epoch_seconds: != null
13
13
  city: != null
14
+ git_branch: != null
15
+ git_commit: =* ^([0-9a-f]{8})?$
16
+ git_commit_hash: =* ^([0-9a-f]{7,40})?$
17
+ git_describe: != null
18
+ git_dirty: =* ^(true|false)$
19
+ commit_alias: c:git_commit
14
20
  missing_token: "c:not_a_token"
15
21
  literal_token: "c:day"
16
22
  literal_omit: "omit"
@@ -23,3 +29,4 @@ steps:
23
29
  curly_whole: "!= null"
24
30
  text_slice: "=# 1"
25
31
  missing_embed: "xc:not_a_tokeny"
32
+ - check: ${call.commit_alias} == ${call.git_commit}
@@ -1,6 +1,6 @@
1
1
  type: test
2
2
  title: Current token resolution (urlencoded body)
3
- description: "Echoes c: values as form text."
3
+ description: "Echoes c: clock, locale, and git values as form text."
4
4
  import:
5
5
  api: ../api/current_urlencoded_body.mmt
6
6
  steps:
@@ -11,6 +11,12 @@ steps:
11
11
  day_name: != null
12
12
  epoch_seconds: != null
13
13
  city: != null
14
+ git_branch: != null
15
+ git_commit: =* ^([0-9a-f]{8})?$
16
+ git_commit_hash: =* ^([0-9a-f]{7,40})?$
17
+ git_describe: != null
18
+ git_dirty: =* ^(true|false)$
19
+ commit_alias: c:git_commit
14
20
  missing_token: "c:not_a_token"
15
21
  literal_token: "c:day"
16
22
  literal_omit: "omit"
@@ -23,3 +29,4 @@ steps:
23
29
  curly_whole: "!= null"
24
30
  text_slice: "=# 1"
25
31
  missing_embed: "xc:not_a_tokeny"
32
+ - check: ${call.commit_alias} == ${call.git_commit}