Skip to content

Commit 8238efa

Browse files
authored
Merge pull request #119 from deploystackio/main
update IaC lifecycle documentation and add new diagram
2 parents b4be6f2 + 69fda92 commit 8238efa

12 files changed

Lines changed: 546 additions & 96 deletions

.gitignore

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -51,13 +51,11 @@ ehthumbs.db
5151
*.iml
5252
*.ipr
5353
*.iws
54+
._*.png
55+
._*.webp
56+
._*.svg
57+
5458

5559
# Tests
5660
coverage/
5761
.jest/
58-
59-
# Vitepress
60-
.vitepress/dist
61-
.vitepress/cache
62-
.backup
63-
.remark-cache/
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
<mxfile host="Electron" agent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/26.0.9 Chrome/128.0.6613.186 Electron/32.2.5 Safari/537.36" version="26.0.9">
2+
<diagram name="Seite-1" id="Gjpo2csS5-b6mWFYLMsI">
3+
<mxGraphModel dx="1114" dy="794" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1100" pageHeight="850" math="0" shadow="0">
4+
<root>
5+
<mxCell id="0" />
6+
<mxCell id="1" parent="0" />
7+
<mxCell id="DkQQ7b9g_ovJa4es4mWr-2" value="App Project Repository" style="swimlane;fontStyle=1;childLayout=stackLayout;horizontal=1;startSize=30;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;" vertex="1" parent="1">
8+
<mxGeometry x="80" y="80" width="240" height="90" as="geometry">
9+
<mxRectangle x="40" y="40" width="100" height="30" as="alternateBounds" />
10+
</mxGeometry>
11+
</mxCell>
12+
<mxCell id="DkQQ7b9g_ovJa4es4mWr-3" value="I.e.: Change file:" style="text;strokeColor=none;fillColor=default;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;" vertex="1" parent="DkQQ7b9g_ovJa4es4mWr-2">
13+
<mxGeometry y="30" width="240" height="30" as="geometry" />
14+
</mxCell>
15+
<mxCell id="DkQQ7b9g_ovJa4es4mWr-4" value=".deploystack/docker-run.txt" style="text;strokeColor=none;fillColor=default;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;fontFamily=Courier New;" vertex="1" parent="DkQQ7b9g_ovJa4es4mWr-2">
16+
<mxGeometry y="60" width="240" height="30" as="geometry" />
17+
</mxCell>
18+
<mxCell id="DkQQ7b9g_ovJa4es4mWr-13" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="DkQQ7b9g_ovJa4es4mWr-7" target="DkQQ7b9g_ovJa4es4mWr-10">
19+
<mxGeometry relative="1" as="geometry" />
20+
</mxCell>
21+
<mxCell id="DkQQ7b9g_ovJa4es4mWr-7" value="DeployStack GitHub App&lt;div&gt;Event on file Change&lt;/div&gt;" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">
22+
<mxGeometry x="400" y="95" width="160" height="60" as="geometry" />
23+
</mxCell>
24+
<mxCell id="DkQQ7b9g_ovJa4es4mWr-8" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="DkQQ7b9g_ovJa4es4mWr-3" target="DkQQ7b9g_ovJa4es4mWr-7">
25+
<mxGeometry relative="1" as="geometry" />
26+
</mxCell>
27+
<mxCell id="DkQQ7b9g_ovJa4es4mWr-18" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="DkQQ7b9g_ovJa4es4mWr-9" target="DkQQ7b9g_ovJa4es4mWr-15">
28+
<mxGeometry relative="1" as="geometry" />
29+
</mxCell>
30+
<mxCell id="DkQQ7b9g_ovJa4es4mWr-9" value="DeployStack Backend" style="swimlane;fontStyle=1;childLayout=stackLayout;horizontal=1;startSize=30;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;" vertex="1" parent="1">
31+
<mxGeometry x="640" y="80" width="230" height="90" as="geometry">
32+
<mxRectangle x="40" y="40" width="100" height="30" as="alternateBounds" />
33+
</mxGeometry>
34+
</mxCell>
35+
<mxCell id="DkQQ7b9g_ovJa4es4mWr-10" value="Validate Change within .deploystack" style="text;strokeColor=none;fillColor=default;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;" vertex="1" parent="DkQQ7b9g_ovJa4es4mWr-9">
36+
<mxGeometry y="30" width="230" height="30" as="geometry" />
37+
</mxCell>
38+
<mxCell id="DkQQ7b9g_ovJa4es4mWr-12" value="directory" style="text;strokeColor=none;fillColor=default;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;" vertex="1" parent="DkQQ7b9g_ovJa4es4mWr-9">
39+
<mxGeometry y="60" width="230" height="30" as="geometry" />
40+
</mxCell>
41+
<mxCell id="DkQQ7b9g_ovJa4es4mWr-14" value="DeployStack Backend" style="swimlane;fontStyle=1;childLayout=stackLayout;horizontal=1;startSize=30;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;" vertex="1" parent="1">
42+
<mxGeometry x="120" y="240" width="230" height="90" as="geometry">
43+
<mxRectangle x="40" y="40" width="100" height="30" as="alternateBounds" />
44+
</mxGeometry>
45+
</mxCell>
46+
<mxCell id="DkQQ7b9g_ovJa4es4mWr-15" value="Re-create IaC templates with new" style="text;strokeColor=none;fillColor=default;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;" vertex="1" parent="DkQQ7b9g_ovJa4es4mWr-14">
47+
<mxGeometry y="30" width="230" height="30" as="geometry" />
48+
</mxCell>
49+
<mxCell id="DkQQ7b9g_ovJa4es4mWr-17" value="values from docker-run.txt file" style="text;strokeColor=none;fillColor=default;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;" vertex="1" parent="DkQQ7b9g_ovJa4es4mWr-14">
50+
<mxGeometry y="60" width="230" height="30" as="geometry" />
51+
</mxCell>
52+
<mxCell id="DkQQ7b9g_ovJa4es4mWr-19" value="deploy-templates repository" style="swimlane;fontStyle=1;childLayout=stackLayout;horizontal=1;startSize=30;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;" vertex="1" parent="1">
53+
<mxGeometry x="450" y="240" width="230" height="90" as="geometry">
54+
<mxRectangle x="40" y="40" width="100" height="30" as="alternateBounds" />
55+
</mxGeometry>
56+
</mxCell>
57+
<mxCell id="DkQQ7b9g_ovJa4es4mWr-20" value="Push changes to IaC public repository" style="text;strokeColor=none;fillColor=default;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;" vertex="1" parent="DkQQ7b9g_ovJa4es4mWr-19">
58+
<mxGeometry y="30" width="230" height="30" as="geometry" />
59+
</mxCell>
60+
<mxCell id="DkQQ7b9g_ovJa4es4mWr-21" value="deploystackio/deploy-templates" style="text;strokeColor=none;fillColor=default;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;" vertex="1" parent="DkQQ7b9g_ovJa4es4mWr-19">
61+
<mxGeometry y="60" width="230" height="30" as="geometry" />
62+
</mxCell>
63+
<mxCell id="DkQQ7b9g_ovJa4es4mWr-22" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="DkQQ7b9g_ovJa4es4mWr-15" target="DkQQ7b9g_ovJa4es4mWr-20">
64+
<mxGeometry relative="1" as="geometry" />
65+
</mxCell>
66+
</root>
67+
</mxGraphModel>
68+
</diagram>
69+
</mxfile>
14.6 KB
Loading
13.4 KB
Loading

