redkite 0.1.7 → 0.1.9

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 (123) hide show
  1. package/README.md +343 -26
  2. package/dist/build.d.ts +2 -0
  3. package/dist/build.d.ts.map +1 -1
  4. package/dist/build.js +11 -1
  5. package/dist/build.js.map +1 -1
  6. package/dist/checks.d.ts.map +1 -1
  7. package/dist/checks.js +4 -0
  8. package/dist/checks.js.map +1 -1
  9. package/dist/cli/agent.d.ts +2 -0
  10. package/dist/cli/agent.d.ts.map +1 -1
  11. package/dist/cli/agent.js +23 -1
  12. package/dist/cli/agent.js.map +1 -1
  13. package/dist/cli/config.d.ts.map +1 -1
  14. package/dist/cli/config.js +15 -2
  15. package/dist/cli/config.js.map +1 -1
  16. package/dist/cli/index.d.ts.map +1 -1
  17. package/dist/cli/index.js +98 -30
  18. package/dist/cli/index.js.map +1 -1
  19. package/dist/config.d.ts.map +1 -1
  20. package/dist/config.js +20 -1
  21. package/dist/config.js.map +1 -1
  22. package/dist/deploy.d.ts +4 -1
  23. package/dist/deploy.d.ts.map +1 -1
  24. package/dist/deploy.js +77 -23
  25. package/dist/deploy.js.map +1 -1
  26. package/dist/dockerfile.js +6 -7
  27. package/dist/dockerfile.js.map +1 -1
  28. package/dist/environment.d.ts +5 -0
  29. package/dist/environment.d.ts.map +1 -0
  30. package/dist/environment.js +20 -0
  31. package/dist/environment.js.map +1 -0
  32. package/dist/host.d.ts +2 -0
  33. package/dist/host.d.ts.map +1 -1
  34. package/dist/host.js +6 -0
  35. package/dist/host.js.map +1 -1
  36. package/dist/index.d.ts +4 -1
  37. package/dist/index.d.ts.map +1 -1
  38. package/dist/index.js +4 -1
  39. package/dist/index.js.map +1 -1
  40. package/dist/localHost.d.ts.map +1 -1
  41. package/dist/localHost.js +2 -0
  42. package/dist/localHost.js.map +1 -1
  43. package/dist/plugin.d.ts +15 -0
  44. package/dist/plugin.d.ts.map +1 -0
  45. package/dist/plugin.js +21 -0
  46. package/dist/plugin.js.map +1 -0
  47. package/dist/plugins/bitwarden.d.ts +11 -0
  48. package/dist/plugins/bitwarden.d.ts.map +1 -0
  49. package/dist/plugins/bitwarden.js +40 -0
  50. package/dist/plugins/bitwarden.js.map +1 -0
  51. package/dist/plugins/digitalOcean.d.ts +19 -0
  52. package/dist/plugins/digitalOcean.d.ts.map +1 -0
  53. package/dist/plugins/digitalOcean.js +71 -0
  54. package/dist/plugins/digitalOcean.js.map +1 -0
  55. package/dist/plugins/index.d.ts +5 -0
  56. package/dist/plugins/index.d.ts.map +1 -0
  57. package/dist/plugins/index.js +5 -0
  58. package/dist/plugins/index.js.map +1 -0
  59. package/dist/plugins/rds.d.ts +14 -0
  60. package/dist/plugins/rds.d.ts.map +1 -0
  61. package/dist/plugins/rds.js +86 -0
  62. package/dist/plugins/rds.js.map +1 -0
  63. package/dist/plugins/snapshot.d.ts +7 -0
  64. package/dist/plugins/snapshot.d.ts.map +1 -0
  65. package/dist/plugins/snapshot.js +29 -0
  66. package/dist/plugins/snapshot.js.map +1 -0
  67. package/dist/presets/nodeApp.d.ts +1 -2
  68. package/dist/presets/nodeApp.d.ts.map +1 -1
  69. package/dist/presets/nodeApp.js +0 -1
  70. package/dist/presets/nodeApp.js.map +1 -1
  71. package/dist/recover.d.ts +19 -0
  72. package/dist/recover.d.ts.map +1 -0
  73. package/dist/recover.js +58 -0
  74. package/dist/recover.js.map +1 -0
  75. package/dist/secrets/store.d.ts +5 -2
  76. package/dist/secrets/store.d.ts.map +1 -1
  77. package/dist/secrets/store.js +25 -14
  78. package/dist/secrets/store.js.map +1 -1
  79. package/dist/source.d.ts +6 -1
  80. package/dist/source.d.ts.map +1 -1
  81. package/dist/source.js +12 -4
  82. package/dist/source.js.map +1 -1
  83. package/dist/sshHost.d.ts +2 -0
  84. package/dist/sshHost.d.ts.map +1 -1
  85. package/dist/sshHost.js +29 -11
  86. package/dist/sshHost.js.map +1 -1
  87. package/dist/steps.d.ts +0 -7
  88. package/dist/steps.d.ts.map +1 -1
  89. package/dist/steps.js +6 -3
  90. package/dist/steps.js.map +1 -1
  91. package/dist/types.d.ts +7 -5
  92. package/dist/types.d.ts.map +1 -1
  93. package/package.json +1 -1
  94. package/src/build.ts +12 -1
  95. package/src/checks.ts +4 -0
  96. package/src/cli/agent.ts +28 -1
  97. package/src/cli/config.ts +19 -2
  98. package/src/cli/index.ts +118 -29
  99. package/src/config.ts +27 -1
  100. package/src/deploy.ts +101 -29
  101. package/src/dockerfile.ts +7 -11
  102. package/src/environment.ts +24 -0
  103. package/src/host.ts +11 -0
  104. package/src/index.ts +4 -1
  105. package/src/localHost.ts +3 -0
  106. package/src/plugin.ts +50 -0
  107. package/src/plugins/bitwarden.ts +57 -0
  108. package/src/plugins/digitalOcean.ts +111 -0
  109. package/src/plugins/index.ts +4 -0
  110. package/src/plugins/rds.ts +126 -0
  111. package/src/plugins/snapshot.ts +44 -0
  112. package/src/presets/nodeApp.ts +1 -3
  113. package/src/recover.ts +90 -0
  114. package/src/secrets/store.ts +39 -20
  115. package/src/source.ts +20 -5
  116. package/src/sshHost.ts +35 -11
  117. package/src/steps.ts +7 -6
  118. package/src/types.ts +29 -12
  119. package/dist/secrets/bitwarden.d.ts +0 -3
  120. package/dist/secrets/bitwarden.d.ts.map +0 -1
  121. package/dist/secrets/bitwarden.js +0 -6
  122. package/dist/secrets/bitwarden.js.map +0 -1
  123. package/src/secrets/bitwarden.ts +0 -7
