awscfn 1.1.0 → 1.1.2
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 +77 -40
- package/bin/awscfn +12 -6
- package/dist/lib/cfn/listStacks.d.ts +1 -1
- package/dist/lib/cfn/listStacks.d.ts.map +1 -1
- package/dist/lib/cfn/listStacks.js +7 -2
- package/dist/lib/cfn/listStacks.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -9,15 +9,51 @@
|
|
|
9
9
|
[](https://conventionalcommits.org)
|
|
10
10
|
[](https://github.com/mhweiner/autorel)
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
Deploy CloudFormation stacks without the usual suffering.
|
|
13
13
|
|
|
14
14
|
## Why awscfn?
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
-
|
|
19
|
-
-
|
|
20
|
-
-
|
|
16
|
+
If you've deployed CloudFormation stacks, you know the pain:
|
|
17
|
+
|
|
18
|
+
- You run `aws cloudformation create-stack` and get... nothing. Is it working? Who knows.
|
|
19
|
+
- You open the AWS console, hit refresh, scroll through events, trying to find the one that matters.
|
|
20
|
+
- It fails. The error says "Resource creation cancelled." The *actual* reason is buried somewhere in the event log.
|
|
21
|
+
- The stack is stuck in `ROLLBACK_COMPLETE`. Now you have to delete it manually before you can try again.
|
|
22
|
+
- Your CI job times out or exits 0 even though the deploy failed.
|
|
23
|
+
- You write a parameter file and remember: oh right, CloudFormation wants *that* JSON format.
|
|
24
|
+
|
|
25
|
+
**awscfn fixes this.**
|
|
26
|
+
|
|
27
|
+
- **Watch deploys happen** — Stack events stream to your terminal in real time. No refreshing. No second window.
|
|
28
|
+
- **See why it failed** — When a deploy fails, you get the actual failure reason, not "Resource creation cancelled."
|
|
29
|
+
- **Recover automatically** — Stuck in `ROLLBACK_COMPLETE`? awscfn detects it and re-creates the stack for you.
|
|
30
|
+
- **YAML params** — Simple YAML parameter files. No more verbose JSON.
|
|
31
|
+
- **CI that works** — Auto-detects CI environments. Exits non-zero when deploys fail. Compact output mode.
|
|
32
|
+
- **CLI + TypeScript SDK** — Use from the command line or import directly into Node.js/TypeScript projects.
|
|
33
|
+
|
|
34
|
+
It's not a CDK. It's not a framework. It's just a better way to deploy raw CloudFormation.
|
|
35
|
+
|
|
36
|
+
## Installation
|
|
37
|
+
|
|
38
|
+
**Global install** (recommended for CLI use):
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
npm i -g awscfn
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Then run commands directly: `awscfn create-stack ...`
|
|
45
|
+
|
|
46
|
+
**Project dependency** (for SDK/library use):
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
npm i awscfn
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
**npx** (no install):
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
npx awscfn create-stack ...
|
|
56
|
+
```
|
|
21
57
|
|
|
22
58
|
## CLI commands
|
|
23
59
|
|
|
@@ -25,12 +61,15 @@ CLI and TypeScript SDK for managing AWS CloudFormation stacks.
|
|
|
25
61
|
|
|
26
62
|
### Global Options
|
|
27
63
|
|
|
28
|
-
| Flag |
|
|
29
|
-
|
|
30
|
-
| `--ci` |
|
|
31
|
-
| `--no-color
|
|
32
|
-
| `--
|
|
33
|
-
| `--
|
|
64
|
+
| Flag | Description |
|
|
65
|
+
|------|-------------|
|
|
66
|
+
| `--ci`, `-C` | CI mode (compact output). Auto-detected when `CI=true` or `GITHUB_ACTIONS=true`. |
|
|
67
|
+
| `--no-color`, `-N` | Disable colored output |
|
|
68
|
+
| `--verbose`, `-V` | Show full error details on failure |
|
|
69
|
+
| `--help`, `-h` | Show help |
|
|
70
|
+
| `--version`, `-v` | Show version |
|
|
71
|
+
|
|
72
|
+
Run `awscfn --help` or `awscfn <command> --help` for full CLI usage.
|
|
34
73
|
|
|
35
74
|
### Shell Completion
|
|
36
75
|
|
|
@@ -62,34 +101,32 @@ When a failure occurs, the error message includes the actual reason from CloudFo
|
|
|
62
101
|
List all CloudFormation stacks in the current region (name, status, creation date).
|
|
63
102
|
|
|
64
103
|
```bash
|
|
65
|
-
|
|
104
|
+
awscfn list-stacks
|
|
66
105
|
```
|
|
67
106
|
|
|
68
|
-
No options. Output is a table of stack name, status, and creation date.
|
|
69
|
-
|
|
70
107
|
### 🚀 create-stack
|
|
71
108
|
|
|
72
109
|
```bash
|
|
73
|
-
|
|
110
|
+
awscfn create-stack -n <STACK_NAME> -t <TEMPLATE_FILE> -p <PARAMS_FILE>
|
|
74
111
|
```
|
|
75
112
|
|
|
76
|
-
| Flag |
|
|
77
|
-
|
|
78
|
-
| `--name
|
|
79
|
-
| `--template
|
|
80
|
-
| `--params
|
|
113
|
+
| Flag | Description |
|
|
114
|
+
|------|-------------|
|
|
115
|
+
| `--name`, `-n` | Stack name |
|
|
116
|
+
| `--template`, `-t` | CloudFormation template file |
|
|
117
|
+
| `--params`, `-p` | Parameters file (YAML) |
|
|
81
118
|
|
|
82
119
|
### ⬆️ update-stack
|
|
83
120
|
|
|
84
121
|
```bash
|
|
85
|
-
|
|
122
|
+
awscfn update-stack -n <STACK_NAME> -t <TEMPLATE_FILE> -p <PARAMS_FILE>
|
|
86
123
|
```
|
|
87
124
|
|
|
88
|
-
| Flag |
|
|
89
|
-
|
|
90
|
-
| `--name
|
|
91
|
-
| `--template
|
|
92
|
-
| `--params
|
|
125
|
+
| Flag | Description |
|
|
126
|
+
|------|-------------|
|
|
127
|
+
| `--name`, `-n` | Stack name |
|
|
128
|
+
| `--template`, `-t` | CloudFormation template file |
|
|
129
|
+
| `--params`, `-p` | Parameters file (YAML) |
|
|
93
130
|
|
|
94
131
|
If there are no changes to apply, the command succeeds gracefully:
|
|
95
132
|
```
|
|
@@ -99,13 +136,13 @@ If there are no changes to apply, the command succeeds gracefully:
|
|
|
99
136
|
### ♻️ redeploy-stack
|
|
100
137
|
|
|
101
138
|
```bash
|
|
102
|
-
|
|
139
|
+
awscfn redeploy-stack -n <STACK_NAME> -t <TEMPLATE_FILE>
|
|
103
140
|
```
|
|
104
141
|
|
|
105
|
-
| Flag |
|
|
106
|
-
|
|
107
|
-
| `--name
|
|
108
|
-
| `--template
|
|
142
|
+
| Flag | Description |
|
|
143
|
+
|------|-------------|
|
|
144
|
+
| `--name`, `-n` | Stack name |
|
|
145
|
+
| `--template`, `-t` | CloudFormation template file |
|
|
109
146
|
|
|
110
147
|
Redeploys using the existing stack's parameters. Useful for updating a stack with a new template without re-specifying params, or re-deploying after a failed create.
|
|
111
148
|
|
|
@@ -114,20 +151,20 @@ Redeploys using the existing stack's parameters. Useful for updating a stack wit
|
|
|
114
151
|
Deletes a CloudFormation stack with a confirmation safeguard.
|
|
115
152
|
|
|
116
153
|
```bash
|
|
117
|
-
|
|
154
|
+
awscfn delete-stack -n <STACK_NAME> -c <STACK_NAME>
|
|
118
155
|
```
|
|
119
156
|
|
|
120
|
-
| Flag |
|
|
121
|
-
|
|
122
|
-
| `--name
|
|
123
|
-
| `--confirm
|
|
157
|
+
| Flag | Description |
|
|
158
|
+
|------|-------------|
|
|
159
|
+
| `--name`, `-n` | Stack name |
|
|
160
|
+
| `--confirm`, `-c` | Repeat stack name to confirm |
|
|
124
161
|
|
|
125
|
-
|
|
162
|
+
`--confirm` must match `--name` exactly to prevent accidental deletion.
|
|
126
163
|
|
|
127
164
|
**Example:**
|
|
128
165
|
|
|
129
166
|
```bash
|
|
130
|
-
|
|
167
|
+
awscfn delete-stack -n my-app-prod -c my-app-prod
|
|
131
168
|
```
|
|
132
169
|
|
|
133
170
|
If the stack doesn't exist, the command will exit with an error.
|
|
@@ -141,7 +178,7 @@ If the names don't match, the deletion will be aborted.
|
|
|
141
178
|
|
|
142
179
|
### 📋 `listStacks(): Promise<StackSummary[]>`
|
|
143
180
|
|
|
144
|
-
Returns all CloudFormation stacks in the current region (paginated). Excludes `DELETE_COMPLETE`
|
|
181
|
+
Returns all CloudFormation stacks in the current region (paginated). Excludes deleted stacks (`DELETE_COMPLETE`, `DELETE_IN_PROGRESS`) via `StackStatusFilter`. Each item is an AWS SDK `StackSummary` (e.g. `StackName`, `StackStatus`, `CreationTime`).
|
|
145
182
|
|
|
146
183
|
```ts
|
|
147
184
|
import { listStacks } from 'awscfn';
|
package/bin/awscfn
CHANGED
|
@@ -9,7 +9,7 @@ const { deleteStack } = require('../dist/deleteStack');
|
|
|
9
9
|
const { listStacks } = require('../dist/listStacks');
|
|
10
10
|
const { redeployStack } = require('../dist/redeployStack');
|
|
11
11
|
const { updateStack } = require('../dist/updateStack');
|
|
12
|
-
const { setOutputConfig } = require('../dist/lib/output');
|
|
12
|
+
const { getOutputConfig, setOutputConfig } = require('../dist/lib/output');
|
|
13
13
|
|
|
14
14
|
const pkg = JSON.parse(fs.readFileSync(path.resolve(__dirname, '../package.json'), 'utf8'));
|
|
15
15
|
const isCI = process.env.CI === 'true' || process.env.GITHUB_ACTIONS === 'true';
|
|
@@ -74,7 +74,9 @@ async function runCommand(fn) {
|
|
|
74
74
|
if (message !== err.message) {
|
|
75
75
|
console.log(`\x1b[90m(original: ${err.message})\x1b[0m`);
|
|
76
76
|
}
|
|
77
|
-
|
|
77
|
+
if (getOutputConfig().verbose) {
|
|
78
|
+
logErrorDetails(err.data);
|
|
79
|
+
}
|
|
78
80
|
process.exit(1);
|
|
79
81
|
}
|
|
80
82
|
}
|
|
@@ -95,6 +97,7 @@ const confirmOpt = {
|
|
|
95
97
|
yargs
|
|
96
98
|
.option('ci', {
|
|
97
99
|
type: 'boolean',
|
|
100
|
+
alias: 'C',
|
|
98
101
|
description: 'CI mode (compact output). Auto-detected when CI=true or GITHUB_ACTIONS=true. Colors remain enabled in CI.',
|
|
99
102
|
default: isCI,
|
|
100
103
|
})
|
|
@@ -104,10 +107,17 @@ yargs
|
|
|
104
107
|
description: 'Disable colored output',
|
|
105
108
|
default: false,
|
|
106
109
|
})
|
|
110
|
+
.option('verbose', {
|
|
111
|
+
type: 'boolean',
|
|
112
|
+
alias: 'V',
|
|
113
|
+
description: 'Show full error details (e.g. err.data JSON) on failure',
|
|
114
|
+
default: false,
|
|
115
|
+
})
|
|
107
116
|
.middleware((argv) => {
|
|
108
117
|
setOutputConfig({
|
|
109
118
|
ci: argv.ci,
|
|
110
119
|
color: !argv.noColor && (process.stdout.isTTY || argv.ci),
|
|
120
|
+
verbose: argv.verbose,
|
|
111
121
|
});
|
|
112
122
|
})
|
|
113
123
|
.command(
|
|
@@ -123,7 +133,6 @@ yargs
|
|
|
123
133
|
'Create a CloudFormation stack',
|
|
124
134
|
(cmd) => cmd.options({ ...nameOpt, ...templateOpt, ...paramsOpt }),
|
|
125
135
|
({ name, template, params }) => {
|
|
126
|
-
console.log(`Creating stack: ${name}...`);
|
|
127
136
|
runCommand(() => createStack(name, template, params));
|
|
128
137
|
}
|
|
129
138
|
)
|
|
@@ -132,7 +141,6 @@ yargs
|
|
|
132
141
|
'Delete a CloudFormation stack',
|
|
133
142
|
(cmd) => cmd.options({ ...nameOpt, ...confirmOpt }),
|
|
134
143
|
({ name, confirm }) => {
|
|
135
|
-
console.log(`Deleting stack: ${name}...`);
|
|
136
144
|
runCommand(() => deleteStack(name, confirm));
|
|
137
145
|
}
|
|
138
146
|
)
|
|
@@ -141,7 +149,6 @@ yargs
|
|
|
141
149
|
'Redeploy a CloudFormation stack (uses existing params)',
|
|
142
150
|
(cmd) => cmd.options({ ...nameOpt, ...templateOpt }),
|
|
143
151
|
({ name, template }) => {
|
|
144
|
-
console.log(`Redeploying stack: ${name}...`);
|
|
145
152
|
runCommand(() => redeployStack(name, template));
|
|
146
153
|
}
|
|
147
154
|
)
|
|
@@ -150,7 +157,6 @@ yargs
|
|
|
150
157
|
'Update a CloudFormation stack',
|
|
151
158
|
(cmd) => cmd.options({ ...nameOpt, ...templateOpt, ...paramsOpt }),
|
|
152
159
|
({ name, template, params }) => {
|
|
153
|
-
console.log(`Updating stack: ${name}...`);
|
|
154
160
|
runCommand(() => updateStack(name, template, params));
|
|
155
161
|
}
|
|
156
162
|
)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { StackSummary } from '@aws-sdk/client-cloudformation';
|
|
2
2
|
/**
|
|
3
|
-
* Fetches all CloudFormation stacks (paginated). Excludes
|
|
3
|
+
* Fetches all CloudFormation stacks (paginated). Excludes deleted stacks (DELETE_COMPLETE, DELETE_IN_PROGRESS).
|
|
4
4
|
*/
|
|
5
5
|
export declare function listStacks(): Promise<StackSummary[]>;
|
|
6
6
|
//# sourceMappingURL=listStacks.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"listStacks.d.ts","sourceRoot":"","sources":["../../../src/lib/cfn/listStacks.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"listStacks.d.ts","sourceRoot":"","sources":["../../../src/lib/cfn/listStacks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiC,YAAY,EAAC,MAAM,gCAAgC,CAAC;AAQ5F;;GAEG;AACH,wBAAsB,UAAU,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC,CAqB1D"}
|
|
@@ -3,15 +3,20 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.listStacks = listStacks;
|
|
4
4
|
const client_cloudformation_1 = require("@aws-sdk/client-cloudformation");
|
|
5
5
|
const _1 = require(".");
|
|
6
|
+
/** All stack statuses except deleted (DELETE_COMPLETE, DELETE_IN_PROGRESS). */
|
|
7
|
+
const ACTIVE_STATUS_FILTER = Object.values(client_cloudformation_1.StackStatus).filter((s) => s !== client_cloudformation_1.StackStatus.DELETE_COMPLETE && s !== client_cloudformation_1.StackStatus.DELETE_IN_PROGRESS);
|
|
6
8
|
/**
|
|
7
|
-
* Fetches all CloudFormation stacks (paginated). Excludes
|
|
9
|
+
* Fetches all CloudFormation stacks (paginated). Excludes deleted stacks (DELETE_COMPLETE, DELETE_IN_PROGRESS).
|
|
8
10
|
*/
|
|
9
11
|
async function listStacks() {
|
|
10
12
|
const cf = (0, _1.getCfClient)();
|
|
11
13
|
const out = [];
|
|
12
14
|
let nextToken;
|
|
13
15
|
do {
|
|
14
|
-
const result = await cf.send(new client_cloudformation_1.ListStacksCommand({
|
|
16
|
+
const result = await cf.send(new client_cloudformation_1.ListStacksCommand({
|
|
17
|
+
NextToken: nextToken,
|
|
18
|
+
StackStatusFilter: ACTIVE_STATUS_FILTER,
|
|
19
|
+
}));
|
|
15
20
|
const summaries = result.StackSummaries ?? [];
|
|
16
21
|
out.push(...summaries);
|
|
17
22
|
nextToken = result.NextToken;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"listStacks.js","sourceRoot":"","sources":["../../../src/lib/cfn/listStacks.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"listStacks.js","sourceRoot":"","sources":["../../../src/lib/cfn/listStacks.ts"],"names":[],"mappings":";;AAWA,gCAqBC;AAhCD,0EAA4F;AAC5F,wBAA8B;AAE9B,+EAA+E;AAC/E,MAAM,oBAAoB,GAAmB,MAAM,CAAC,MAAM,CAAC,mCAAW,CAAmB,CAAC,MAAM,CAC5F,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,mCAAW,CAAC,eAAe,IAAI,CAAC,KAAK,mCAAW,CAAC,kBAAkB,CACnF,CAAC;AAEF;;GAEG;AACI,KAAK,UAAU,UAAU;IAE5B,MAAM,EAAE,GAAG,IAAA,cAAW,GAAE,CAAC;IACzB,MAAM,GAAG,GAAmB,EAAE,CAAC;IAC/B,IAAI,SAA6B,CAAC;IAElC,GAAG,CAAC;QAEA,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,IAAI,yCAAiB,CAAC;YAC/C,SAAS,EAAE,SAAS;YACpB,iBAAiB,EAAE,oBAAoB;SAC1C,CAAC,CAAC,CAAC;QACJ,MAAM,SAAS,GAAG,MAAM,CAAC,cAAc,IAAI,EAAE,CAAC;QAE9C,GAAG,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC,CAAC;QACvB,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC;IAEjC,CAAC,QAAQ,SAAS,EAAE;IAEpB,OAAO,GAAG,CAAC;AAEf,CAAC"}
|
package/package.json
CHANGED