docs/deploystack/iac-lifecycle.md

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,31 @@ Install the [DeployStack Repository Sync](/docs/deploystack/github-application.m
2626
- Cloud providers update their IaC specifications
2727
- DeployStack improves its template generation
2828

29-
![DeployStack IaC Lifecycle](/docs/assets/images/deploystack/iac-lifecycle.drawio.svg)
29+
![DeployStack IaC Lifecycle](/docs/assets/images/deploystack/iac-lifecycle.webp)
30+
31+
## Update Flow
32+
33+
As the app GitHub repository owner, an update flow gives you control over the generation of Infrastructure as Code (IaC) templates. The flow allows you to regenerate IaC templates by changing, for example, the `.deploystack/docker-compose.yml` file.
34+
35+
All IaC templates are stored in public and open-source repository: [https://github.com/deploystackio/deploy-templates](https://github.com/deploystackio/deploy-templates).
36+
37+
### Prerequisites for activating the flow
38+
39+
1. You have installed the [DeployStack GitHub app](/docs/deploystack/github-application.md).
40+
2. You have created the `.deploystack/docker-run.txt` or `.deploystack/docker-compose.yml` file.
41+
42+
The choice between `docker-run.txt` or `docker-compose.yml` depends on the submission process used to DeployStack. When submitting to DeployStack, you can choose two methods -> Docker Run or Docker Compose.
43+
44+
### Example flow
45+
46+
Let's say you want to change your image tag from "deploystack/awesomeapp:v1" to "deploystack/awesomeapp:v2-next".
47+
48+
![DeployStack IaC Lifecycle](/docs/assets/images/deploystack/deploystack-iac-flow-via-github-app.webp)
49+
50+
1. To do this, you will edit the file `.deploy stack/docker-run.txt` and change your new docker tag
51+
2. GitHub will send an event to the DeployStack backend with the change of the file `.deploy stack/docker-run.txt` because you have the DeployStack GitHub app installed.
52+
3. DeployStack backend validates the change, and if everything test passes
53+
4. By using [docker-to-iac module](https://github.com/deploystackio/docker-to-iac), DeployStack backend will generate the new IaC templates for your application and store them in our repository [https://github.com/deploystackio/deploy-templates](https://github.com/deploystackio/deploy-templates)
3054

3155
## Update Triggers
3256

docs/docker-to-iac/api.md

Lines changed: 114 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -29,29 +29,40 @@ console.log(parsers);
2929
{
3030
providerWebsite: 'https://aws.amazon.com/cloudformation/',
3131
providerName: 'Amazon Web Services',
32-
provieerNameAbbreviation: 'AWS',
32+
providerNameAbbreviation: 'AWS',
3333
languageOfficialDocs: 'https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/Welcome.html',
3434
languageAbbreviation: 'CFN',
3535
languageName: 'AWS CloudFormation',
36-
defaultParserConfig: { fileName: 'aws-cloudformation.yaml', cpu: 512, memory: '1GB', templateFormat: 'yaml' }
36+
defaultParserConfig: { files: [Array], cpu: 512, memory: '1GB' }
3737
},
3838
{
3939
providerWebsite: 'https://render.com/docs',
4040
providerName: 'Render',
41-
provieerNameAbbreviation: 'RND',
41+
providerNameAbbreviation: 'RND',
4242
languageOfficialDocs: 'https://docs.render.com/infrastructure-as-code',
4343
languageAbbreviation: 'RND',
4444
languageName: 'Render Blue Print',
4545
defaultParserConfig: {
46-
subscriptionName: 'free',
46+
files: [Array],
47+
subscriptionName: 'starter',
4748
region: 'oregon',
48-
fileName: 'render.yaml',
49-
templateFormat: 'yaml'
49+
diskSizeGB: 10
5050
}
51+
},
52+
{
53+
providerWebsite: 'https://www.digitalocean.com/',
54+
providerName: 'DigitalOcean',
55+
providerNameAbbreviation: 'DO',
56+
languageOfficialDocs: 'https://docs.digitalocean.com/products/app-platform/',
57+
languageAbbreviation: 'DOP',
58+
languageName: 'DigitalOcean App Spec',
59+
defaultParserConfig: { files: [Array], region: 'nyc', subscriptionName: 'basic-xxs' }
5160
}
5261
]
5362
```
5463

64+
**Note the files array**: that's because we have a [multi file strategy](/docs/docker-to-iac/multi-file-configuration.md).
65+
5566
### Type
5667

5768
```typescript
@@ -77,13 +88,24 @@ console.log(awsInfo);
7788

7889
```json
7990
{
80-
providerWebsite: 'https://aws.amazon.com/cloudformation/',
81-
providerName: 'Amazon Web Services',
82-
provieerNameAbbreviation: 'AWS',
83-
languageOfficialDocs: 'https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/Welcome.html',
84-
languageAbbreviation: 'CFN',
85-
languageName: 'AWS CloudFormation',
86-
defaultParserConfig: { fileName: 'aws-cloudformation.yaml', cpu: 512, memory: '1GB', templateFormat: 'yaml' }
91+
providerWebsite: 'https://aws.amazon.com/cloudformation/',
92+
providerName: 'Amazon Web Services',
93+
providerNameAbbreviation: 'AWS',
94+
languageOfficialDocs: 'https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/Welcome.html',
95+
languageAbbreviation: 'CFN',
96+
languageName: 'AWS CloudFormation',
97+
defaultParserConfig: {
98+
files: [
99+
{
100+
path: 'aws-cloudformation.cf.yml',
101+
templateFormat: 'yaml',
102+
isMain: true,
103+
description: 'AWS CloudFormation template'
104+
}
105+
],
106+
cpu: 512,
107+
memory: '1GB'
108+
}
87109
}
88110
```
89111

@@ -107,75 +129,117 @@ translate(input: string, options: {
107129
environmentVariableGeneration?: EnvironmentVariableGenerationConfig;
108130
environmentVariables?: Record<string, string>;
109131
persistenceKey?: string;
110-
}): any
132+
}): TranslationResult
133+
```
134+
135+
Where `TranslationResult` has the structure:
136+
137+
```typescript
138+
interface TranslationResult {
139+
files: {
140+
[path: string]: FileOutput
141+
};
142+
}
143+
144+
interface FileOutput {
145+
content: string;
146+
format: TemplateFormat;
147+
isMain?: boolean;
148+
}
111149
```
112150

113151
### Examples
114152

115153
#### Translating Docker Compose
116154

117155
```javascript
118-
import { readFileSync, writeFileSync } from 'fs';
156+
import { readFileSync, writeFileSync, mkdirSync, existsSync } from 'fs';
157+
import { join, dirname } from 'path';
119158
import { translate } from '@deploystack/docker-to-iac';
120159