package/README.md CHANGED
@@ -30,8 +30,10 @@ between deploys.
30
30
  - [Requirements](#requirements)
31
31
  - [Configuration](#configuration)
32
32
  - [Hooks](#hooks)
33
+ - [Plugins](#plugins)
33
34
  - [Verifying a build](#verifying-a-build)
34
35
  - [CLI](#cli)
36
+ - [GitHub Actions](#github-actions)
35
37
  - [How a deploy runs](#how-a-deploy-runs)
36
38
  - [Design](#design)
37
39
  - [Contributing](#contributing)
@@ -147,7 +149,14 @@ export default defineEnvironment({
147
149
  });
148
150
  ```
149
151
 
150
- Redkite finds them by name, so there is no list to keep in step, and
152
+ Redkite finds them by name, so there is no list to keep in step, and anything
153
+ beside the deployment whose name starts with `redkite` and is a module counts:
154
+ `redkite.staging.ts` and `redkite-staging.ts` name the same environment as
155
+ `redkite.staging.config.ts` does. One that was meant to be an environment and
156
+ is named slightly differently is refused rather than passed over as though it
157
+ were not there. The name has to be lower case, because it becomes part of an
158
+ image tag and a tag cannot hold a capital.
159
+
151
160
  `redkite.config.ts` has no `environments` key at all: a second place to put a
152
161
  set of them is a second place for them to disagree. A config that declares one
153
162
  does not compile.
@@ -253,6 +262,28 @@ sits beside the deployment is refused too: it comes from one place or the other.
253
262
  | `files` | Container path to the item whose contents land there |
254
263
  | `volumes` | Volume name to container path, for state that outlives a deploy |
255
264
 
265
+ ### What an app is built from
266
+
267
+ Every cloned app takes the environment's `branch` unless it says otherwise. An
268
+ app can name its own, and can pin instead of tracking:
269
+
270
+ ```ts
271
+ { name: "backend", repo: "…", branch: "release" } // tracks that branch
272
+ { name: "worker", repo: "…", tag: "v1.2.3" } // pinned
273
+ { name: "legacy", repo: "…", commit: "9f2b4c1" } // pinned
274
+ ```
275
+
276
+ At most one of the three, and a config naming two is refused: they are
277
+ different commits and picking one is not redkite's to do.
278
+
279
+ `branch` is looked up under `refs/heads`, `tag` under `refs/tags` and peeled,
280
+ so an annotated tag answers with the commit it points at rather than with the
281
+ tag object. A `commit` is taken as it is and checked that it is one. The
282
+ failure says which kind was missing: *"acme/backend has no tag v9"*.
283
+
284
+ An environment can only say `branch`. A tag or a commit is a claim about one
285
+ repository, and an environment spans every app in the deployment.
286
+
256
287
  ### Building from a directory
257
288
 
258
289
  An app names either a repository to clone or a directory already on this
@@ -276,7 +307,7 @@ the `branch` an environment names is not consulted at all.
276
307
 
277
308
  The release is the content of the working tree, taken with git's own addressing
278
309
  over a scratch index. It covers what is committed, what is modified and what is
279
- untracked, and honours `.gitignore` which is the same set the build reads. So
310
+ untracked, and honours `.gitignore`, which is the same set the build reads. So
280
311
  an edit you never committed is a new release and gets built, and a change under
281
312
  an ignored `node_modules` is not and does not:
282
313
 
@@ -387,6 +418,25 @@ one lockfile for every package in it, so the install has to see all of them,
387
418
  and `node_modules` is where that put it. An app with its own lockfile in a
388
419
  subdirectory is not covered by `dir` alone.
389
420
 
421
+ ### Reaching the deploy host
422
+
423
+ ```ts
424
+ host: { bastion: "deploy@acme.example", hostKeys: "accept-new" }
425
+ ```
426
+
427
+ The host's key is checked before anything is handed to it. `accept-new`, the
428
+ default, trusts it the first time and refuses it if the key ever changes after
429
+ that: no setup, and nothing to intercept once the first deploy has happened.
430
+ `strict` refuses any host not already in `known_hosts`, which is stronger and
431
+ means putting the key there yourself. `off` checks nothing, for a host whose
432
+ address is handed out again and again and only where nothing on the way to it
433
+ can listen.
434
+
435
+ ssh is never left able to ask a question, whichever of the three it is under: a
436
+ prompt nobody is there to answer is a deploy that hangs rather than one that
437
+ fails. Cloning is separate and always `accept-new`, because the deploy host
438
+ reaches GitHub rather than reaching you.
439
+
390
440
  ### Services
391
441
 
392
442
  Long-lived containers shared by the apps. The proxy is not one of them: apps
@@ -428,13 +478,54 @@ An id is a pointer, not a credential, so it belongs in the config while the
428
478
  credentials arrive at deploy time.
429
479
 
430
480
  ```ts
431
- secrets: bitwarden("00000000-0000-4000-8000-000000000001"),
432
- files: { "/app/service-account.json": bitwarden("...") },
481
+ plugins: [bitwarden()],
482
+ // ...
483
+ secrets: bitwarden.item("00000000-0000-4000-8000-000000000001"),
484
+ files: { "/app/service-account.json": bitwarden.item("...") },
433
485
  ```
434
486
 
435
- A deployment reading from Bitwarden wants `BW_CLIENT_ID`, `BW_CLIENT_SECRET` and
436
- `BW_PASSWORD` in the environment. One that does not needs nothing: redkite only
437
- opens the stores your config actually names.
487
+ The vault is a [plugin](#plugins) like any other, so `bitwarden()` has to be
488
+ registered before `bitwarden.item()` resolves to anything. A deployment that
489
+ names a provider nothing registers is refused before it builds, rather than
490
+ reaching for a vault by name.
491
+
492
+ It unlocks with `BW_KEY`, a session obtained elsewhere, and falls back to
493
+ `BW_CLIENT_ID`, `BW_CLIENT_SECRET` and `BW_PASSWORD` when that is not set. A
494
+ config that would rather name its own variable passes the session in:
495
+ `bitwarden({ secrets: process.env.MY_VAULT_SESSION })`. One that reads no
496
+ secrets at all needs none of them: redkite only opens the stores your config
497
+ actually names.
498
+
499
+ #### Where a secret is, and where it is not
500
+
501
+ **Nothing a vault resolves is ever written into an image.** During the build it
502
+ is mounted as `.env` at the app's root for the length of each step and gone
503
+ after it, so a build can read a credential without shipping one, and no layer
504
+ ever holds it. Copying it in and deleting it later would not do: a deleted file
505
+ is still readable in the layer underneath.
506
+
507
+ At runtime it arrives as the container's own environment, written to the host
508
+ and handed to `docker create --env-file`, so no value appears in an argument
509
+ list and the file goes with the rest of the deploy's scratch. Read it from
510
+ `process.env`; there is no `.env` to read.
511
+
512
+ The same is true of the migrations and checks that run in the builder image:
513
+ they are given `--env-file` too, rather than finding a file the build left
514
+ behind.
515
+
516
+ If you do want one in the image, say so, in a build step where the mount is
517
+ still there:
518
+
519
+ ```ts
520
+ steps: ["yarn build", "cp .env dist/.env"],
521
+ ```
522
+
523
+ `files` is the other way to put a credential in an image on purpose, for the
524
+ ones that have to be a file rather than a variable:
525
+
526
+ ```ts
527
+ files: { "/app/service-account.json": bitwarden.item("...") },
528
+ ```
438
529
 
439
530
  ## Hooks
440
531
 
@@ -473,7 +564,7 @@ import { defineStep } from "redkite";
473
564
  export default defineDeployment({
474
565
  // ...
475
566
  steps: [
476
- defineStep("build:after:sourcemaps", async (built, context) => {
567
+ defineStep("build:after:report", async (built, context) => {
477
568
  for (const app of built.apps) {
478
569
  context.task.detail(`${app.name} at ${app.release.slice(0, 7)}`);
479
570
  }
@@ -563,37 +654,181 @@ defineStep("swap:before:seed", async (built, context) => {
563
654
  });
564
655
  ```
565
656
 
566
- ### Plugins
657
+ ### Snapshotting a database before a swap
567
658
 
568
- A plugin is a function answering with steps, the way `redis()` answers with a
569
- service spec:
659
+ A migration that goes wrong is the one thing a blue-green swap cannot undo:
660
+ putting the container back does not put the rows back. These take a snapshot
661
+ first, and they sit at `swap:before` so they run while the old containers are
662
+ still serving.
570
663
 
571
664
  ```ts
572
- const slack = (webhook: string) => [
573
- defineStep("swap:before:announce", async (built) => {
574
- await fetch(webhook, { method: "POST", body: `deploying ${built.apps.length} apps` });
575
- return built;
576
- }),
577
- defineStep("cleanup:after:notify", async (finished) => {
578
- await fetch(webhook, { method: "POST", body: `released ${finished.released.join(", ")}` });
579
- return finished;
580
- }),
581
- ];
665
+ steps: [
666
+ // Above the migrate, because steps run in the order they are listed
667
+ rdsSnapshot({ instance: "acme-production", region: "eu-west-1" }),
668
+ migrate({ app: "backend", command: "yarn db:migrate" }),
669
+ ]
670
+ ```
671
+
672
+ `rdsSnapshot` goes through the AWS CLI, which every runner already has with the
673
+ credentials the job was given; signing a request by hand is a page of crypto
674
+ that nothing here could check. It takes an `instance`, or a `cluster` for
675
+ Aurora, and refuses a config naming both. RDS captures the data when the
676
+ snapshot begins rather than when it finishes, so it does not wait by default:
677
+ `wait: true` turns a snapshot that silently failed into a deploy that stops
678
+ before the migration, at the cost of however long the snapshot takes.
679
+
680
+ ```ts
681
+ digitalOceanSnapshot({ volume: "e7f8...", tokenFrom: "DIGITALOCEAN_TOKEN" })
582
682
  ```
583
683
 
584
- Read whatever it needs where the config is loaded, so a missing value is a
585
- config that fails rather than a deploy that gets most of the way through:
684
+ DigitalOcean's managed databases have no endpoint that takes a snapshot on
685
+ demand: their backups are automatic and the API only lists them. So what this
686
+ snapshots is the block storage `volume` the data sits on, which for redkite's
687
+ own postgres service is the disk under the container, or the `droplet` when the
688
+ database is the whole machine. A volume snapshot of a running Postgres is crash
689
+ consistent rather than clean, which Postgres is built to survive.
690
+
691
+ The token is named rather than given: a config is committed and a token is not.
692
+ Both plugins check what they can before the run starts, so a missing token or a
693
+ config naming two databases fails while the host is still untouched.
694
+
695
+ ## Plugins
696
+
697
+ A plugin is what a deployment opts into. It adds steps to the run, or teaches
698
+ it to resolve a kind of secret, and **nothing it carries happens until the
699
+ config lists it** in `plugins`. Redkite's own vault is one of these rather than
700
+ something wired in behind them, so the rule has no exceptions to remember.
586
701
 
587
702
  ```ts
588
- const webhook = process.env.SLACK_WEBHOOK;
589
- if (!webhook) throw new Error("SLACK_WEBHOOK is not set");
703
+ import { bitwarden, defineDeployment, digitalOceanSnapshot, rdsSnapshot } from "redkite";
590
704
 
591
705
  export default defineDeployment({
706
+ project: "acme",
707
+ plugins: [
708
+ bitwarden(),
709
+ rdsSnapshot({ instance: "acme-production", region: "eu-west-1" }),
710
+ ],
592
711
  // ...
593
- steps: [...slack(webhook)],
594
712
  });
595
713
  ```
596
714
 
715
+ `plan` prints what a deployment opted into and where each plugin's steps land,
716
+ so what a run will do is readable without running it:
717
+
718
+ ```
719
+ plugins
720
+ bitwarden 0 steps resolves bitwarden
721
+ rds-snapshot-acme-db 1 step
722
+
723
+ pipeline (deploy)
724
+ setup redkite
725
+ build redkite
726
+ swap:before:snapshot-acme-db rds-snapshot-acme-db
727
+ swap:before:migrate-backend
728
+ swap redkite
729
+ cleanup redkite
730
+ ```
731
+
732
+ A plugin's steps run above the deployment's own, which is why the snapshot
733
+ lands before the migration written under `steps`. Registering the same plugin
734
+ twice is refused, and so is a second plugin claiming a provider another already
735
+ resolves.
736
+
737
+ The ones redkite ships are `bitwarden()`, [`rdsSnapshot()` and
738
+ `digitalOceanSnapshot()`](#snapshotting-a-database-before-a-swap). None of them
739
+ is on unless you say so.
740
+
741
+ ### Writing plugins
742
+
743
+ A plugin is an object with a name, and steps or stores. `definePlugin` is
744
+ identity, but it checks the points where the plugin is written rather than
745
+ where it is registered, so a typo is the plugin's own failure:
746
+
747
+ ```ts
748
+ import { definePlugin, defineStep, type Plugin } from "redkite";
749
+
750
+ export function announce(options: { url: string }): Plugin {
751
+ return definePlugin({
752
+ name: "announce",
753
+ steps: [
754
+ defineStep("swap:after:announce", async (input, context) => {
755
+ if (!input.ok) return input;
756
+
757
+ context.task.detail(`announcing ${input.released.join(", ")}`);
758
+ await fetch(options.url, { method: "POST", body: input.released.join(",") });
759
+
760
+ return input;
761
+ }),
762
+ ],
763
+ });
764
+ }
765
+ ```
766
+
767
+ The input and output types come from the point: a step at `swap:after` is
768
+ handed what the swap answered with, and must answer with the same, which is
769
+ what makes `input.released` typed without annotating anything.
770
+
771
+ A plugin resolving secrets registers a store per provider tag instead. It is
772
+ opened once, and only when a ref actually names that provider:
773
+
774
+ ```ts
775
+ definePlugin({
776
+ name: "onepassword",
777
+ stores: {
778
+ onepassword: async ({ detail }) => {
779
+ detail("unlocking");
780
+ return { read: async (id: string) => await read(id) };
781
+ },
782
+ },
783
+ });
784
+ ```
785
+
786
+ Then a ref pointing at it is `{ provider: "onepassword", id }`, which is what a
787
+ helper like `bitwarden.item()` answers with.
788
+
789
+ ### As a separate package
790
+
791
+ There is nothing to register: a package exports a function, a config imports it
792
+ and lists what it answers with. The one thing to know is that **a plugin has to
793
+ ship JavaScript**. Node strips types from a config file, but it refuses to do
794
+ so for anything under `node_modules`, so a package shipping `.ts` fails to load
795
+ with `Stripping types is currently unsupported for files under node_modules`.
796
+ Compile it and ship `dist`, the way redkite itself does:
797
+
798
+ ```json
799
+ {
800
+ "name": "redkite-plugin-announce",
801
+ "type": "module",
802
+ "main": "./dist/index.js",
803
+ "types": "./dist/index.d.ts",
804
+ "files": ["dist"],
805
+ "scripts": { "build": "tsc index.ts --outDir dist --declaration" },
806
+ "peerDependencies": { "redkite": ">=0.1.7" }
807
+ }
808
+ ```
809
+
810
+ `redkite` belongs in `peerDependencies` rather than `dependencies`: a plugin
811
+ extends the redkite the deployment is already running, and a second copy of it
812
+ would be a second set of types that do not match.
813
+
814
+ ```sh
815
+ npm install redkite-plugin-announce
816
+ ```
817
+
818
+ ```ts
819
+ import { announce } from "redkite-plugin-announce";
820
+
821
+ plugins: [announce({ url: process.env.SLACK_WEBHOOK ?? "" })],
822
+ ```
823
+
824
+ A complete one is in [examples/plugin](examples/plugin). Two things worth
825
+ copying from it: take what the plugin needs as options rather than reading the
826
+ environment at import time, and name the variable a token comes from rather
827
+ than the token itself, so a config stays committable. Anything a plugin can
828
+ check about its own configuration it should check when it is constructed, so a
829
+ mistake is a config that fails to load rather than a deploy that stops with the
830
+ swap ahead of it.
831
+
597
832
  ## Verifying a build
598
833
 
599
834
  `redkite verify` is the same host, the same services and the same images as a
@@ -664,6 +899,8 @@ redkite <command> [environment]
664
899
  plan [environment] Print the derived topology, the pipeline and the nginx
665
900
  deploy [environment] Build, swap, health check, and revert on failure
666
901
  verify [environment] Bring the services up, build, and run each app's checks
902
+ rollback [environment] Put back any app a run moved and did not finish
903
+ down [environment] Stop everything this environment named
667
904
 
668
905
  --config <path> Defaults to redkite.config.ts at the root of the project
669
906
  --local Build the images here and ship them to the host
@@ -767,6 +1004,86 @@ the CPU and disk it is using. Nothing will clean up after it but you.
767
1004
 
768
1005
  The sixth press leaves.
769
1006
 
1007
+ ## GitHub Actions
1008
+
1009
+ There is a composite action in this repository. `verify` on a pull request,
1010
+ `deploy` on merge:
1011
+
1012
+ ```yaml
1013
+ - uses: actions/checkout@v4
1014
+ - uses: JVKdouk/redkite@v1
1015
+ with:
1016
+ command: deploy
1017
+ environment: production
1018
+ ssh-key: ${{ secrets.DEPLOY_KEY }}
1019
+ env:
1020
+ BW_CLIENT_ID: ${{ secrets.BW_CLIENT_ID }}
1021
+ BW_CLIENT_SECRET: ${{ secrets.BW_CLIENT_SECRET }}
1022
+ BW_PASSWORD: ${{ secrets.BW_PASSWORD }}
1023
+ ```
1024
+
1025
+ Whole workflows are in [examples/actions](examples/actions). The action sets
1026
+ Node up, caches `~/.cache/redkite` so the pinned Bitwarden CLI is installed once
1027
+ rather than every run, loads the key into an agent for the job, and runs a
1028
+ pinned `redkite`.
1029
+
1030
+ The view stands down on its own: it wants a terminal on both stdout and stdin,
1031
+ and a runner has neither, so what a job logs is one line per event.
1032
+
1033
+ A runner's `known_hosts` is empty every time, so the default `accept-new`
1034
+ trusts the deploy host on first sight each run. `hostKeys: "strict"` there means
1035
+ writing the key into `~/.ssh/known_hosts` before the deploy step.
1036
+
1037
+ **The key is only needed where something uses it.** A run that reaches a deploy
1038
+ host, or clones over ssh, wants an agent holding one. A `verify` that builds
1039
+ what the checkout already holds wants nothing: no host to reach, no clone. That
1040
+ is what makes a pull request from a fork's branch testable without handing the
1041
+ job a deploy key.
1042
+
1043
+ **Build on the host, not on the runner.** The obvious move is to point an app at
1044
+ the checkout the job already has, and it is usually the wrong one: a runner is
1045
+ thrown away, so BuildKit starts cold every time and the finished image has to be
1046
+ shipped over ssh. An app that names a `repo` is cloned by the deploy host into a
1047
+ mirror that is already warm, and nothing crosses the wire. Keep `path` for
1048
+ `verify`, where the point is to test the tree in the pull request including what
1049
+ was never pushed.
1050
+
1051
+ **Two runs would race.** Redkite holds no lock, so give the deploy job a
1052
+ `concurrency` group. Leave `cancel-in-progress` false on that one: a deploy
1053
+ interrupted between retiring the old container and starting the new one is the
1054
+ one state nothing downstream can reason about.
1055
+
1056
+ ### Cancelling a run
1057
+
1058
+ A run that is **asked** to stop puts back whatever it moved. Everything from
1059
+ retiring the old container to the health check is one guarded stretch, and an
1060
+ abort anywhere in it reverts the apps that had already moved, on a connection
1061
+ the stop cannot refuse.
1062
+
1063
+ A run that is **killed** never gets that far, which is what a cancelled job is:
1064
+ SIGINT, then the job is torn down after a grace period. So the recovery has to
1065
+ be something a different process can do, reading what the host is in rather
1066
+ than what the dead run remembered. A retired container is the whole signal, and
1067
+ that is what `rollback` looks for:
1068
+
1069
+ ```yaml
1070
+ - if: cancelled()
1071
+ uses: JVKdouk/redkite@v1
1072
+ with:
1073
+ command: rollback
1074
+ environment: production
1075
+ ssh-key: ${{ secrets.DEPLOY_KEY }}
1076
+ ```
1077
+
1078
+ It does nothing when nothing was interrupted, so it is safe to leave in the
1079
+ workflow. `down` is its counterpart for an environment that exists to be built
1080
+ against rather than served from: it stops that environment's containers, the
1081
+ derived proxy included, and stops rather than removes them so the next run
1082
+ adopts them where it left off.
1083
+
1084
+ The build itself is still the one thing a killed job cannot take back with it:
1085
+ it keeps going on the deploy host. Nothing inside the job can change that.
1086
+
770
1087
  ## How a deploy runs
771
1088
 
772
1089
  Everything happens on the deploy host, over a single multiplexed ssh connection
package/dist/build.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import type { Docker } from "./docker.js";
2
+ import type { Ref } from "./source.js";
2
3
  import type { Host } from "./host.js";
3
4
  import type { AppTopology } from "./topology.js";
4
5
  import type { AppSpec } from "./types.js";
@@ -23,5 +24,6 @@ export type BuildResult = {
23
24
  builderTag: string;
24
25
  cached: boolean;
25
26
  };
27
+ export declare function refOf(app: AppSpec, branch: string): Ref;
26
28
  export declare function build(app: AppSpec, topology: AppTopology, context: BuildContext): Promise<BuildResult>;
27
29
  //# sourceMappingURL=build.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../src/build.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEtC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAM1C,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,IAAI,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IAGf,OAAO,CAAC,EAAE;QAAE,IAAI,EAAE,IAAI,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAEzC,GAAG,EAAE,MAAM,CAAC;IAEZ,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAEnC,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACjC,CAAC;AAOF,MAAM,MAAM,WAAW,GAAG;IACxB,OAAO,EAAE,MAAM,CAAC;IAEhB,WAAW,EAAE,MAAM,CAAC;IAEpB,GAAG,EAAE,MAAM,CAAC;IAIZ,UAAU,EAAE,MAAM,CAAC;IAEnB,MAAM,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF,wBAAsB,KAAK,CACzB,GAAG,EAAE,OAAO,EACZ,QAAQ,EAAE,WAAW,EACrB,OAAO,EAAE,YAAY,GACpB,OAAO,CAAC,WAAW,CAAC,CAuFtB"}
1
+ {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../src/build.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEtC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAM1C,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,IAAI,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IAGf,OAAO,CAAC,EAAE;QAAE,IAAI,EAAE,IAAI,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAEzC,GAAG,EAAE,MAAM,CAAC;IAEZ,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAEnC,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACjC,CAAC;AAOF,MAAM,MAAM,WAAW,GAAG;IACxB,OAAO,EAAE,MAAM,CAAC;IAEhB,WAAW,EAAE,MAAM,CAAC;IAEpB,GAAG,EAAE,MAAM,CAAC;IAIZ,UAAU,EAAE,MAAM,CAAC;IAEnB,MAAM,EAAE,OAAO,CAAC;CACjB,CAAC;AAKF,wBAAgB,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,GAAG,CAKvD;AAED,wBAAsB,KAAK,CACzB,GAAG,EAAE,OAAO,EACZ,QAAQ,EAAE,WAAW,EACrB,OAAO,EAAE,YAAY,GACpB,OAAO,CAAC,WAAW,CAAC,CAuFtB"}
package/dist/build.js CHANGED
@@ -6,6 +6,16 @@ import { prepareSource } from "./source.js";
6
6
  // below is what tells a host it already holds an image, and a host that trusts
7
7
  // the commit alone serves the last pipeline's output forever
8
8
  const PIPELINE = "4";
9
+ // The app's own, or the environment's branch when it names none. A branch is
10
+ // the only thing an environment can say, because a tag or a commit is a claim
11
+ // about one repository and an environment spans every app
12
+ export function refOf(app, branch) {
13
+ if (app.tag)
14
+ return { kind: "tag", name: app.tag };
15
+ if (app.commit)
16
+ return { kind: "commit", name: app.commit };
17
+ return { kind: "branch", name: app.branch ?? branch };
18
+ }
9
19
  export async function build(app, topology, context) {
10
20
  const { host, docker } = context;
11
21
  const spec = app.build;
@@ -17,7 +27,7 @@ export async function build(app, topology, context) {
17
27
  // against the deployment file rather than wherever this was run
18
28
  path: app.path && resolve(app.path),
19
29
  include: app.include,
20
- branch: context.branch,
30
+ ref: refOf(app, context.branch),
21
31
  submodules: spec.submodules,
22
32
  detail,
23
33
  });
package/dist/build.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"build.js","sourceRoot":"","sources":["../src/build.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"build.js","sourceRoot":"","sources":["../src/build.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"checks.d.ts","sourceRoot":"","sources":["../src/checks.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAapE,wBAAsB,SAAS,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAajF;AA8BD,wBAAgB,eAAe,CAAC,IAAI,EAAE,IAAI,QAOzC"}
1
+ {"version":3,"file":"checks.d.ts","sourceRoot":"","sources":["../src/checks.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAapE,wBAAsB,SAAS,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAajF;AAiCD,wBAAgB,eAAe,CAAC,IAAI,EAAE,IAAI,QAOzC"}
package/dist/checks.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { envFlags } from "./environment.js";
1
2
  import { appRoot } from "./layout.js";
2
3
  import { quote } from "./shell.js";
3
4
  import { attachment, builderOf } from "./steps.js";
@@ -24,6 +25,9 @@ async function checkApp(app, spec, input, context) {
24
25
  const flags = [
25
26
  "run --rm",
26
27
  ...attachment(spec.network ?? "deployment", context.topology),
28
+ // Before the named settings, so a check can override what the vault says
29
+ // without editing the vault
30
+ ...(await envFlags(app, context)),
27
31
  `--workdir ${appRoot(app.dir)}`,
28
32
  ...settings({ ...app.environment, ...spec.environment }),
29
33
  builderOf(input, app.name),
@@ -1 +1 @@
1
- {"version":3,"file":"checks.js","sourceRoot":"","sources":["../src/checks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAEtC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAGnD,4EAA4E;AAC5E,gFAAgF;AAChF,oDAAoD;AACpD,EAAE;AACF,gFAAgF;AAChF,8EAA8E;AAC9E,0EAA0E;AAE1E,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,KAAY,EAAE,OAAgB;IAC5D,MAAM,OAAO,GAAa,EAAE,CAAC;IAE7B,KAAK,MAAM,GAAG,IAAI,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;QACtC,IAAI,CAAC,GAAG,CAAC,MAAM;YAAE,SAAS;QAE1B,MAAM,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;QAChD,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACzB,CAAC;IAED,4EAA4E;IAC5E,4DAA4D;IAC5D,OAAO,EAAE,GAAG,KAAK,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC;AACrE,CAAC;AAED,KAAK,UAAU,QAAQ,CAAC,GAAY,EAAE,IAAgB,EAAE,KAAY,EAAE,OAAgB;IACpF,MAAM,KAAK,GAAG;QACZ,UAAU;QACV,GAAG,UAAU,CAAC,IAAI,CAAC,OAAO,IAAI,YAAY,EAAE,OAAO,CAAC,QAAQ,CAAC;QAC7D,aAAa,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE;QAC/B,GAAG,QAAQ,CAAC,EAAE,GAAG,GAAG,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;QACxD,SAAS,CAAC,KAAK,EAAE,GAAG,CAAC,IAAI,CAAC;KAC3B,CAAC;IAEF,4EAA4E;IAC5E,qEAAqE;IACrE,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;QACjC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC,CAAC;QAE/C,MAAM,OAAO,CAAC,MAAM,CAAC,UAAU,CAC7B,CAAC,GAAG,KAAK,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAC7C,GAAG,GAAG,CAAC,IAAI,WAAW,OAAO,EAAE,EAC/B,OAAO,CAAC,IAAI,CAAC,IAAI,CAClB,CAAC;IACJ,CAAC;AACH,CAAC;AAED,SAAS,QAAQ,CAAC,WAAmC;IACnD,OAAO,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;AAC1F,CAAC;AAED,yEAAyE;AACzE,mEAAmE;AACnE,MAAM,UAAU,eAAe,CAAC,IAAU;IACxC,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC;QAAE,OAAO;IAEvD,MAAM,IAAI,KAAK,CACb,2DAA2D;QACzD,0DAA0D,CAC7D,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"checks.js","sourceRoot":"","sources":["../src/checks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAEtC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAGnD,4EAA4E;AAC5E,gFAAgF;AAChF,oDAAoD;AACpD,EAAE;AACF,gFAAgF;AAChF,8EAA8E;AAC9E,0EAA0E;AAE1E,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,KAAY,EAAE,OAAgB;IAC5D,MAAM,OAAO,GAAa,EAAE,CAAC;IAE7B,KAAK,MAAM,GAAG,IAAI,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;QACtC,IAAI,CAAC,GAAG,CAAC,MAAM;YAAE,SAAS;QAE1B,MAAM,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;QAChD,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACzB,CAAC;IAED,4EAA4E;IAC5E,4DAA4D;IAC5D,OAAO,EAAE,GAAG,KAAK,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC;AACrE,CAAC;AAED,KAAK,UAAU,QAAQ,CAAC,GAAY,EAAE,IAAgB,EAAE,KAAY,EAAE,OAAgB;IACpF,MAAM,KAAK,GAAG;QACZ,UAAU;QACV,GAAG,UAAU,CAAC,IAAI,CAAC,OAAO,IAAI,YAAY,EAAE,OAAO,CAAC,QAAQ,CAAC;QAC7D,yEAAyE;QACzE,4BAA4B;QAC5B,GAAG,CAAC,MAAM,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QACjC,aAAa,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE;QAC/B,GAAG,QAAQ,CAAC,EAAE,GAAG,GAAG,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;QACxD,SAAS,CAAC,KAAK,EAAE,GAAG,CAAC,IAAI,CAAC;KAC3B,CAAC;IAEF,4EAA4E;IAC5E,qEAAqE;IACrE,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;QACjC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC,CAAC;QAE/C,MAAM,OAAO,CAAC,MAAM,CAAC,UAAU,CAC7B,CAAC,GAAG,KAAK,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAC7C,GAAG,GAAG,CAAC,IAAI,WAAW,OAAO,EAAE,EAC/B,OAAO,CAAC,IAAI,CAAC,IAAI,CAClB,CAAC;IACJ,CAAC;AACH,CAAC;AAED,SAAS,QAAQ,CAAC,WAAmC;IACnD,OAAO,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;AAC1F,CAAC;AAED,yEAAyE;AACzE,mEAAmE;AACnE,MAAM,UAAU,eAAe,CAAC,IAAU;IACxC,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC;QAAE,OAAO;IAEvD,MAAM,IAAI,KAAK,CACb,2DAA2D;QACzD,0DAA0D,CAC7D,CAAC;AACJ,CAAC"}
@@ -1,2 +1,4 @@
1
+ import type { Deployment } from "../types.js";
2
+ export declare function needsAgent(config: Deployment, environment: string): boolean;
1
3
  export declare function requireAgent(warn: (message: string) => void): string;
2
4
  //# sourceMappingURL=agent.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/cli/agent.ts"],"names":[],"mappings":"AAQA,wBAAgB,YAAY,CAAC,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,UAmB3D"}
1
+ {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/cli/agent.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAQ9C,wBAAgB,UAAU,CAAC,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,WAIjE;AAWD,wBAAgB,YAAY,CAAC,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,UA4B3D"}
package/dist/cli/agent.js CHANGED
@@ -1,6 +1,20 @@
1
1
  import { execFileSync } from "node:child_process";
2
+ import { environmentOf } from "../config.js";
2
3
  // Cloning private repositories and opening the tunnel both go through the
3
4
  // agent, so a deploy without one fails halfway rather than at the start
5
+ // Asked before one is demanded. A runner has no keys and no way to be prompted
6
+ // for one, and a deployment that reaches no other machine and clones nothing
7
+ // has no use for an agent: insisting on one there is a green run turned red
8
+ export function needsAgent(config, environment) {
9
+ if (environmentOf(config, environment)?.host?.bastion)
10
+ return true;
11
+ return config.apps.some((app) => app.repo !== undefined && overSsh(app.repo));
12
+ }
13
+ // A clone URL that names a transport of its own carries its own credentials.
14
+ // Anything else is the scp-like form, which is ssh and wants a key
15
+ function overSsh(repo) {
16
+ return !/^(https?|git|file):\/\//.test(repo);
17
+ }
4
18
  // A plain writer rather than a Log, because this runs before the view opens:
5
19
  // ssh-add may ask for a passphrase, and it cannot ask through a screen
6
20
  // something else is drawing
@@ -18,7 +32,15 @@ export function requireAgent(warn) {
18
32
  if (pid)
19
33
  process.env["SSH_AGENT_PID"] = pid;
20
34
  // Inherits stdio so a passphrase prompt reaches the person running this
21
- execFileSync("ssh-add", [], { stdio: "inherit" });
35
+ try {
36
+ execFileSync("ssh-add", [], { stdio: "inherit" });
37
+ }
38
+ catch {
39
+ throw new Error("ssh-add found no key to load. This deployment reaches another machine " +
40
+ "or clones over ssh, so it needs an agent holding a key that can. On a " +
41
+ "runner, set one up before this step and leave SSH_AUTH_SOCK in the " +
42
+ "environment");
43
+ }
22
44
  return socket;
23
45
  }
24
46
  //# sourceMappingURL=agent.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"agent.js","sourceRoot":"","sources":["../../src/cli/agent.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,0EAA0E;AAC1E,wEAAwE;AAExE,6EAA6E;AAC7E,uEAAuE;AACvE,4BAA4B;AAC5B,MAAM,UAAU,YAAY,CAAC,IAA+B;IAC1D,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IAC9C,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAE9B,IAAI,CAAC,4BAA4B,CAAC,CAAC;IAEnC,MAAM,MAAM,GAAG,YAAY,CAAC,WAAW,EAAE,CAAC,IAAI,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;IACvE,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,wBAAwB,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC3D,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,wBAAwB,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAExD,IAAI,CAAC,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;IAElE,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,GAAG,MAAM,CAAC;IACtC,IAAI,GAAG;QAAE,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,GAAG,GAAG,CAAC;IAE5C,wEAAwE;IACxE,YAAY,CAAC,SAAS,EAAE,EAAE,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;IAElD,OAAO,MAAM,CAAC;AAChB,CAAC"}
1
+ {"version":3,"file":"agent.js","sourceRoot":"","sources":["../../src/cli/agent.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAG7C,0EAA0E;AAC1E,wEAAwE;AAExE,+EAA+E;AAC/E,6EAA6E;AAC7E,4EAA4E;AAC5E,MAAM,UAAU,UAAU,CAAC,MAAkB,EAAE,WAAmB;IAChE,IAAI,aAAa,CAAC,MAAM,EAAE,WAAW,CAAC,EAAE,IAAI,EAAE,OAAO;QAAE,OAAO,IAAI,CAAC;IAEnE,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,KAAK,SAAS,IAAI,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;AAChF,CAAC;AAED,6EAA6E;AAC7E,mEAAmE;AACnE,SAAS,OAAO,CAAC,IAAY;IAC3B,OAAO,CAAC,yBAAyB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC/C,CAAC;AAED,6EAA6E;AAC7E,uEAAuE;AACvE,4BAA4B;AAC5B,MAAM,UAAU,YAAY,CAAC,IAA+B;IAC1D,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IAC9C,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAE9B,IAAI,CAAC,4BAA4B,CAAC,CAAC;IAEnC,MAAM,MAAM,GAAG,YAAY,CAAC,WAAW,EAAE,CAAC,IAAI,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;IACvE,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,wBAAwB,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC3D,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,wBAAwB,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAExD,IAAI,CAAC,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;IAElE,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,GAAG,MAAM,CAAC;IACtC,IAAI,GAAG;QAAE,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,GAAG,GAAG,CAAC;IAE5C,wEAAwE;IACxE,IAAI,CAAC;QACH,YAAY,CAAC,SAAS,EAAE,EAAE,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;IACpD,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CACb,wEAAwE;YACtE,wEAAwE;YACxE,qEAAqE;YACrE,aAAa,CAChB,CAAC;IACJ,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/cli/config.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AA2B3D,wBAAsB,UAAU,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAiBvE;AA0CD,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAwB7C;AAGD,wBAAsB,gBAAgB,CAAC,SAAS,EAAE,MAAM,wCAmBvD"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/cli/config.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAmC3D,wBAAsB,UAAU,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAiBvE;AA0CD,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAwB7C;AAGD,wBAAsB,gBAAgB,CAAC,SAAS,EAAE,MAAM,wCA4BvD"}