@quadnix/octo-build 0.1.0 → 0.2.0
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/README.md +108 -21
- package/dist/commands/apply/apply.command.js +32 -38
- package/dist/commands/apply/apply.command.js.map +1 -1
- package/dist/commands/commit/commit.command.d.ts +4 -3
- package/dist/commands/commit/commit.command.js +31 -44
- package/dist/commands/commit/commit.command.js.map +1 -1
- package/dist/commands/create-app/generator-octo-app-template/generators/app/index.js +15 -6
- package/dist/commands/create-app/generator-octo-app-template/generators/app/index.js.map +1 -1
- package/dist/commands/create-app/generator-octo-app-template/generators/app/templates/README.md.ejs +25 -16
- package/dist/commands/create-app/generator-octo-app-template/generators/app/templates/gitignore.ejs +3 -2
- package/dist/commands/create-app/generator-octo-app-template/generators/app/templates/src/aws-dynamodb-service/octo.yaml.ejs +1 -1
- package/dist/commands/create-app/generator-octo-app-template/generators/app/templates/src/aws-ecs-server/octo.yaml.ejs +14 -16
- package/dist/commands/create-app/generator-octo-app-template/generators/app/templates/src/aws-s3-website/octo.yaml.ejs +11 -3
- package/dist/commands/create-model/generator-octo-model-template/generators/app/templates/models/model/model.ts.ejs +38 -0
- package/dist/commands/generate/generate.command.d.ts +3 -1
- package/dist/commands/generate/generate.command.js +12 -12
- package/dist/commands/generate/generate.command.js.map +1 -1
- package/dist/commands/get-response/get-response.command.js +3 -3
- package/dist/commands/get-response/get-response.command.js.map +1 -1
- package/dist/commands/lock/lock.command.d.ts +8 -3
- package/dist/commands/lock/lock.command.js +16 -13
- package/dist/commands/lock/lock.command.js.map +1 -1
- package/dist/commands/run-action/run-action.command.js +4 -10
- package/dist/commands/run-action/run-action.command.js.map +1 -1
- package/dist/commands/unlock/unlock.command.d.ts +5 -5
- package/dist/commands/unlock/unlock.command.js +15 -31
- package/dist/commands/unlock/unlock.command.js.map +1 -1
- package/dist/commands/validate/validate.command.d.ts +1 -1
- package/dist/commands/validate/validate.command.js +9 -15
- package/dist/commands/validate/validate.command.js.map +1 -1
- package/dist/resources/octo-v1.schema.json +25 -11
- package/dist/utilities/definition/yaml/yaml-definition.utility.d.ts +15 -13
- package/dist/utilities/definition/yaml/yaml-definition.utility.js +38 -22
- package/dist/utilities/definition/yaml/yaml-definition.utility.js.map +1 -1
- package/dist/utilities/octo/octo.utility.d.ts +62 -45
- package/dist/utilities/octo/octo.utility.js +162 -128
- package/dist/utilities/octo/octo.utility.js.map +1 -1
- package/package.json +5 -3
package/README.md
CHANGED
|
@@ -1,35 +1,122 @@
|
|
|
1
1
|
# Octo
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Infrastructure as code written as intent: you describe an app and what it needs, modules turn that
|
|
4
|
+
into Terraform, and your own Terragrunt applies it. Users start at
|
|
5
|
+
[octo.quadnix.com](https://octo.quadnix.com/).
|
|
4
6
|
|
|
5
|
-
|
|
7
|
+
> Octo is in `0.x`. Version `1.x` will mark it ready for production.
|
|
6
8
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
> We plan to release version `1.x.x` when it is deemed ready for production use.
|
|
9
|
+
**This README is a set of procedures for working on the repository.** `docs/ARCHITECTURE.md`
|
|
10
|
+
explains what exists, and `docs/CODING-STANDARDS.md` how to add to it.
|
|
10
11
|
|
|
11
|
-
|
|
12
|
+
Requires Node 20 or newer, Terraform or OpenTofu 1.6 or newer, and Terragrunt 0.78 or newer. The
|
|
13
|
+
integration suites also need Docker, and the e2e suites AWS credentials.
|
|
12
14
|
|
|
13
|
-
|
|
15
|
+
---
|
|
14
16
|
|
|
15
|
-
|
|
16
|
-
exact package manager the project expects — you do **not** need to install pnpm yourself.
|
|
17
|
+
## A — Set up this machine
|
|
17
18
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
This repository is a [pnpm](https://pnpm.io) workspace. Corepack reads the `packageManager`
|
|
21
|
-
field in the root `package.json` and uses the pnpm version pinned there, so everyone (and CI)
|
|
22
|
-
runs the same version.
|
|
19
|
+
Once.
|
|
23
20
|
|
|
24
21
|
```sh
|
|
25
|
-
# One-time per machine: activate Corepack so the `pnpm` command uses the pinned version.
|
|
26
22
|
corepack enable
|
|
27
|
-
|
|
28
|
-
# Install all workspace dependencies (packages/*).
|
|
29
23
|
pnpm install
|
|
24
|
+
pnpm run prepare
|
|
30
25
|
```
|
|
31
26
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
27
|
+
`prepare` installs the pre-commit hook, which runs the format check, lint, the build with its type
|
|
28
|
+
check, the circular-dependency check, the secrets spec and the docs code-block check.
|
|
29
|
+
|
|
30
|
+
## B — Build, lint and test
|
|
31
|
+
|
|
32
|
+
```sh
|
|
33
|
+
pnpm run build
|
|
34
|
+
pnpm run lint
|
|
35
|
+
pnpm test
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
`octo-aws-cdk`, `octo-event-listeners`, `octo-build` and `octo-templates` import `octo` from its
|
|
39
|
+
`dist`, and `octo-templates` imports `octo-aws-cdk` the same way. **Rebuild what you changed before
|
|
40
|
+
testing what depends on it**, or the suite runs against the old code and still passes.
|
|
41
|
+
|
|
42
|
+
`pnpm run build` also type-checks every package, tests included, through each package's
|
|
43
|
+
`check:types`.
|
|
44
|
+
|
|
45
|
+
`pnpm run format` writes what `pnpm run format:check` checks. Lint does not check formatting.
|
|
46
|
+
|
|
47
|
+
`pnpm run lint:fix` sorts imports, members and keys. A flag passed through `pnpm run` is written
|
|
48
|
+
without `--`: pnpm forwards the separator, and the script then drops the flag.
|
|
49
|
+
|
|
50
|
+
## C — Run integration tests
|
|
51
|
+
|
|
52
|
+
Integration specs run real Terraform; `octo-templates`' start LocalStack in Docker.
|
|
53
|
+
|
|
54
|
+
```sh
|
|
55
|
+
pnpm run test:integration
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## D — Run an e2e suite
|
|
59
|
+
|
|
60
|
+
**Every e2e suite reaches a live AWS account.** `octo-aws-cdk`'s plan and apply nothing;
|
|
61
|
+
`octo-templates`' create real resources and tear them down.
|
|
62
|
+
|
|
63
|
+
1. Copy the `.env.defaults` beside the suite to `.env` and fill in real values. `.env` is ignored.
|
|
64
|
+
2. Build the packages the suite imports:
|
|
65
|
+
|
|
66
|
+
```sh
|
|
67
|
+
npx nx run-many -t build --projects=octo,octo-event-listeners,octo-aws-cdk
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
3. Run one spec, by path, from its package:
|
|
71
|
+
|
|
72
|
+
```sh
|
|
73
|
+
cd packages/octo-templates
|
|
74
|
+
NODE_OPTIONS=--experimental-vm-modules npx jest --runTestsByPath src/<template>/main.e2e-spec.ts
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Never `pnpm run test:e2e` — it runs every suite live at once. Never combine `-u` with `-t`: jest then
|
|
78
|
+
deletes the snapshots of every test it skipped. A template's own `README.md`, where it has one,
|
|
79
|
+
holds what is particular to it.
|
|
80
|
+
|
|
81
|
+
## E — Work in a worktree
|
|
82
|
+
|
|
83
|
+
For a large change or a hands-free agent run:
|
|
84
|
+
|
|
85
|
+
```sh
|
|
86
|
+
git worktree add ../ai-worktrees/octo-worktree-<branch> -b ai/<branch>
|
|
87
|
+
WORKTREE=../ai-worktrees/octo-worktree-<branch>
|
|
88
|
+
find . -maxdepth 4 -name node_modules -type d ! -path "*/node_modules/*/node_modules" | \
|
|
89
|
+
while read src; do
|
|
90
|
+
mkdir -p "$WORKTREE/$(dirname $src)"
|
|
91
|
+
ln -s "$(pwd)/$src" "$WORKTREE/$src"
|
|
92
|
+
done
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
The symlinks let Nx and Jest resolve packages. Run lint and tests from inside the worktree.
|
|
96
|
+
|
|
97
|
+
## F — Release
|
|
98
|
+
|
|
99
|
+
1. Merge to `main` with PR titles per `.github/jobs/validate-pr-title.job.sh`. The commit type sets
|
|
100
|
+
the bump: `chore` releases nothing.
|
|
101
|
+
2. Run the **Manual Release** workflow on `main`. It versions every changed package, tags, writes
|
|
102
|
+
the changelog, and publishes to npm.
|
|
103
|
+
|
|
104
|
+
## Environment variables
|
|
105
|
+
|
|
106
|
+
Everything outside the code that governs how this repository behaves. A suite's `.env` is read
|
|
107
|
+
through `env-smart`, falling back to the `.env.defaults` beside it.
|
|
108
|
+
|
|
109
|
+
| Variable | Set by | What it does |
|
|
110
|
+
|-----------------------------------------------------------------------------------------------------|-----------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|
111
|
+
| `AWS_ACCOUNT_ID` | a suite's `.env` | The account every e2e suite plans or applies into. |
|
|
112
|
+
| `AWS_REGION_ID` | `packages/octo-aws-cdk/test/.env` | The region the module e2es plan into. Template suites hardcode `us-east-1`. |
|
|
113
|
+
| `OCTO_DEFINITION_FILE_PATH` | the user, or a `create-app` project's scripts | The `octo.yaml` every lifecycle command boots from. `OctoCliUtility` sets it for the CLI-driven template suites. A relative path is resolved once against the working directory, so `run-action` callbacks find it. |
|
|
114
|
+
| `OCTO_JOURNAL_COMMAND_ID` | `JournalEventListener` | The running command's id, set for every process it starts, so a `run-action` that Terraform starts mid-apply names that apply as `parentCommandId` in its journal. |
|
|
115
|
+
| `TF_VAR_OCTO_PROJECT_ROOT` | `TerraformUtility`, unless already set | The working directory, so `terraform.localPath()` paths resolve inside Terragrunt's cache copy of a folder. |
|
|
116
|
+
| `TG_LOG_CUSTOM_FORMAT` | `TerraformUtility`, always | Terragrunt's log line layout, its default without the time, since the journal records when each line arrived. |
|
|
117
|
+
| `TG_LOG_FORMAT` | `TerraformUtility`, always unset | Unset for every Terragrunt process, so it cannot override `TG_LOG_CUSTOM_FORMAT`. |
|
|
118
|
+
| `TG_PROVIDER_CACHE` | `TerraformUtility`, unless already set | `1`, so Terragrunt shares one provider cache across folders. |
|
|
119
|
+
| `TG_TF_PATH` | `TerraformUtility`, from `--terraformBinary` | Which Terraform or OpenTofu binary Terragrunt runs. |
|
|
120
|
+
| `NODE_OPTIONS` | every package's test scripts | `--experimental-vm-modules`, which Jest needs to run ESM. Set it yourself when running `jest` directly. |
|
|
121
|
+
| `OCTO_STAGE`, `OCTO_PHASE`, `OCTO_NAT`, `OCTO_TARGET`, `OCTO_WORK`, `OCTO_CASE`, `OCTO_PROBE_STATE` | you, by hand | Drive the `aws-ecs-server` debugging harnesses; that template's `README.md` describes each. |
|
|
122
|
+
| `GH_TOKEN` | a repository secret | Checkout and push in **Manual Release**, and the tags and GitHub releases `nx release` creates. |
|
|
@@ -1,34 +1,41 @@
|
|
|
1
1
|
import { resolve } from 'path';
|
|
2
2
|
import { Container, StateManagementService, TerraformUtility } from '@quadnix/octo';
|
|
3
3
|
import chalk from 'chalk';
|
|
4
|
-
import {
|
|
4
|
+
import { OctoUtility } from '../../utilities/octo/octo.utility.js';
|
|
5
5
|
/**
|
|
6
|
-
* Plans the directory and prints anything the apply would destroy
|
|
6
|
+
* Plans the directory and prints anything the apply would destroy, marking each destroy of a resource
|
|
7
|
+
* the last commit recorded as losing data.
|
|
7
8
|
*
|
|
8
|
-
* Returns
|
|
9
|
-
*
|
|
9
|
+
* Returns why the apply must not proceed: something would be destroyed, or a folder would not plan and
|
|
10
|
+
* so nothing can be said about what it would destroy. Returns `undefined` when it may.
|
|
10
11
|
*/
|
|
11
|
-
async function
|
|
12
|
+
async function findDestroyRefusal(terraformUtility, stateManagementService, resolvedDir) {
|
|
12
13
|
const { errors, plans } = await terraformUtility.plan(resolvedDir, { json: true });
|
|
13
14
|
if (errors.size > 0) {
|
|
14
15
|
for (const [moduleId, error] of errors.entries()) {
|
|
15
16
|
console.error(chalk.red(`ERROR [${moduleId}] Terraform failed to plan:\n${error}`));
|
|
16
17
|
}
|
|
17
|
-
|
|
18
|
-
'Fix them, or pass --auto-approve to apply anyway
|
|
19
|
-
return true;
|
|
18
|
+
return ('Cannot check this apply for destroys because the folders above would not plan. ' +
|
|
19
|
+
'Fix them, or pass --auto-approve to apply anyway!');
|
|
20
20
|
}
|
|
21
21
|
const destroys = terraformUtility.findPlannedDestroys(plans);
|
|
22
22
|
if (destroys.length === 0) {
|
|
23
|
-
return
|
|
23
|
+
return undefined;
|
|
24
24
|
}
|
|
25
|
+
// Find the addresses whose destroy loses data.
|
|
26
|
+
const { userData } = await stateManagementService.getResourceState(stateManagementService.actualResourceStateFileName);
|
|
27
|
+
const dataLossAddresses = new Set((userData.terraformResources ?? [])
|
|
28
|
+
.filter((mapping) => mapping.destroyLosesData)
|
|
29
|
+
.flatMap((mapping) => mapping.terraformAddresses.map((address) => `${mapping.moduleId} ${address}`)));
|
|
25
30
|
console.error(chalk.red('This apply would DESTROY:'));
|
|
26
31
|
for (const destroy of destroys.sort((a, b) => a.address.localeCompare(b.address))) {
|
|
27
|
-
|
|
32
|
+
const dataLoss = dataLossAddresses.has(`${destroy.moduleId} ${destroy.address}`)
|
|
33
|
+
? ' - the data it holds is lost with it'
|
|
34
|
+
: '';
|
|
35
|
+
console.error(chalk.red(` [${destroy.moduleId}] ${destroy.address} (${destroy.tfActions.join(', ')})${dataLoss}`));
|
|
28
36
|
}
|
|
29
|
-
|
|
30
|
-
'then re-run with --auto-approve to proceed
|
|
31
|
-
return true;
|
|
37
|
+
return ('Refusing to apply. Run "octo validate" to see why each of these is being destroyed, ' +
|
|
38
|
+
'then re-run with --auto-approve to proceed!');
|
|
32
39
|
}
|
|
33
40
|
/**
|
|
34
41
|
* Step 3 of the octo lifecycle, and the only one that changes live infrastructure.
|
|
@@ -79,9 +86,9 @@ export const applyCommand = {
|
|
|
79
86
|
handler: async (argv) => {
|
|
80
87
|
const { autoApprove, lockId, terraformBinary, terragruntBinary, terragruntDir, timeoutInMs } = argv;
|
|
81
88
|
const resolvedDir = resolve(process.cwd(), terragruntDir);
|
|
82
|
-
prepareCallbackEnvironment();
|
|
83
|
-
|
|
84
|
-
await bootStateProvider();
|
|
89
|
+
OctoUtility.prepareCallbackEnvironment();
|
|
90
|
+
await OctoUtility.runCommand('apply', async () => {
|
|
91
|
+
const { stateCheckInIntervalInMs } = await OctoUtility.bootStateProvider();
|
|
85
92
|
// The lock is verified before anything is planned, so a run without it fails having done
|
|
86
93
|
// nothing. It is released by `octo commit`, not here - the apply is the middle of a run.
|
|
87
94
|
const stateManagementService = await Container.getInstance().get(StateManagementService);
|
|
@@ -89,30 +96,22 @@ export const applyCommand = {
|
|
|
89
96
|
throw new Error('App is not locked! Run "octo lock" first.');
|
|
90
97
|
}
|
|
91
98
|
const terraformUtility = await Container.getInstance().get(TerraformUtility, {
|
|
92
|
-
args: [{ terraformBinary, terragruntBinary, timeoutInMs }, true],
|
|
99
|
+
args: [{ stateCheckInIntervalInMs, terraformBinary, terragruntBinary, timeoutInMs }, true],
|
|
93
100
|
});
|
|
94
101
|
// The underlying apply runs `-auto-approve` and validate is optional, so without an explicit
|
|
95
102
|
// opt-in, plan first and refuse to destroy anything the user has not been shown. What is at
|
|
96
103
|
// stake is the data inside a resource terraform recreates; octo's own state stays consistent
|
|
97
104
|
// either way.
|
|
98
|
-
|
|
99
|
-
|
|
105
|
+
const refusal = autoApprove
|
|
106
|
+
? undefined
|
|
107
|
+
: await findDestroyRefusal(terraformUtility, stateManagementService, resolvedDir);
|
|
108
|
+
if (refusal !== undefined) {
|
|
109
|
+
throw new Error(refusal);
|
|
100
110
|
}
|
|
101
111
|
else {
|
|
102
|
-
//
|
|
103
|
-
// own progress is the only sign it is alive. `apply` boots no octo and so has no listeners,
|
|
104
|
-
// which makes this the only writer here - nothing to interleave with.
|
|
112
|
+
// Terragrunt's output goes out as events as it is written, which the listeners print and record.
|
|
105
113
|
try {
|
|
106
|
-
await terraformUtility.apply(resolvedDir
|
|
107
|
-
onOutput: (chunk, stream) => {
|
|
108
|
-
if (stream === 'stdout') {
|
|
109
|
-
process.stdout.write(chunk);
|
|
110
|
-
}
|
|
111
|
-
else {
|
|
112
|
-
process.stderr.write(chunk);
|
|
113
|
-
}
|
|
114
|
-
},
|
|
115
|
-
});
|
|
114
|
+
await terraformUtility.apply(resolvedDir);
|
|
116
115
|
}
|
|
117
116
|
catch (error) {
|
|
118
117
|
// An apply that got this far may have built some of what was asked for, and only a commit
|
|
@@ -124,13 +123,8 @@ export const applyCommand = {
|
|
|
124
123
|
'what failed and run again.'));
|
|
125
124
|
throw error;
|
|
126
125
|
}
|
|
127
|
-
console.log(chalk.green('==== Apply complete ===='));
|
|
128
126
|
}
|
|
129
|
-
}
|
|
130
|
-
catch (error) {
|
|
131
|
-
reportError(error);
|
|
132
|
-
process.exit(1);
|
|
133
|
-
}
|
|
127
|
+
});
|
|
134
128
|
},
|
|
135
129
|
};
|
|
136
130
|
//# sourceMappingURL=apply.command.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"apply.command.js","sourceRoot":"","sources":["../../../src/commands/apply/apply.command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAC/B,OAAO,EAAE,SAAS,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACpF,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"apply.command.js","sourceRoot":"","sources":["../../../src/commands/apply/apply.command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAC/B,OAAO,EAAE,SAAS,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACpF,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,WAAW,EAAE,MAAM,sCAAsC,CAAC;AAWnE;;;;;;GAMG;AACH,KAAK,UAAU,kBAAkB,CAC/B,gBAAkC,EAClC,sBAA8C,EAC9C,WAAmB;IAEnB,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,gBAAgB,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IAEnF,IAAI,MAAM,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;QACpB,KAAK,MAAM,CAAC,QAAQ,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,EAAE,EAAE,CAAC;YACjD,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,QAAQ,gCAAgC,KAAK,EAAE,CAAC,CAAC,CAAC;QACtF,CAAC;QAED,OAAO,CACL,iFAAiF;YACjF,mDAAmD,CACpD,CAAC;IACJ,CAAC;IAED,MAAM,QAAQ,GAAG,gBAAgB,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC;IAC7D,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,+CAA+C;IAC/C,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,sBAAsB,CAAC,gBAAgB,CAChE,sBAAsB,CAAC,2BAA2B,CACnD,CAAC;IACF,MAAM,iBAAiB,GAAG,IAAI,GAAG,CAC/B,CAAC,QAAQ,CAAC,kBAAkB,IAAI,EAAE,CAAC;SAChC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,gBAAgB,CAAC;SAC7C,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,GAAG,OAAO,CAAC,QAAQ,IAAI,OAAO,EAAE,CAAC,CAAC,CACvG,CAAC;IAEF,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAC,CAAC;IAEtD,KAAK,MAAM,OAAO,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC;QAClF,MAAM,QAAQ,GAAG,iBAAiB,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;YAC9E,CAAC,CAAC,sCAAsC;YACxC,CAAC,CAAC,EAAE,CAAC;QACP,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,OAAO,KAAK,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,QAAQ,EAAE,CAAC,CAAC,CAAC;IACtH,CAAC;IAED,OAAO,CACL,sFAAsF;QACtF,6CAA6C,CAC9C,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,OAAO,EAAE,CAAC,KAAW,EAAQ,EAAE;QAC7B,OAAO,KAAK;aACT,MAAM,CAAC,eAAe,EAAE;YACvB,YAAY,EAAE,IAAI;YAClB,WAAW,EAAE,8CAA8C;YAC3D,IAAI,EAAE,QAAQ;SACf,CAAC;aACD,MAAM,CAAC,QAAQ,EAAE;YAChB,YAAY,EAAE,IAAI;YAClB,WAAW,EAAE,yEAAyE;YACtF,IAAI,EAAE,QAAQ;SACf,CAAC;aACD,MAAM,CAAC,aAAa,EAAE;YACrB,OAAO,EAAE,KAAK;YACd,YAAY,EAAE,KAAK;YACnB,WAAW,EAAE,mFAAmF;YAChG,IAAI,EAAE,SAAS;SAChB,CAAC;aACD,MAAM,CAAC,iBAAiB,EAAE;YACzB,YAAY,EAAE,KAAK;YACnB,WAAW,EAAE,gFAAgF;YAC7F,IAAI,EAAE,QAAQ;SACf,CAAC;aACD,MAAM,CAAC,kBAAkB,EAAE;YAC1B,YAAY,EAAE,KAAK;YACnB,WAAW,EAAE,gDAAgD;YAC7D,IAAI,EAAE,QAAQ;SACf,CAAC;aACD,MAAM,CAAC,aAAa,EAAE;YACrB,YAAY,EAAE,KAAK;YACnB,WAAW,EAAE,oDAAoD;YACjE,IAAI,EAAE,QAAQ;SACf,CAAC,CAAC;IACP,CAAC;IACD,OAAO,EAAE,OAAO;IAChB,QAAQ,EAAE,oEAAoE;IAC9E,OAAO,EAAE,KAAK,EAAE,IAA+C,EAAiB,EAAE;QAChF,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,eAAe,EAAE,gBAAgB,EAAE,aAAa,EAAE,WAAW,EAAE,GAAG,IAAI,CAAC;QACpG,MAAM,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,aAAa,CAAC,CAAC;QAE1D,WAAW,CAAC,0BAA0B,EAAE,CAAC;QAEzC,MAAM,WAAW,CAAC,UAAU,CAAC,OAAO,EAAE,KAAK,IAAI,EAAE;YAC/C,MAAM,EAAE,wBAAwB,EAAE,GAAG,MAAM,WAAW,CAAC,iBAAiB,EAAE,CAAC;YAE3E,yFAAyF;YACzF,yFAAyF;YACzF,MAAM,sBAAsB,GAAG,MAAM,SAAS,CAAC,WAAW,EAAE,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;YACzF,IAAI,CAAC,CAAC,MAAM,sBAAsB,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC;gBACxD,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;YAC/D,CAAC;YAED,MAAM,gBAAgB,GAAG,MAAM,SAAS,CAAC,WAAW,EAAE,CAAC,GAAG,CAAwB,gBAAgB,EAAE;gBAClG,IAAI,EAAE,CAAC,EAAE,wBAAwB,EAAE,eAAe,EAAE,gBAAgB,EAAE,WAAW,EAAE,EAAE,IAAI,CAAC;aAC3F,CAAC,CAAC;YAEH,6FAA6F;YAC7F,4FAA4F;YAC5F,6FAA6F;YAC7F,cAAc;YACd,MAAM,OAAO,GAAG,WAAW;gBACzB,CAAC,CAAC,SAAS;gBACX,CAAC,CAAC,MAAM,kBAAkB,CAAC,gBAAgB,EAAE,sBAAsB,EAAE,WAAW,CAAC,CAAC;YACpF,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;gBAC1B,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC;YAC3B,CAAC;iBAAM,CAAC;gBACN,iGAAiG;gBACjG,IAAI,CAAC;oBACH,MAAM,gBAAgB,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;gBAC5C,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,0FAA0F;oBAC1F,yFAAyF;oBACzF,sFAAsF;oBACtF,WAAW;oBACX,OAAO,CAAC,KAAK,CACX,KAAK,CAAC,GAAG,CACP,qFAAqF;wBACnF,mBAAmB,aAAa,aAAa,MAAM,kDAAkD;wBACrG,4BAA4B,CAC/B,CACF,CAAC;oBACF,MAAM,KAAK,CAAC;gBACd,CAAC;YACH,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;CACF,CAAC"}
|
|
@@ -8,10 +8,11 @@ type CommitCommandArguments = {
|
|
|
8
8
|
timeoutInMs?: number;
|
|
9
9
|
};
|
|
10
10
|
/**
|
|
11
|
-
* Step 4 of the octo lifecycle. See
|
|
11
|
+
* Step 4 of the octo lifecycle. See `Octo.commit()`.
|
|
12
12
|
*
|
|
13
|
-
* This is the command that ends a run, so
|
|
14
|
-
*
|
|
13
|
+
* This is the command that ends a run, so a commit that succeeds releases the app lock. One that
|
|
14
|
+
* fails keeps it, and is run again with the same lock ID. Octo never unlocks on its own; the lock is
|
|
15
|
+
* the CLI's to take and to drop.
|
|
15
16
|
*/
|
|
16
17
|
export declare const commitCommand: {
|
|
17
18
|
builder: (yargs: Argv) => Argv;
|
|
@@ -1,24 +1,25 @@
|
|
|
1
1
|
import { resolve } from 'path';
|
|
2
2
|
import { Container, StateManagementService, TerraformUtility } from '@quadnix/octo';
|
|
3
3
|
import chalk from 'chalk';
|
|
4
|
-
import {
|
|
4
|
+
import { OctoUtility } from '../../utilities/octo/octo.utility.js';
|
|
5
5
|
/**
|
|
6
|
-
* Step 4 of the octo lifecycle. See
|
|
6
|
+
* Step 4 of the octo lifecycle. See `Octo.commit()`.
|
|
7
7
|
*
|
|
8
|
-
* This is the command that ends a run, so
|
|
9
|
-
*
|
|
8
|
+
* This is the command that ends a run, so a commit that succeeds releases the app lock. One that
|
|
9
|
+
* fails keeps it, and is run again with the same lock ID. Octo never unlocks on its own; the lock is
|
|
10
|
+
* the CLI's to take and to drop.
|
|
10
11
|
*/
|
|
11
12
|
export const commitCommand = {
|
|
12
13
|
builder: (yargs) => {
|
|
13
14
|
return yargs
|
|
14
15
|
.option('terragruntDir', {
|
|
15
16
|
demandOption: true,
|
|
16
|
-
description: 'The generated Terragrunt directory, post apply (`terragrunt run
|
|
17
|
+
description: 'The generated Terragrunt directory, post apply (`terragrunt run --all -- apply`).',
|
|
17
18
|
type: 'string',
|
|
18
19
|
})
|
|
19
20
|
.option('lockId', {
|
|
20
21
|
demandOption: true,
|
|
21
|
-
description: 'The app lock ID from `octo lock`. Released when
|
|
22
|
+
description: 'The app lock ID from `octo lock`. Released when the commit succeeds.',
|
|
22
23
|
type: 'string',
|
|
23
24
|
})
|
|
24
25
|
.option('partial', {
|
|
@@ -48,47 +49,33 @@ export const commitCommand = {
|
|
|
48
49
|
handler: async (argv) => {
|
|
49
50
|
const { lockId, partial, terraformBinary, terragruntBinary, terragruntDir, timeoutInMs } = argv;
|
|
50
51
|
const resolvedDir = resolve(process.cwd(), terragruntDir);
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
//
|
|
58
|
-
//
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
// is warned and omitted rather than aborting the commit: octo rejects the commit itself if
|
|
67
|
-
// that folder held a module it tracks, and merely warns if it is a folder octo does not know.
|
|
68
|
-
const [outputs, moduleIds] = await Promise.all([
|
|
69
|
-
terraformUtility.output(resolvedDir, { json: true }),
|
|
70
|
-
terraformUtility.listModuleFolders(resolvedDir),
|
|
71
|
-
]);
|
|
72
|
-
for (const moduleId of moduleIds) {
|
|
73
|
-
if (!outputs.has(moduleId)) {
|
|
74
|
-
console.error(chalk.yellow(`WARN [${moduleId}] Could not read terraform outputs`));
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
const { warnings } = await octo.commit(app, { lockId, outputs, partial });
|
|
78
|
-
for (const warning of warnings) {
|
|
79
|
-
console.error(chalk.yellow(`WARN ${warning.moduleId ? `[${warning.moduleId}] ` : ''}${warning.message}`));
|
|
52
|
+
await OctoUtility.runCommand('commit', async () => {
|
|
53
|
+
const { app, octo } = await OctoUtility.bootOcto();
|
|
54
|
+
const terraformUtility = await Container.getInstance().get(TerraformUtility, {
|
|
55
|
+
args: [{ terraformBinary, terragruntBinary, timeoutInMs }, true],
|
|
56
|
+
});
|
|
57
|
+
// Read outputs from every folder terragrunt discovers. A folder whose outputs cannot be read
|
|
58
|
+
// is warned and omitted rather than aborting the commit: octo rejects the commit itself if
|
|
59
|
+
// that folder held a module it tracks, and merely warns if it is a folder octo does not know.
|
|
60
|
+
const [outputs, moduleIds] = await Promise.all([
|
|
61
|
+
terraformUtility.output(resolvedDir, { json: true }),
|
|
62
|
+
terraformUtility.listModuleFolders(resolvedDir),
|
|
63
|
+
]);
|
|
64
|
+
for (const moduleId of moduleIds) {
|
|
65
|
+
if (!outputs.has(moduleId)) {
|
|
66
|
+
console.error(chalk.yellow(`WARN [${moduleId}] Could not read terraform outputs`));
|
|
80
67
|
}
|
|
81
|
-
// No verdict printed here - the listeners own stdout and render the commit report there.
|
|
82
|
-
// The warnings above stay, on stderr: a different fd, so they cannot interleave with pino.
|
|
83
68
|
}
|
|
84
|
-
|
|
85
|
-
|
|
69
|
+
const { warnings } = await octo.commit(app, { lockId, outputs, partial });
|
|
70
|
+
for (const warning of warnings) {
|
|
71
|
+
console.error(chalk.yellow(`WARN ${warning.moduleId ? `[${warning.moduleId}] ` : ''}${warning.message}`));
|
|
86
72
|
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
73
|
+
// Release the lock once the run is recorded. A failed commit keeps it for the re-run.
|
|
74
|
+
const stateManagementService = await Container.getInstance().get(StateManagementService);
|
|
75
|
+
await stateManagementService.unlockApp(lockId);
|
|
76
|
+
// No verdict printed here - the listeners render the commit report on stderr, beside the
|
|
77
|
+
// warnings above.
|
|
78
|
+
});
|
|
92
79
|
},
|
|
93
80
|
};
|
|
94
81
|
//# sourceMappingURL=commit.command.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"commit.command.js","sourceRoot":"","sources":["../../../src/commands/commit/commit.command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAC/B,OAAO,EAAE,SAAS,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACpF,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"commit.command.js","sourceRoot":"","sources":["../../../src/commands/commit/commit.command.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
import { readdir, stat } from 'fs/promises';
|
|
2
2
|
import { join, resolve } from 'path';
|
|
3
3
|
import Generator, {} from 'yeoman-generator';
|
|
4
|
+
/**
|
|
5
|
+
* Every octo package is pre-1.0 and released independently, so a new app tracks the whole `0.x`
|
|
6
|
+
* line rather than naming a version that goes stale the next time one of them ships. Revisit on
|
|
7
|
+
* the first 1.0.
|
|
8
|
+
*
|
|
9
|
+
* @internal
|
|
10
|
+
*/
|
|
11
|
+
const OCTO_VERSION_RANGE = '0.x.x';
|
|
4
12
|
/**
|
|
5
13
|
* @internal
|
|
6
14
|
*/
|
|
@@ -52,8 +60,9 @@ export default class extends Generator {
|
|
|
52
60
|
// on PATH - which is what the `octo run-action` callback terraform makes mid-apply needs.
|
|
53
61
|
this.log(' npm run octo:generate');
|
|
54
62
|
this.log(' npm run octo:validate # optional');
|
|
55
|
-
this.log(' npm run octo:
|
|
56
|
-
this.log(' npm run octo:
|
|
63
|
+
this.log(' LOCK_ID=$(npm run --silent octo:lock)');
|
|
64
|
+
this.log(' npm run octo:apply -- --lockId $LOCK_ID');
|
|
65
|
+
this.log(' npm run octo:commit -- --lockId $LOCK_ID');
|
|
57
66
|
this.log(' See README.md for the full flow.');
|
|
58
67
|
}
|
|
59
68
|
/**
|
|
@@ -95,10 +104,10 @@ export default class extends Generator {
|
|
|
95
104
|
version: '0.0.1',
|
|
96
105
|
});
|
|
97
106
|
await this.addDependencies({
|
|
98
|
-
'@quadnix/octo':
|
|
99
|
-
'@quadnix/octo-aws-cdk':
|
|
100
|
-
'@quadnix/octo-build':
|
|
101
|
-
'@quadnix/octo-event-listeners':
|
|
107
|
+
'@quadnix/octo': OCTO_VERSION_RANGE,
|
|
108
|
+
'@quadnix/octo-aws-cdk': OCTO_VERSION_RANGE,
|
|
109
|
+
'@quadnix/octo-build': OCTO_VERSION_RANGE,
|
|
110
|
+
'@quadnix/octo-event-listeners': OCTO_VERSION_RANGE,
|
|
102
111
|
});
|
|
103
112
|
await this.addDevDependencies({
|
|
104
113
|
'@eslint/js': '^9.33.0',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../src/commands/create-app/generator-octo-app-template/generators/app/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAE5C,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACrC,OAAO,SAAS,EAAE,EAAoB,MAAM,kBAAkB,CAAC;AAE/D;;GAEG;AACH,MAAM,CAAC,OAAO,MAAO,SAAQ,SAAS;IAOpC;;OAEG;IACH,YAAY,IAAc,EAAE,IAAiB;QAC3C,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE;YAChB,2FAA2F;YAC3F,6FAA6F;YAC7F,4FAA4F;YAC5F,6FAA6F;YAC7F,iBAAiB,EAAE,KAAK,EAAE,kBAAsC,EAAE,cAAsC,EAAE,EAAE;gBAC1G,uFAAuF;gBACvF,0EAA0E;gBAC1E,IAAI,CAAC,cAAc,GAAG,GAAG,kBAAkB,IAAI,KAAK,UAAU,CAAC;gBAE/D,IAAI,CAAC;oBACH,MAAM,cAAc,EAAE,CAAC;oBACvB,IAAI,CAAC,cAAc,GAAG,SAAS,CAAC;gBAClC,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,IAAI,CAAC,GAAG,CAAC,uCAAuC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;oBACjE,IAAI,CAAC,GAAG,CAAC,iCAAiC,IAAI,CAAC,cAAc,kCAAkC,CAAC,CAAC;gBACnG,CAAC;YACH,CAAC;SACF,CAAC,CAAC;QAEH,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACvB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACvB,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IAC7B,CAAC;IAED;;OAEG;IACH,GAAG;QACD,MAAM,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;QAE7D,IAAI,CAAC,GAAG,CAAC,wDAAwD,CAAC,CAAC;QACnE,IAAI,CAAC,GAAG,CAAC,sBAAsB,UAAU,EAAE,CAAC,CAAC;QAC7C,IAAI,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;QAC3B,IAAI,CAAC,GAAG,CAAC,SAAS,UAAU,EAAE,CAAC,CAAC;QAChC,oFAAoF;QACpF,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACxB,IAAI,CAAC,GAAG,CAAC,MAAM,IAAI,CAAC,cAAc,EAAE,CAAC,CAAC;QACxC,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,uCAAuC,CAAC,CAAC;QAClD,IAAI,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;QAC7B,2FAA2F;QAC3F,+FAA+F;QAC/F,0FAA0F;QAC1F,IAAI,CAAC,GAAG,CAAC,0BAA0B,CAAC,CAAC;QACrC,IAAI,CAAC,GAAG,CAAC,uCAAuC,CAAC,CAAC;QAClD,IAAI,CAAC,GAAG,CAAC,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../src/commands/create-app/generator-octo-app-template/generators/app/index.ts"],"names":[],"mappings":"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"}
|
package/dist/commands/create-app/generator-octo-app-template/generators/app/templates/README.md.ejs
CHANGED
|
@@ -19,8 +19,7 @@ It contains all the modules you want to run,
|
|
|
19
19
|
which will create your infrastructure resources as per the module's instructions.
|
|
20
20
|
|
|
21
21
|
Octo generates Terragrunt module folders from your definition; Terraform/Tofu (via Terragrunt) is the
|
|
22
|
-
executor. The flow has
|
|
23
|
-
optional validate step compares the Terraform plan against Octo's own diff.
|
|
22
|
+
executor. The flow has four steps: generate, validate, apply, then commit the results back into Octo.
|
|
24
23
|
|
|
25
24
|
Each step is a script, so there is nothing to set up first:
|
|
26
25
|
|
|
@@ -28,30 +27,34 @@ Each step is a script, so there is nothing to set up first:
|
|
|
28
27
|
# 1. Generate the Terragrunt module folders into ./.octo-tf (folders are overwritten in place; state and unrelated folders survive).
|
|
29
28
|
npm run octo:generate
|
|
30
29
|
|
|
31
|
-
# 2. (optional) Plan every module folder and
|
|
30
|
+
# 2. (optional) Plan every module folder and report the plans against your intent.
|
|
32
31
|
# `validate` runs the plan itself; there is nothing to run beforehand.
|
|
33
32
|
npm run octo:validate
|
|
34
33
|
|
|
35
34
|
# 3. Take the app lock. Apply and commit both require it, so that only one run writes state at a time.
|
|
36
35
|
LOCK_ID=$(npm run --silent octo:lock)
|
|
37
36
|
|
|
38
|
-
# 4. Apply, then record the applied outputs into Octo.
|
|
37
|
+
# 4. Apply, then record the applied outputs into Octo. A commit that succeeds releases the lock.
|
|
39
38
|
npm run octo:apply -- --lockId $LOCK_ID
|
|
40
39
|
npm run octo:commit -- --lockId $LOCK_ID
|
|
41
40
|
```
|
|
42
41
|
|
|
43
|
-
Generate and validate need no lock
|
|
44
|
-
run without one.
|
|
45
|
-
run dies between the lock and the commit, `npm run octo:unlock -- --force` releases it.
|
|
42
|
+
Generate and validate need no lock, because neither writes shared state. Apply and commit do, and
|
|
43
|
+
refuse to run without one.
|
|
46
44
|
|
|
47
|
-
If the apply fails partway,
|
|
48
|
-
|
|
49
|
-
|
|
45
|
+
If the apply fails partway, it prints the command that records what did apply and releases the
|
|
46
|
+
lock: `npm run octo:commit -- --lockId $LOCK_ID --partial`. Then fix what failed and run the four
|
|
47
|
+
steps again. If a commit fails, it keeps the lock: fix what it reported and run the same commit
|
|
48
|
+
again. A run that died holding the lock is finished through it, not released:
|
|
49
|
+
[Recovering a Failed Run](https://octo.quadnix.com/docs/using-octo/recovering-a-failed-run) has the
|
|
50
|
+
steps for every case.
|
|
50
51
|
|
|
51
52
|
`octo apply` plans first and refuses to proceed if the apply would destroy anything, printing what
|
|
52
53
|
would be destroyed. Run `npm run octo:validate` to see why each one is being destroyed, then re-run
|
|
53
|
-
the apply with `--auto-approve`
|
|
54
|
-
required for every destroy,
|
|
54
|
+
the apply with `--auto-approve` and the same lock ID to go ahead:
|
|
55
|
+
`npm run octo:apply -- --lockId $LOCK_ID --auto-approve`. That flag is required for every destroy,
|
|
56
|
+
including the teardown flow below. If you decide not to go ahead, release the lock with
|
|
57
|
+
`npm run octo:unlock -- --lockId $LOCK_ID`.
|
|
55
58
|
|
|
56
59
|
Each script sets `OCTO_DEFINITION_FILE_PATH=octo.yaml` and points at `.octo-tf` for you. Edit the
|
|
57
60
|
scripts in `package.json` if your definition file or output directory is named differently. Running
|
|
@@ -85,8 +88,8 @@ delete it by hand.
|
|
|
85
88
|
In `octo.yaml`, comment out all modules except the `app` and `account` modules.
|
|
86
89
|
The app and account modules load AWS credentials to call AWS APIs, hence they remain uncommented.
|
|
87
90
|
|
|
88
|
-
By commenting the `s3-website-service-module`
|
|
89
|
-
you are safely deleting the s3-website resources created by
|
|
91
|
+
By commenting the `region-module` and `s3-website-service-module` modules below,
|
|
92
|
+
you are safely deleting the s3-website resources created by these modules.
|
|
90
93
|
|
|
91
94
|
```yaml
|
|
92
95
|
modules:
|
|
@@ -101,13 +104,19 @@ modules:
|
|
|
101
104
|
accountId: "${env.AWS_ACCOUNT_ID}"
|
|
102
105
|
app: "${{app-module.model.app}}"
|
|
103
106
|
|
|
107
|
+
#- moduleId: region-module
|
|
108
|
+
# moduleClass: AwsServerlessRegionModule
|
|
109
|
+
# moduleInputs:
|
|
110
|
+
# account: "${{account-module.model.account}}"
|
|
111
|
+
# name: aws-s3-website
|
|
112
|
+
# regionId: aws-us-east-1
|
|
113
|
+
|
|
104
114
|
#- moduleId: s3-website-service-module
|
|
105
115
|
# moduleClass: AwsS3StaticWebsiteServiceModule
|
|
106
116
|
# moduleInputs:
|
|
107
|
-
# account: "${{account-module.model.account}}"
|
|
108
|
-
# awsRegionId: us-east-1
|
|
109
117
|
# bucketName: "${env.AWS_S3_WEBSITE_BUCKET_NAME}"
|
|
110
118
|
# directoryPath: website
|
|
119
|
+
# region: "${{region-module.model.region}}"
|
|
111
120
|
```
|
|
112
121
|
|
|
113
122
|
### Step 2
|
package/dist/commands/create-app/generator-octo-app-template/generators/app/templates/gitignore.ejs
CHANGED
|
@@ -19,9 +19,10 @@ build/
|
|
|
19
19
|
.terragrunt-cache/
|
|
20
20
|
*.tfstate*
|
|
21
21
|
!.octo/*.tfstate
|
|
22
|
-
!.octo/*.tfstate.enc
|
|
23
22
|
.octo/local-state.lock
|
|
24
|
-
.
|
|
23
|
+
# The journal: files per command, archived per lock, which would land in every pull request.
|
|
24
|
+
.octo/journal.*
|
|
25
|
+
.octo/archives/
|
|
25
26
|
|
|
26
27
|
# Environment variables
|
|
27
28
|
.env
|