121160
const dockerComposeContent = readFileSync('path/to/docker-compose.yml', 'utf8');
122161

123-
const translatedConfig = translate(dockerComposeContent, {
162+
const result = translate(dockerComposeContent, {
124163
source: 'compose',
125164
target: 'CFN',
126165
templateFormat: 'yaml'
127166
});
128-
console.log(translatedConfig);
167+
168+
// Access individual file contents
169+
console.log(`Generated ${Object.keys(result.files).length} files:`);
170+
Object.keys(result.files).forEach(path => {
171+
console.log(`- ${path}`);
172+
});
173+
174+
// Write files to disk preserving directory structure
175+
Object.entries(result.files).forEach(([path, fileData]) => {
176+
const fullPath = join('output', path);
177+
const dir = dirname(fullPath);
178+
179+
if (!existsSync(dir)) {
180+
mkdirSync(dir, { recursive: true });
181+
}
182+
183+
writeFileSync(fullPath, fileData.content);
184+
});
129185
```
130186

131187
#### Translating Docker Run Command
132188

133189
```javascript
134190
import { translate } from '@deploystack/docker-to-iac';
191+
import { writeFileSync, mkdirSync, existsSync } from 'fs';
192+
import { join, dirname } from 'path';
135193

136194
const dockerRunCommand = 'docker run -d -p 8080:80 nginx:latest';
137195

138-
const translatedConfig = translate(dockerRunCommand, {
196+
const result = translate(dockerRunCommand, {
139197
source: 'run',
140-
target: 'CFN',
198+
target: 'RND',
141199
templateFormat: 'yaml'
142200
});
143-
console.log(translatedConfig);
201+
202+
console.log(result)
203+
204+
// Access and save all generated files
205+
Object.entries(result.files).forEach(([path, fileData]) => {
206+
const fullPath = join('output', path);
207+
const dir = dirname(fullPath);
208+
209+
if (!existsSync(dir)) {
210+
mkdirSync(dir, { recursive: true });
211+
}
212+
213+
writeFileSync(fullPath, fileData.content);
214+
console.log(`Created: ${path}`);
215+
});
144216
```
145217

146218
### Example Output (AWS CloudFormation)
147219

148220
```yaml
149-
AWSTemplateFormatVersion: 2010-09-09
150-
Description: Generated from container configuration by docker-to-iac
151-
Parameters:
152-
VPC:
153-
Type: AWS::EC2::VPC::Id
154-
SubnetA:
155-
Type: AWS::EC2::Subnet::Id
156-
SubnetB:
157-
Type: AWS::EC2::Subnet::Id
158-
ServiceName:
159-
Type: String
160-
Default: DeployStackService
161-
Resources:
162-
Cluster:
163-
Type: AWS::ECS::Cluster
164-
Properties:
165-
ClusterName: !Join ['', [!Ref ServiceName, Cluster]]
166-
ExecutionRole:
167-
Type: AWS::IAM::Role
168-
Properties:
169-
RoleName: !Join ['', [!Ref ServiceName, ExecutionRole]]
170-
AssumeRolePolicyDocument:
171-
Statement:
172-
- Effect: Allow
173-
Principal:
174-
Service: ecs-tasks.amazonaws.com
175-
Action: sts:AssumeRole
176-
ManagedPolicyArns:
177-
- arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy
178-
...
221+
{
222+
files: {
223+
'render.yaml': {
224+
content: 'services:\n' +
225+
' - name: default\n' +
226+
' type: web\n' +
227+
' env: docker\n' +
228+
' runtime: image\n' +
229+
' image:\n' +
230+
' url: docker.io/library/nginx:latest\n' +
231+
' startCommand: ""\n' +
232+
' plan: starter\n' +
233+
' region: oregon\n' +
234+
' envVars:\n' +
235+
' - key: PORT\n' +
236+
' value: "80"\n',
237+
format: 'yaml',
238+
isMain: true
239+
}
240+
}
241+
}
242+
Created: render.yaml
179243
```
180244
181245
#### Translation with Environment Variable Generation

0 commit comments

Comments
 (0)