@reventlessdev/reventless-aws 3.0.0-alpha.367 → 3.0.0-alpha.369

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.
package/CHANGELOG.md CHANGED
@@ -3,6 +3,21 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ # 3.0.0-alpha.369 (2026-10-01)
7
+
8
+ ### Features
9
+
10
+ * **spec, aws, core, local:** an app declares its environments, and every deployment records its commit ([c7cc925](https://github.com/ReventlessDev/reventless-core/commit/c7cc92573e97742b681a9000cea0bdfd6e9a33fc))
11
+
12
+
13
+ # 3.0.0-alpha.368 (2026-09-29)
14
+
15
+ **Note:** Version bump only for package @reventlessdev/reventless-aws
16
+
17
+
18
+
19
+
20
+
6
21
  # 3.0.0-alpha.367 (2026-09-28)
7
22
 
8
23
  **Note:** Version bump only for package @reventlessdev/reventless-aws
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reventlessdev/reventless-aws",
3
- "version": "3.0.0-alpha.367",
3
+ "version": "3.0.0-alpha.369",
4
4
  "description": "AWS adapters for Reventless",
5
5
  "license": "Apache-2.0",
6
6
  "bin": {
@@ -8,7 +8,8 @@
8
8
  "provision-admin": "./run-provision-admin.mjs",
9
9
  "provision-accounts": "./run-provision-accounts.mjs",
10
10
  "bake-manifest": "./run-bake-manifest.mjs",
11
- "deploy-app": "./run-deploy-app.mjs"
11
+ "deploy-app": "./run-deploy-app.mjs",
12
+ "resolve-environment": "./run-resolve-environment.mjs"
12
13
  },
13
14
  "dependencies": {
14
15
  "@aws-sdk/client-appsync": "3.970.0",
@@ -20,19 +21,19 @@
20
21
  "sury": "11.0.0",
21
22
  "uuid": "^13.0.0",
22
23
  "yaml": "^2.8.3",
23
- "@reventlessdev/rescript-aws-sdk": "3.0.0-alpha.26",
24
- "@reventlessdev/rescript-effect": "0.1.0-alpha.34",
24
+ "@reventlessdev/rescript-aws-sdk": "3.0.0-alpha.27",
25
25
  "@reventlessdev/rescript-jest": "1.0.0-alpha.11",
26
- "@reventlessdev/rescript-pulumi-aws": "3.0.0-alpha.21",
27
- "@reventlessdev/rescript-node": "2.0.0-alpha.19",
26
+ "@reventlessdev/rescript-node": "2.0.0-alpha.20",
27
+ "@reventlessdev/rescript-pulumi-aws": "3.0.0-alpha.22",
28
+ "@reventlessdev/rescript-effect": "0.1.0-alpha.34",
28
29
  "@reventlessdev/rescript-pulumi-pulumi": "2.3.0-alpha.22",
29
- "@reventlessdev/rescript-web": "1.0.0-alpha.6",
30
30
  "@reventlessdev/rescript-uuid": "2.0.0-alpha.1",
31
+ "@reventlessdev/rescript-web": "1.0.0-alpha.7",
32
+ "@reventlessdev/reventless-infra": "3.0.0-alpha.183",
33
+ "@reventlessdev/reventless-core": "3.0.0-alpha.285",
34
+ "@reventlessdev/reventless-postgres": "3.0.0-alpha.149",
31
35
  "@reventlessdev/reventless-interop": "3.0.0-alpha.38",
32
- "@reventlessdev/reventless-core": "3.0.0-alpha.283",
33
- "@reventlessdev/reventless-infra": "3.0.0-alpha.181",
34
- "@reventlessdev/reventless-postgres": "3.0.0-alpha.147",
35
- "@reventlessdev/reventless-spec": "3.0.0-alpha.153"
36
+ "@reventlessdev/reventless-spec": "3.0.0-alpha.155"
36
37
  },
37
38
  "devDependencies": {
38
39
  "rescript": "12.3.1",
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ import { main } from "./scripts/ResolveEnvironment.res.mjs"
3
+ await main()
@@ -0,0 +1,135 @@
1
+ /***
2
+ Which environment a push, a tag or a pull request deploys to, from the app's
3
+ `environments.yaml`.
4
+
5
+ ```
6
+ pnpm exec resolve-environment --ref refs/heads/test
7
+ pnpm exec resolve-environment --pull-request 7 --base dev
8
+ ```
9
+
10
+ Prints `key=value` lines, so the deploy workflow appends them to
11
+ `$GITHUB_OUTPUT` as they are:
12
+
13
+ ```
14
+ matched=true
15
+ environment=test
16
+ stack=test
17
+ purpose=test
18
+ ```
19
+
20
+ Nothing matched is an answer, not a failure: `matched=false` and exit 0, so a push
21
+ to a branch no environment names deploys nowhere and says so. The workflow asks
22
+ only when the file exists; without it the stack is the branch, as it always was.
23
+ */
24
+
25
+ type request =
26
+ | Push(string)
27
+ | PullRequest({number: int, base: string, draft: bool})
28
+
29
+ type args = {
30
+ file: option<string>,
31
+ manifest: option<string>,
32
+ request: request,
33
+ }
34
+
35
+ let parseArgs = (argv: array<string>): result<args, string> =>
36
+ Reventless.CliArgs.parse(
37
+ ~strings=["file", "manifest", "ref", "pull-request", "base"],
38
+ ~bools=["draft"],
39
+ argv,
40
+ )
41
+ ->Result.flatMap(Reventless.CliArgs.noPositionals)
42
+ ->Result.flatMap(a => {
43
+ let string = name => a->Reventless.CliArgs.string(name)
44
+ let request = switch (string("ref"), string("pull-request"), string("base")) {
45
+ | (Some(ref), None, None) => Ok(Push(ref))
46
+ | (None, Some(number), Some(base)) =>
47
+ switch Int.fromString(number) {
48
+ | Some(number) => Ok(PullRequest({number, base, draft: a->Reventless.CliArgs.bool("draft")}))
49
+ | None => Error(`--pull-request takes a number, not "${number}"`)
50
+ }
51
+ | (None, Some(_), None) => Error("--pull-request needs --base, the branch it targets")
52
+ | (None, None, None) => Error("say what deploys: --ref, or --pull-request with --base")
53
+ | _ => Error("--ref and --pull-request are two different questions; ask one")
54
+ }
55
+ request->Result.map(request => {file: string("file"), manifest: string("manifest"), request})
56
+ })
57
+
58
+ let usage = `
59
+ Usage: resolve-environment (--ref <ref> | --pull-request <n> --base <branch> [--draft])
60
+ [--file <path>] [--manifest <path>]
61
+
62
+ Which environment of the app's environments.yaml a deploy goes to.
63
+
64
+ --ref <ref> A push or a tag: refs/heads/<branch> or refs/tags/<tag>.
65
+ --pull-request <n> A pull request, by number ...
66
+ --base <branch> ... and the branch it targets.
67
+ --draft The pull request is a draft.
68
+ --file <path> The environments file. Defaults to ${Reventless.Environments.fileName}
69
+ beside the deploy manifest.
70
+ --manifest <path> The deploy manifest. Defaults to ${DeployManifest.defaultFile}
71
+ in the working directory.
72
+
73
+ Prints matched, environment, stack and purpose as key=value lines; a deploy that
74
+ matches nothing prints matched=false and exits 0.
75
+ `
76
+
77
+ /** The lines printed for a request, from the environments already read. */
78
+ let answer = (environments: Reventless.Environments.t, request: request): array<string> => {
79
+ let resolved = switch request {
80
+ | Push(ref) =>
81
+ ref
82
+ ->Reventless.Environments.refOf
83
+ ->Option.flatMap(ref => environments->Reventless.Environments.resolve(ref))
84
+ | PullRequest({number, base, draft}) =>
85
+ environments->Reventless.Environments.resolvePullRequest(~base, ~number, ~draft)
86
+ }
87
+ switch resolved {
88
+ | Some({name, stack, purpose}) => [
89
+ "matched=true",
90
+ `environment=${name}`,
91
+ `stack=${stack}`,
92
+ `purpose=${purpose->Reventless.Environments.purposeName}`,
93
+ ]
94
+ | None => ["matched=false"]
95
+ }
96
+ }
97
+
98
+ let run = (args: args): result<array<string>, string> => {
99
+ let file = switch args.file {
100
+ | Some(file) => file
101
+ | None =>
102
+ Reventless.Environments.pathBeside(
103
+ ~manifest=args.manifest->Option.getOr(
104
+ NodePath.join([NodeProcess.cwd(), DeployManifest.defaultFile]),
105
+ ),
106
+ )
107
+ }
108
+ if !NodeFs.existsSync(file) {
109
+ Error(
110
+ `no environments file at ${file}. Without one every branch deploys to the stack of its own name, and there is nothing to resolve; --file names another path.`,
111
+ )
112
+ } else {
113
+ file
114
+ ->Reventless.Environments.parseFile
115
+ ->Result.map(environments => answer(environments, args.request))
116
+ ->Result.mapError(message =>
117
+ `${file}: ${message}. The deploy reads any file of this name beside the deploy manifest as its environments; a file kept there for something else needs another name, or the workflow's environments input pointed elsewhere.`
118
+ )
119
+ }
120
+ }
121
+
122
+ let cli: Reventless.CliArgs.cli<args> = {bin: "resolve-environment", usage, parse: parseArgs}
123
+
124
+ let main = () =>
125
+ Reventless.CliArgs.run(cli, async args =>
126
+ switch run(args) {
127
+ | Ok(lines) => lines->Array.forEach(line => Console.log(line))
128
+ | Error(message) =>
129
+ Console.error(`resolve-environment: ${message}`)
130
+ NodeProcess.exit(1)
131
+ }
132
+ )
133
+
134
+ // No top-level call: `../run-resolve-environment.mjs` invokes [main], so a test can
135
+ // import this module.
@@ -0,0 +1,148 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+ import * as Nodefs from "node:fs";
4
+ import * as Nodepath from "node:path";
5
+ import * as Stdlib_Int from "@rescript/runtime/lib/es6/Stdlib_Int.js";
6
+ import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
7
+ import * as Stdlib_Result from "@rescript/runtime/lib/es6/Stdlib_Result.js";
8
+ import * as CliArgs$Reventless from "@reventlessdev/reventless-spec/src/CliArgs.res.mjs";
9
+ import * as Environments$Reventless from "@reventlessdev/reventless-spec/src/types/Environments.res.mjs";
10
+ import * as DeployManifest$ReventlessAws from "./DeployManifest.res.mjs";
11
+
12
+ function parseArgs(argv) {
13
+ return Stdlib_Result.flatMap(Stdlib_Result.flatMap(CliArgs$Reventless.parse([
14
+ "file",
15
+ "manifest",
16
+ "ref",
17
+ "pull-request",
18
+ "base"
19
+ ], ["draft"], undefined, undefined, argv), CliArgs$Reventless.noPositionals), a => {
20
+ let match = CliArgs$Reventless.string(a, "ref");
21
+ let match$1 = CliArgs$Reventless.string(a, "pull-request");
22
+ let match$2 = CliArgs$Reventless.string(a, "base");
23
+ let request;
24
+ if (match !== undefined) {
25
+ request = match$1 !== undefined || match$2 !== undefined ? ({
26
+ TAG: "Error",
27
+ _0: "--ref and --pull-request are two different questions; ask one"
28
+ }) : ({
29
+ TAG: "Ok",
30
+ _0: {
31
+ TAG: "Push",
32
+ _0: match
33
+ }
34
+ });
35
+ } else if (match$1 !== undefined) {
36
+ if (match$2 !== undefined) {
37
+ let number = Stdlib_Int.fromString(match$1, undefined);
38
+ request = number !== undefined ? ({
39
+ TAG: "Ok",
40
+ _0: {
41
+ TAG: "PullRequest",
42
+ number: number,
43
+ base: match$2,
44
+ draft: CliArgs$Reventless.bool(a, "draft")
45
+ }
46
+ }) : ({
47
+ TAG: "Error",
48
+ _0: `--pull-request takes a number, not "` + match$1 + `"`
49
+ });
50
+ } else {
51
+ request = {
52
+ TAG: "Error",
53
+ _0: "--pull-request needs --base, the branch it targets"
54
+ };
55
+ }
56
+ } else {
57
+ request = match$2 !== undefined ? ({
58
+ TAG: "Error",
59
+ _0: "--ref and --pull-request are two different questions; ask one"
60
+ }) : ({
61
+ TAG: "Error",
62
+ _0: "say what deploys: --ref, or --pull-request with --base"
63
+ });
64
+ }
65
+ return Stdlib_Result.map(request, request => ({
66
+ file: CliArgs$Reventless.string(a, "file"),
67
+ manifest: CliArgs$Reventless.string(a, "manifest"),
68
+ request: request
69
+ }));
70
+ });
71
+ }
72
+
73
+ let usage = `
74
+ Usage: resolve-environment (--ref <ref> | --pull-request <n> --base <branch> [--draft])
75
+ [--file <path>] [--manifest <path>]
76
+
77
+ Which environment of the app's environments.yaml a deploy goes to.
78
+
79
+ --ref <ref> A push or a tag: refs/heads/<branch> or refs/tags/<tag>.
80
+ --pull-request <n> A pull request, by number ...
81
+ --base <branch> ... and the branch it targets.
82
+ --draft The pull request is a draft.
83
+ --file <path> The environments file. Defaults to ` + Environments$Reventless.fileName + `
84
+ beside the deploy manifest.
85
+ --manifest <path> The deploy manifest. Defaults to ` + DeployManifest$ReventlessAws.defaultFile + `
86
+ in the working directory.
87
+
88
+ Prints matched, environment, stack and purpose as key=value lines; a deploy that
89
+ matches nothing prints matched=false and exits 0.
90
+ `;
91
+
92
+ function answer(environments, request) {
93
+ let resolved;
94
+ resolved = request.TAG === "Push" ? Stdlib_Option.flatMap(Environments$Reventless.refOf(request._0), ref => Environments$Reventless.resolve(environments, ref)) : Environments$Reventless.resolvePullRequest(environments, request.base, request.number, request.draft);
95
+ if (resolved !== undefined) {
96
+ return [
97
+ "matched=true",
98
+ `environment=` + resolved.name,
99
+ `stack=` + resolved.stack,
100
+ `purpose=` + Environments$Reventless.purposeName(resolved.purpose)
101
+ ];
102
+ } else {
103
+ return ["matched=false"];
104
+ }
105
+ }
106
+
107
+ function run(args) {
108
+ let file = args.file;
109
+ let file$1 = file !== undefined ? file : Environments$Reventless.pathBeside(Stdlib_Option.getOr(args.manifest, Nodepath.join(process.cwd(), DeployManifest$ReventlessAws.defaultFile)));
110
+ if (Nodefs.existsSync(file$1)) {
111
+ return Stdlib_Result.mapError(Stdlib_Result.map(Environments$Reventless.parseFile(file$1), environments => answer(environments, args.request)), message => file$1 + `: ` + message + `. The deploy reads any file of this name beside the deploy manifest as its environments; a file kept there for something else needs another name, or the workflow's environments input pointed elsewhere.`);
112
+ } else {
113
+ return {
114
+ TAG: "Error",
115
+ _0: `no environments file at ` + file$1 + `. Without one every branch deploys to the stack of its own name, and there is nothing to resolve; --file names another path.`
116
+ };
117
+ }
118
+ }
119
+
120
+ let cli = {
121
+ bin: "resolve-environment",
122
+ usage: usage,
123
+ parse: parseArgs
124
+ };
125
+
126
+ function main() {
127
+ return CliArgs$Reventless.run(cli, undefined, undefined, async args => {
128
+ let lines = run(args);
129
+ if (lines.TAG === "Ok") {
130
+ lines._0.forEach(line => {
131
+ console.log(line);
132
+ });
133
+ return;
134
+ }
135
+ console.error(`resolve-environment: ` + lines._0);
136
+ process.exit(1);
137
+ });
138
+ }
139
+
140
+ export {
141
+ parseArgs,
142
+ usage,
143
+ answer,
144
+ run,
145
+ cli,
146
+ main,
147
+ }
148
+ /* node:fs Not a pure module */
@@ -0,0 +1,91 @@
1
+ open JestGlobals
2
+
3
+ // What the deploy workflow appends to $GITHUB_OUTPUT. The resolving itself, and
4
+ // the file's rules, are tested with the format in `spec`'s `EnvironmentsTest`;
5
+ // what is tested here is the command line and the lines it prints, because the
6
+ // workflow reads those as they are.
7
+
8
+ module Resolve = ResolveEnvironment
9
+
10
+ let environments = switch Reventless.Environments.parseString(`environments:
11
+ - { name: review, purpose: review, pullRequestsInto: dev }
12
+ - { name: dev, purpose: dev, branch: dev }
13
+ - { name: production, purpose: production, branch: main, tags: "v*", stack: prod }
14
+ `) {
15
+ | Ok(environments) => environments
16
+ | Error(message) => JsError.throwWithMessage(message)
17
+ }
18
+
19
+ describe("ResolveEnvironment.parseArgs", () => {
20
+ testSync("a ref asks about a push", () =>
21
+ expect(Resolve.parseArgs(["--ref", "refs/heads/dev"])->Result.map(a => a.request))->toEqual(
22
+ Ok(Resolve.Push("refs/heads/dev")),
23
+ )
24
+ )
25
+
26
+ testSync("a pull request needs the branch it targets", () =>
27
+ expect(Resolve.parseArgs(["--pull-request", "7"])->Result.isError)->toBe(true)
28
+ )
29
+
30
+ testSync("a pull request with its base and draft state", () =>
31
+ expect(
32
+ Resolve.parseArgs(["--pull-request", "7", "--base", "dev", "--draft"])->Result.map(
33
+ a => a.request,
34
+ ),
35
+ )->toEqual(Ok(Resolve.PullRequest({number: 7, base: "dev", draft: true})))
36
+ )
37
+
38
+ testSync("a pull request number that is not a number is refused", () =>
39
+ expect(Resolve.parseArgs(["--pull-request", "seven", "--base", "dev"])->Result.isError)->toBe(
40
+ true,
41
+ )
42
+ )
43
+
44
+ testSync("both questions at once are refused", () =>
45
+ expect(
46
+ Resolve.parseArgs([
47
+ "--ref",
48
+ "refs/heads/dev",
49
+ "--pull-request",
50
+ "7",
51
+ "--base",
52
+ "dev",
53
+ ])->Result.isError,
54
+ )->toBe(true)
55
+ )
56
+
57
+ testSync("no question is refused", () =>
58
+ expect(Resolve.parseArgs([])->Result.isError)->toBe(true)
59
+ )
60
+ })
61
+
62
+ describe("ResolveEnvironment.answer", () => {
63
+ testSync("a push to a branch prints its environment, stack and purpose", () =>
64
+ expect(Resolve.answer(environments, Push("refs/heads/main")))->toEqual([
65
+ "matched=true",
66
+ "environment=production",
67
+ "stack=prod",
68
+ "purpose=production",
69
+ ])
70
+ )
71
+
72
+ testSync("a tag deploys where its pattern says", () =>
73
+ expect(Resolve.answer(environments, Push("refs/tags/v1.2.0"))->Array.get(2))->toEqual(
74
+ Some("stack=prod"),
75
+ )
76
+ )
77
+
78
+ testSync("a pull request into dev gets its review stack", () =>
79
+ expect(
80
+ Resolve.answer(environments, PullRequest({number: 7, base: "dev", draft: false})),
81
+ )->toEqual(["matched=true", "environment=review", "stack=review-pr-7", "purpose=review"])
82
+ )
83
+
84
+ testSync("nothing matched is an answer, not an error", () =>
85
+ expect(Resolve.answer(environments, Push("refs/heads/feature/x")))->toEqual(["matched=false"])
86
+ )
87
+
88
+ testSync("a ref that is neither a branch nor a tag matches nothing", () =>
89
+ expect(Resolve.answer(environments, Push("refs/pull/7/merge")))->toEqual(["matched=false"])
90
+ )
91
+ })
@@ -0,0 +1,128 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+ import * as Stdlib_Result from "@rescript/runtime/lib/es6/Stdlib_Result.js";
4
+ import * as Stdlib_JsError from "@rescript/runtime/lib/es6/Stdlib_JsError.js";
5
+ import * as Environments$Reventless from "@reventlessdev/reventless-spec/src/types/Environments.res.mjs";
6
+ import * as ResolveEnvironment$ReventlessAws from "../scripts/ResolveEnvironment.res.mjs";
7
+
8
+ let environments = Environments$Reventless.parseString(`environments:
9
+ - { name: review, purpose: review, pullRequestsInto: dev }
10
+ - { name: dev, purpose: dev, branch: dev }
11
+ - { name: production, purpose: production, branch: main, tags: "v*", stack: prod }
12
+ `);
13
+
14
+ let environments$1;
15
+
16
+ environments$1 = environments.TAG === "Ok" ? environments._0 : Stdlib_JsError.throwWithMessage(environments._0);
17
+
18
+ globalThis.describe("ResolveEnvironment.parseArgs", () => {
19
+ globalThis.test("a ref asks about a push", () => {
20
+ globalThis.expect(Stdlib_Result.map(ResolveEnvironment$ReventlessAws.parseArgs([
21
+ "--ref",
22
+ "refs/heads/dev"
23
+ ]), a => a.request)).toEqual({
24
+ TAG: "Ok",
25
+ _0: {
26
+ TAG: "Push",
27
+ _0: "refs/heads/dev"
28
+ }
29
+ });
30
+ });
31
+ globalThis.test("a pull request needs the branch it targets", () => {
32
+ globalThis.expect(Stdlib_Result.isError(ResolveEnvironment$ReventlessAws.parseArgs([
33
+ "--pull-request",
34
+ "7"
35
+ ]))).toBe(true);
36
+ });
37
+ globalThis.test("a pull request with its base and draft state", () => {
38
+ globalThis.expect(Stdlib_Result.map(ResolveEnvironment$ReventlessAws.parseArgs([
39
+ "--pull-request",
40
+ "7",
41
+ "--base",
42
+ "dev",
43
+ "--draft"
44
+ ]), a => a.request)).toEqual({
45
+ TAG: "Ok",
46
+ _0: {
47
+ TAG: "PullRequest",
48
+ number: 7,
49
+ base: "dev",
50
+ draft: true
51
+ }
52
+ });
53
+ });
54
+ globalThis.test("a pull request number that is not a number is refused", () => {
55
+ globalThis.expect(Stdlib_Result.isError(ResolveEnvironment$ReventlessAws.parseArgs([
56
+ "--pull-request",
57
+ "seven",
58
+ "--base",
59
+ "dev"
60
+ ]))).toBe(true);
61
+ });
62
+ globalThis.test("both questions at once are refused", () => {
63
+ globalThis.expect(Stdlib_Result.isError(ResolveEnvironment$ReventlessAws.parseArgs([
64
+ "--ref",
65
+ "refs/heads/dev",
66
+ "--pull-request",
67
+ "7",
68
+ "--base",
69
+ "dev"
70
+ ]))).toBe(true);
71
+ });
72
+ globalThis.test("no question is refused", () => {
73
+ globalThis.expect(Stdlib_Result.isError(ResolveEnvironment$ReventlessAws.parseArgs([]))).toBe(true);
74
+ });
75
+ });
76
+
77
+ globalThis.describe("ResolveEnvironment.answer", () => {
78
+ globalThis.test("a push to a branch prints its environment, stack and purpose", () => {
79
+ globalThis.expect(ResolveEnvironment$ReventlessAws.answer(environments$1, {
80
+ TAG: "Push",
81
+ _0: "refs/heads/main"
82
+ })).toEqual([
83
+ "matched=true",
84
+ "environment=production",
85
+ "stack=prod",
86
+ "purpose=production"
87
+ ]);
88
+ });
89
+ globalThis.test("a tag deploys where its pattern says", () => {
90
+ globalThis.expect(ResolveEnvironment$ReventlessAws.answer(environments$1, {
91
+ TAG: "Push",
92
+ _0: "refs/tags/v1.2.0"
93
+ })[2]).toEqual("stack=prod");
94
+ });
95
+ globalThis.test("a pull request into dev gets its review stack", () => {
96
+ globalThis.expect(ResolveEnvironment$ReventlessAws.answer(environments$1, {
97
+ TAG: "PullRequest",
98
+ number: 7,
99
+ base: "dev",
100
+ draft: false
101
+ })).toEqual([
102
+ "matched=true",
103
+ "environment=review",
104
+ "stack=review-pr-7",
105
+ "purpose=review"
106
+ ]);
107
+ });
108
+ globalThis.test("nothing matched is an answer, not an error", () => {
109
+ globalThis.expect(ResolveEnvironment$ReventlessAws.answer(environments$1, {
110
+ TAG: "Push",
111
+ _0: "refs/heads/feature/x"
112
+ })).toEqual(["matched=false"]);
113
+ });
114
+ globalThis.test("a ref that is neither a branch nor a tag matches nothing", () => {
115
+ globalThis.expect(ResolveEnvironment$ReventlessAws.answer(environments$1, {
116
+ TAG: "Push",
117
+ _0: "refs/pull/7/merge"
118
+ })).toEqual(["matched=false"]);
119
+ });
120
+ });
121
+
122
+ let Resolve;
123
+
124
+ export {
125
+ Resolve,
126
+ environments$1 as environments,
127
+ }
128
+ /* environments Not a pure module */