@payfit/nx-core 5.0.1 → 5.0.2-ephemeral-vibe-code-spacelift-stack-manager.1
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/dist/src/executors/spacelift-stack-management/executor.d.ts +4 -0
- package/dist/src/executors/spacelift-stack-management/executor.js +195 -0
- package/dist/src/executors/spacelift-stack-management/executor.js.map +1 -0
- package/dist/src/executors/spacelift-stack-management/schema.json +31 -0
- package/package.json +1 -1
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { ExecutorContext } from '@nx/devkit';
|
|
2
|
+
import { SpaceliftStackManagementExecutorOptions, SpaceliftStackManagementExecutorSchema } from './schema';
|
|
3
|
+
declare const runExecutor: (options: SpaceliftStackManagementExecutorOptions, context: ExecutorContext) => Promise<SpaceliftStackManagementExecutorSchema>;
|
|
4
|
+
export default runExecutor;
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const fs_1 = require("fs");
|
|
4
|
+
const path_1 = require("path");
|
|
5
|
+
const core_1 = require("@apollo/client/core");
|
|
6
|
+
const yaml_1 = require("yaml");
|
|
7
|
+
const logger_1 = require("../../utils/common/logger");
|
|
8
|
+
const graphql_service_1 = require("../../utils/spacelift/lib/graphql.service");
|
|
9
|
+
function getEnvVar(name) {
|
|
10
|
+
const value = process.env[name];
|
|
11
|
+
if (!value) {
|
|
12
|
+
throw new Error(`Missing env var ${name}`);
|
|
13
|
+
}
|
|
14
|
+
return value;
|
|
15
|
+
}
|
|
16
|
+
function ensureSpaceliftAuthEnv() {
|
|
17
|
+
// Ensure required Spacelift credentials are provided
|
|
18
|
+
getEnvVar('SPACELIFT_KEY_ID');
|
|
19
|
+
getEnvVar('SPACELIFT_KEY_SECRET');
|
|
20
|
+
}
|
|
21
|
+
const CREATE_STACK = (0, core_1.gql) `
|
|
22
|
+
mutation CreateStack(
|
|
23
|
+
$input: StackInput!
|
|
24
|
+
$slug: String
|
|
25
|
+
$manageState: Boolean!
|
|
26
|
+
) {
|
|
27
|
+
stackCreate(input: $input, slug: $slug, manageState: $manageState) {
|
|
28
|
+
id
|
|
29
|
+
name
|
|
30
|
+
repository
|
|
31
|
+
branch
|
|
32
|
+
state
|
|
33
|
+
namespace
|
|
34
|
+
projectRoot
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
`;
|
|
38
|
+
const UPDATE_STACK = (0, core_1.gql) `
|
|
39
|
+
mutation UpdateStack($id: ID!, $input: StackInput!) {
|
|
40
|
+
stackUpdate(id: $id, input: $input) {
|
|
41
|
+
id
|
|
42
|
+
name
|
|
43
|
+
repository
|
|
44
|
+
branch
|
|
45
|
+
state
|
|
46
|
+
namespace
|
|
47
|
+
projectRoot
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
`;
|
|
51
|
+
const DELETE_STACK = (0, core_1.gql) `
|
|
52
|
+
mutation DeleteStack($id: ID!, $destroyResources: Boolean) {
|
|
53
|
+
stackDelete(id: $id, destroyResources: $destroyResources) {
|
|
54
|
+
id
|
|
55
|
+
name
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
`;
|
|
59
|
+
const GET_STACK = (0, core_1.gql) `
|
|
60
|
+
query GetStack($id: ID!) {
|
|
61
|
+
stack(id: $id) {
|
|
62
|
+
id
|
|
63
|
+
name
|
|
64
|
+
repository
|
|
65
|
+
branch
|
|
66
|
+
administrative
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
`;
|
|
70
|
+
const runExecutor = async (options, context) => {
|
|
71
|
+
try {
|
|
72
|
+
// Use default path if not provided
|
|
73
|
+
const configFile = options.configFile || 'spacelift.yaml';
|
|
74
|
+
const configPath = (0, path_1.resolve)(context.root, configFile);
|
|
75
|
+
const action = options.action || 'update';
|
|
76
|
+
if (!(0, fs_1.existsSync)(configPath) && action !== 'delete') {
|
|
77
|
+
throw new Error(`${configFile} not found at workspace root`);
|
|
78
|
+
}
|
|
79
|
+
const config = action === 'delete'
|
|
80
|
+
? // For delete, we only need the name to compute slug; require file to be present in workspace for simplicity
|
|
81
|
+
(() => {
|
|
82
|
+
if (!(0, fs_1.existsSync)(configPath)) {
|
|
83
|
+
throw new Error(`${configFile} not found. Provide the file or pass --action=delete with the file present to derive the slug from name.`);
|
|
84
|
+
}
|
|
85
|
+
const content = (0, fs_1.readFileSync)(configPath, 'utf-8');
|
|
86
|
+
return (0, yaml_1.parse)(content);
|
|
87
|
+
})()
|
|
88
|
+
: (() => {
|
|
89
|
+
logger_1.consola.info(`Reading stack configuration from: ${configPath}`);
|
|
90
|
+
const content = (0, fs_1.readFileSync)(configPath, 'utf-8');
|
|
91
|
+
const parsed = (0, yaml_1.parse)(content);
|
|
92
|
+
logger_1.consola.box(`Managing Spacelift stack: ${parsed.name}`);
|
|
93
|
+
return parsed;
|
|
94
|
+
})();
|
|
95
|
+
// Ensure authentication env vars are set (same pattern as other executors)
|
|
96
|
+
ensureSpaceliftAuthEnv();
|
|
97
|
+
// Initialize GraphQL service (handles JWT retrieval internally)
|
|
98
|
+
const graphQlService = new graphql_service_1.GraphQlService();
|
|
99
|
+
// Compute slug/ID from name for update/delete
|
|
100
|
+
const stackIdFromName = config.name
|
|
101
|
+
.trim()
|
|
102
|
+
.toLowerCase()
|
|
103
|
+
.replace(/[^a-z0-9]+/g, '-')
|
|
104
|
+
.replace(/(^-|-$)/g, '');
|
|
105
|
+
// Fetch current stack for update/delete paths to allow comparisons and avoid accidental changes
|
|
106
|
+
const currentStack = action !== 'create'
|
|
107
|
+
? (await graphQlService.query({
|
|
108
|
+
query: GET_STACK,
|
|
109
|
+
variables: { id: stackIdFromName },
|
|
110
|
+
})).stack
|
|
111
|
+
: undefined;
|
|
112
|
+
// Build the minimal required stack input
|
|
113
|
+
const stackInput = {
|
|
114
|
+
name: config.name,
|
|
115
|
+
repository: config.repository,
|
|
116
|
+
branch: config.branch,
|
|
117
|
+
// preserve existing administrative flag on update to avoid unintended changes
|
|
118
|
+
administrative: currentStack?.administrative ?? false,
|
|
119
|
+
};
|
|
120
|
+
logger_1.consola.info('Desired stack configuration (subset):', {
|
|
121
|
+
name: stackInput.name,
|
|
122
|
+
repository: stackInput.repository,
|
|
123
|
+
branch: stackInput.branch,
|
|
124
|
+
});
|
|
125
|
+
if (action === 'create') {
|
|
126
|
+
const result = await graphQlService.mutate({
|
|
127
|
+
mutation: CREATE_STACK,
|
|
128
|
+
variables: {
|
|
129
|
+
input: stackInput,
|
|
130
|
+
slug: undefined,
|
|
131
|
+
manageState: true,
|
|
132
|
+
},
|
|
133
|
+
});
|
|
134
|
+
const createdStack = result.stackCreate;
|
|
135
|
+
logger_1.consola.success(`Stack created successfully!`);
|
|
136
|
+
logger_1.consola.info(`Stack ID: ${createdStack.id}`);
|
|
137
|
+
return {
|
|
138
|
+
success: true,
|
|
139
|
+
stackId: createdStack.id,
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
if (action === 'update') {
|
|
143
|
+
if (!currentStack) {
|
|
144
|
+
logger_1.consola.warn(`Stack ${stackIdFromName} not found. Nothing to update. Consider action=create if you want to create it.`);
|
|
145
|
+
return { success: true };
|
|
146
|
+
}
|
|
147
|
+
const skipIfUnchanged = options.skipIfUnchanged ?? true;
|
|
148
|
+
const isUnchanged = currentStack.name === stackInput.name &&
|
|
149
|
+
currentStack.repository === stackInput.repository &&
|
|
150
|
+
currentStack.branch === stackInput.branch;
|
|
151
|
+
if (skipIfUnchanged && isUnchanged) {
|
|
152
|
+
logger_1.consola.info('No changes detected. Skipping update.');
|
|
153
|
+
return { success: true, stackId: currentStack.id };
|
|
154
|
+
}
|
|
155
|
+
const result = await graphQlService.mutate({
|
|
156
|
+
mutation: UPDATE_STACK,
|
|
157
|
+
variables: {
|
|
158
|
+
id: stackIdFromName,
|
|
159
|
+
input: stackInput,
|
|
160
|
+
},
|
|
161
|
+
});
|
|
162
|
+
const updatedStack = result.stackUpdate;
|
|
163
|
+
logger_1.consola.success(`Stack updated successfully!`);
|
|
164
|
+
logger_1.consola.info(`Stack ID: ${updatedStack.id}`);
|
|
165
|
+
return {
|
|
166
|
+
success: true,
|
|
167
|
+
stackId: updatedStack.id,
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
if (action === 'delete') {
|
|
171
|
+
const result = await graphQlService.mutate({
|
|
172
|
+
mutation: DELETE_STACK,
|
|
173
|
+
variables: {
|
|
174
|
+
id: stackIdFromName,
|
|
175
|
+
destroyResources: options.destroyResources,
|
|
176
|
+
},
|
|
177
|
+
});
|
|
178
|
+
const deletedStack = result.stackDelete;
|
|
179
|
+
logger_1.consola.success(`Stack deletion requested successfully!`);
|
|
180
|
+
return {
|
|
181
|
+
success: true,
|
|
182
|
+
stackId: deletedStack?.id,
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
throw new Error(`Unsupported action: ${action}`);
|
|
186
|
+
}
|
|
187
|
+
catch (error) {
|
|
188
|
+
logger_1.consola.error('Failed to create Spacelift stack:', error);
|
|
189
|
+
return {
|
|
190
|
+
success: false,
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
};
|
|
194
|
+
exports.default = runExecutor;
|
|
195
|
+
//# sourceMappingURL=executor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"executor.js","sourceRoot":"","sources":["../../../../src/executors/spacelift-stack-management/executor.ts"],"names":[],"mappings":";;AAAA,2BAA6C;AAC7C,+BAA8B;AAE9B,8CAA4D;AAE5D,+BAAyC;AAEzC,sDAAmD;AAKnD,+EAA0E;AAO1E,SAAS,SAAS,CAAC,IAAY;IAC7B,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;IAC/B,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CAAC,mBAAmB,IAAI,EAAE,CAAC,CAAA;IAC5C,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC;AAED,SAAS,sBAAsB;IAC7B,qDAAqD;IACrD,SAAS,CAAC,kBAAkB,CAAC,CAAA;IAC7B,SAAS,CAAC,sBAAsB,CAAC,CAAA;AACnC,CAAC;AAcD,MAAM,YAAY,GAAwD,IAAA,UAAG,EAAA;;;;;;;;;;;;;;;;CAgB5E,CAAA;AAWD,MAAM,YAAY,GAAwD,IAAA,UAAG,EAAA;;;;;;;;;;;;CAY5E,CAAA;AAWD,MAAM,YAAY,GAAwD,IAAA,UAAG,EAAA;;;;;;;CAO5E,CAAA;AAUD,MAAM,SAAS,GAAkD,IAAA,UAAG,EAAA;;;;;;;;;;CAUnE,CAAA;AAED,MAAM,WAAW,GAAG,KAAK,EACvB,OAAgD,EAChD,OAAwB,EACyB,EAAE;IACnD,IAAI,CAAC;QACH,mCAAmC;QACnC,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,gBAAgB,CAAA;QACzD,MAAM,UAAU,GAAG,IAAA,cAAO,EAAC,OAAO,CAAC,IAAI,EAAE,UAAU,CAAC,CAAA;QAEpD,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,QAAQ,CAAA;QAEzC,IAAI,CAAC,IAAA,eAAU,EAAC,UAAU,CAAC,IAAI,MAAM,KAAK,QAAQ,EAAE,CAAC;YACnD,MAAM,IAAI,KAAK,CAAC,GAAG,UAAU,8BAA8B,CAAC,CAAA;QAC9D,CAAC;QAED,MAAM,MAAM,GACV,MAAM,KAAK,QAAQ;YACjB,CAAC,CAAC,4GAA4G;gBAC5G,CAAC,GAAG,EAAE;oBACJ,IAAI,CAAC,IAAA,eAAU,EAAC,UAAU,CAAC,EAAE,CAAC;wBAC5B,MAAM,IAAI,KAAK,CACb,GAAG,UAAU,0GAA0G,CACxH,CAAA;oBACH,CAAC;oBACD,MAAM,OAAO,GAAG,IAAA,iBAAY,EAAC,UAAU,EAAE,OAAO,CAAC,CAAA;oBACjD,OAAO,IAAA,YAAS,EAAC,OAAO,CAAyB,CAAA;gBACnD,CAAC,CAAC,EAAE;YACN,CAAC,CAAC,CAAC,GAAG,EAAE;gBACJ,gBAAO,CAAC,IAAI,CAAC,qCAAqC,UAAU,EAAE,CAAC,CAAA;gBAC/D,MAAM,OAAO,GAAG,IAAA,iBAAY,EAAC,UAAU,EAAE,OAAO,CAAC,CAAA;gBACjD,MAAM,MAAM,GAAG,IAAA,YAAS,EAAC,OAAO,CAAyB,CAAA;gBACzD,gBAAO,CAAC,GAAG,CAAC,6BAA6B,MAAM,CAAC,IAAI,EAAE,CAAC,CAAA;gBACvD,OAAO,MAAM,CAAA;YACf,CAAC,CAAC,EAAE,CAAA;QAEV,2EAA2E;QAC3E,sBAAsB,EAAE,CAAA;QAExB,gEAAgE;QAChE,MAAM,cAAc,GAAG,IAAI,gCAAc,EAAE,CAAA;QAE3C,8CAA8C;QAC9C,MAAM,eAAe,GAAG,MAAM,CAAC,IAAI;aAChC,IAAI,EAAE;aACN,WAAW,EAAE;aACb,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC;aAC3B,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAA;QAE1B,gGAAgG;QAChG,MAAM,YAAY,GAChB,MAAM,KAAK,QAAQ;YACjB,CAAC,CAAC,CACE,MAAM,cAAc,CAAC,KAAK,CAA6B;gBACrD,KAAK,EAAE,SAAS;gBAChB,SAAS,EAAE,EAAE,EAAE,EAAE,eAAe,EAAE;aACnC,CAAC,CACH,CAAC,KAAK;YACT,CAAC,CAAC,SAAS,CAAA;QAEf,yCAAyC;QACzC,MAAM,UAAU,GAAe;YAC7B,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,UAAU,EAAE,MAAM,CAAC,UAAU;YAC7B,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,8EAA8E;YAC9E,cAAc,EAAE,YAAY,EAAE,cAAc,IAAI,KAAK;SACtD,CAAA;QAED,gBAAO,CAAC,IAAI,CAAC,uCAAuC,EAAE;YACpD,IAAI,EAAE,UAAU,CAAC,IAAI;YACrB,UAAU,EAAE,UAAU,CAAC,UAAU;YACjC,MAAM,EAAE,UAAU,CAAC,MAAM;SAC1B,CAAC,CAAA;QAEF,IAAI,MAAM,KAAK,QAAQ,EAAE,CAAC;YACxB,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,MAAM,CAGxC;gBACA,QAAQ,EAAE,YAAY;gBACtB,SAAS,EAAE;oBACT,KAAK,EAAE,UAAU;oBACjB,IAAI,EAAE,SAAS;oBACf,WAAW,EAAE,IAAI;iBAClB;aACF,CAAC,CAAA;YAEF,MAAM,YAAY,GAAI,MAA0B,CAAC,WAAW,CAAA;YAC5D,gBAAO,CAAC,OAAO,CAAC,6BAA6B,CAAC,CAAA;YAC9C,gBAAO,CAAC,IAAI,CAAC,aAAa,YAAY,CAAC,EAAE,EAAE,CAAC,CAAA;YAC5C,OAAO;gBACL,OAAO,EAAE,IAAI;gBACb,OAAO,EAAE,YAAY,CAAC,EAAE;aACzB,CAAA;QACH,CAAC;QAED,IAAI,MAAM,KAAK,QAAQ,EAAE,CAAC;YACxB,IAAI,CAAC,YAAY,EAAE,CAAC;gBAClB,gBAAO,CAAC,IAAI,CACV,SAAS,eAAe,iFAAiF,CAC1G,CAAA;gBACD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAA;YAC1B,CAAC;YAED,MAAM,eAAe,GAAG,OAAO,CAAC,eAAe,IAAI,IAAI,CAAA;YACvD,MAAM,WAAW,GACf,YAAY,CAAC,IAAI,KAAK,UAAU,CAAC,IAAI;gBACrC,YAAY,CAAC,UAAU,KAAK,UAAU,CAAC,UAAU;gBACjD,YAAY,CAAC,MAAM,KAAK,UAAU,CAAC,MAAM,CAAA;YAE3C,IAAI,eAAe,IAAI,WAAW,EAAE,CAAC;gBACnC,gBAAO,CAAC,IAAI,CAAC,uCAAuC,CAAC,CAAA;gBACrD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,YAAY,CAAC,EAAE,EAAE,CAAA;YACpD,CAAC;YAED,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,MAAM,CAGxC;gBACA,QAAQ,EAAE,YAAY;gBACtB,SAAS,EAAE;oBACT,EAAE,EAAE,eAAe;oBACnB,KAAK,EAAE,UAAU;iBAClB;aACF,CAAC,CAAA;YAEF,MAAM,YAAY,GAAI,MAA0B,CAAC,WAAW,CAAA;YAC5D,gBAAO,CAAC,OAAO,CAAC,6BAA6B,CAAC,CAAA;YAC9C,gBAAO,CAAC,IAAI,CAAC,aAAa,YAAY,CAAC,EAAE,EAAE,CAAC,CAAA;YAC5C,OAAO;gBACL,OAAO,EAAE,IAAI;gBACb,OAAO,EAAE,YAAY,CAAC,EAAE;aACzB,CAAA;QACH,CAAC;QAED,IAAI,MAAM,KAAK,QAAQ,EAAE,CAAC;YACxB,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,MAAM,CAGxC;gBACA,QAAQ,EAAE,YAAY;gBACtB,SAAS,EAAE;oBACT,EAAE,EAAE,eAAe;oBACnB,gBAAgB,EAAE,OAAO,CAAC,gBAAgB;iBAC3C;aACF,CAAC,CAAA;YAEF,MAAM,YAAY,GAAI,MAA0B,CAAC,WAAW,CAAA;YAC5D,gBAAO,CAAC,OAAO,CAAC,wCAAwC,CAAC,CAAA;YACzD,OAAO;gBACL,OAAO,EAAE,IAAI;gBACb,OAAO,EAAE,YAAY,EAAE,EAAE;aAC1B,CAAA;QACH,CAAC;QAED,MAAM,IAAI,KAAK,CAAC,uBAAuB,MAAM,EAAE,CAAC,CAAA;IAClD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,gBAAO,CAAC,KAAK,CAAC,mCAAmC,EAAE,KAAK,CAAC,CAAA;QACzD,OAAO;YACL,OAAO,EAAE,KAAK;SACf,CAAA;IACH,CAAC;AACH,CAAC,CAAA;AAED,kBAAe,WAAW,CAAA"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/schema",
|
|
3
|
+
"version": 2,
|
|
4
|
+
"title": "Spacelift Stack Management",
|
|
5
|
+
"description": "Create and manage Spacelift stacks from YAML configuration",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"properties": {
|
|
8
|
+
"configFile": {
|
|
9
|
+
"type": "string",
|
|
10
|
+
"description": "Path to the YAML configuration file containing stack definition",
|
|
11
|
+
"default": "spacelift.yaml"
|
|
12
|
+
},
|
|
13
|
+
"action": {
|
|
14
|
+
"type": "string",
|
|
15
|
+
"description": "Action to perform on the stack",
|
|
16
|
+
"enum": ["create", "update", "delete"],
|
|
17
|
+
"default": "update"
|
|
18
|
+
},
|
|
19
|
+
"destroyResources": {
|
|
20
|
+
"type": "boolean",
|
|
21
|
+
"description": "When deleting, also destroy resources",
|
|
22
|
+
"default": false
|
|
23
|
+
},
|
|
24
|
+
"skipIfUnchanged": {
|
|
25
|
+
"type": "boolean",
|
|
26
|
+
"description": "Skip update if YAML matches current stack",
|
|
27
|
+
"default": true
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
"required": []
|
|
31
|
+
}
|