@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.
|
|
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.
|
|
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-
|
|
27
|
-
"@reventlessdev/rescript-
|
|
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-
|
|
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,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 */
|