Skip to content

Commit bdccf70

Browse files
authored
Add support for hemfile (#1)
1 parent cfde8cd commit bdccf70

File tree

15 files changed

+321
-188
lines changed

15 files changed

+321
-188
lines changed

.dockeringnore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
node_modules
2+
.env*
3+
action.yml
4+
LICENSE
5+
README.md
6+
.gitignore
7+
.eslintrc.yml

.gitignore

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,2 @@
1-
test.sh
21
node_modules
3-
.env
2+
.env*

Dockerfile

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
FROM node:14
2+
3+
WORKDIR /app
4+
5+
ARG HELMFILE_VERSION=v0.135.0
6+
7+
ADD https://github.com/roboll/helmfile/releases/download/${HELMFILE_VERSION}/helmfile_linux_amd64 \
8+
/tmp/
9+
10+
COPY . .
11+
12+
RUN npm install \
13+
&& mv /tmp/helmfile_linux_amd64 /usr/local/bin/helmfile \
14+
&& chmod +x /usr/local/bin/helmfile \
15+
&& curl https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 | bash
16+
17+
ENTRYPOINT [ "node", "/app/src/index.js" ]

README.md

Lines changed: 36 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,6 @@ It does so by reading specified file in your repository updating respective
77
dependency/version and opening pull request with this update to against default branch.
88
See _Types_ section to see, what can this action update.
99

10-
> NOTE: This action is not using standard github action execution with `uses` keyword, because that
11-
> would require to check in node_modules. Instead, it clones this action and then runs npm install
12-
> and npm start
13-
1410
## Inputs
1511

1612
Environment variables are used for inputs instead of actual github action inputs,
@@ -55,7 +51,7 @@ By default this type returns latest image based on your inputs:
5551
| INSTANCE_TYPE | Virtualization details, varies based on cloud | `hvm-ssd` | no |
5652
| RELEASE | release (do not supply if you want latest) | `20200924` | no |
5753

58-
## Example
54+
#### Example
5955

6056
```yaml
6157
name: update ubuntu base image
@@ -68,17 +64,11 @@ jobs:
6864
update:
6965
runs-on: ubuntu-20.04
7066
steps:
71-
- name: checkout dragonraid/deployment-bumper
72-
uses: actions/checkout@v2
73-
with:
74-
repository: dragonraid/deployment-bumper
75-
ref: refs/heads/main
76-
path: ./.github/actions/deployment-bumper
77-
- name: run deployment-bumper
78-
working-directory: ./.github/actions/deployment-bumper
67+
- name: update ubuntu AMI
68+
uses: dragonraid/deployment-bumper
7969
env:
8070
TYPE: ubuntu
81-
FILE: packer.json
71+
FILE: ami.json
8272
REPOSITORY: dragonraid/test
8373
USERNAME: ${{ secrets.username }}
8474
PASSWORD: ${{ secrets.password }}
@@ -88,7 +78,36 @@ jobs:
8878
VERSION: '20.04'
8979
ARCHITECTURE: amd64
9080
INSTANCE_TYPE: hvm-ssd
91-
run: |
92-
npm install --only=prod
93-
npm start
81+
```
82+
83+
### Helmfile lock
84+
85+
With this type you can update [helmfile](https://github.com/roboll/helmfile) lock files.
86+
Under the hood this type runs [helmfile deps](https://github.com/roboll/helmfile#deps) command.
87+
88+
| Input | Description | Example | Required |
89+
| :---------- | --------------------------------------: | ------: | -------: |
90+
| ENVIRONMENT | helmfile global options `--environment` | `myEnv` | no |
91+
92+
#### Example
93+
94+
```yaml
95+
name: update helmfile lock
96+
97+
on:
98+
schedule:
99+
- cron: '0 0 1 * *'
100+
101+
jobs:
102+
update:
103+
runs-on: ubuntu-20.04
104+
steps:
105+
- name: update helmfile.lock
106+
uses: dragonraid/deployment-bumper
107+
env:
108+
TYPE: helmfile
109+
FILE: helmfile.yaml
110+
USERNAME: ${{ secrets.username }}
111+
PASSWORD: ${{ secrets.password }}
112+
ENVIRONMENT: staging
94113
```

action.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
name: 'Deployment Bumper'
22
description: 'Update deployment related stuff'
33
runs:
4-
using: 'node12'
4+
using: 'docker'
5+
image: 'Dockerfile'
56
branding:
67
icon: 'edit'
78
color: blue

package.json

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@
55
"main": "src/index.js",
66
"scripts": {
77
"cleanup": "rm -fr /tmp/dragonraid",
8-
"dev": "npm run cleanup && node src/index.js",
9-
"start": "NODE_ENV=production node src/index.js",
10-
"test": "jest ."
8+
"dev-ubuntu": "npm run cleanup && DOTENV_CONFIG_PATH='./.envUbuntu' node -r dotenv/config src/index.js",
9+
"dev-helmfile": "npm run cleanup && DOTENV_CONFIG_PATH='./.envHelmfile' node -r dotenv/config src/index.js",
10+
"start": "node src/index.js",
11+
"test": "jest .",
12+
"lint": "eslint ."
1113
},
1214
"author": {
1315
"name": "Lukas Novotny",

src/github.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,14 @@ class Repository {
1414
* @param {string} username - github username
1515
* @param {string} password - github personal access token
1616
* @param {string} path - where to clone repository
17-
* @param {string} branchNamePrefix - branch name prefix
17+
* @param {string} branchName - branch name prefix
1818
* @param {string} pathPrefix - local repository path prefix
1919
*/
2020
constructor({
2121
repository,
22+
username,
2223
password,
2324
path,
24-
username,
2525
branchName,
2626
pathPrefix = '/tmp/',
2727
}) {

src/handlers.js

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
const { Helmfile } = require('./processors/helmfile');
2+
const { Ubuntu } = require('./processors/ubuntu');
3+
4+
/**
5+
* Ubuntu processor handler. Edits specified value in specified file
6+
* based on input parameters
7+
* @param {object} filePath - full path to file
8+
*/
9+
const handleUbuntu = async (filePath) => {
10+
const filterValues = {
11+
cloud: process.env.CLOUD || null,
12+
zone: process.env.ZONE || null,
13+
version: process.env.VERSION || null,
14+
architecture: process.env.ARCHITECTURE || null,
15+
instanceType: process.env.INSTANCE_TYPE || null,
16+
release: process.env.RELEASE || null,
17+
};
18+
19+
const rawKeys = process.env.KEYS;
20+
let keys;
21+
if (rawKeys) {
22+
keys = rawKeys.split(',');
23+
} else {
24+
throw new Error('KEYS must be supplied!');
25+
}
26+
27+
const filter = {};
28+
Object.keys(filterValues).forEach((value) => {
29+
if (filterValues[value]) filter[value] = filterValues[value];
30+
});
31+
const ubuntu = new Ubuntu(filter, filePath, keys);
32+
await ubuntu.run();
33+
console.log(`File "${filePath}" has been successfully updated.`);
34+
};
35+
36+
/**
37+
* Helmfile processor handler. Updates helmfiles lock file.
38+
* @param {object} filePath - full path to file
39+
*/
40+
const handleHelmfile = async (filePath) => {
41+
const helmfileArgs = {
42+
file: filePath,
43+
};
44+
if (process.env.ENVIRONMENT) {
45+
helmfileArgs.environment = process.env.ENVIRONMENT;
46+
}
47+
48+
const helmfile = new Helmfile(helmfileArgs);
49+
await helmfile.run();
50+
console.log(`File "${filePath}" has been successfully updated.`);
51+
};
52+
53+
module.exports = {
54+
handleUbuntu,
55+
handleHelmfile,
56+
};

src/index.js

Lines changed: 32 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,12 @@
1-
const { File } = require('./file');
21
const { Repository } = require('./github');
3-
const { Ubuntu } = require('./ubuntu');
2+
const handlers = require('./handlers');
43

5-
// load environment variables from .env file if not running in production
6-
if (process.env.NODE_ENV !== 'production') {
7-
require('dotenv').config();
8-
}
9-
10-
// Check if environment variable exists, otherwise set default
4+
/**
5+
* Raw configuration.
6+
*/
117
const RAW_CONFIG = {
128
TYPE: process.env.TYPE || null,
139
FILE: process.env.FILE || null,
14-
KEYS: process.env.KEYS || null,
1510
BRANCH_NAME: process.env.BRANCH_NAME || process.env.TYPE,
1611
BRANCH_PREFIX: process.env.BRANCH_PREFIX || 'update',
1712
REPOSITORY: process.env.REPOSITORY || process.env.GITHUB_REPOSITORY,
@@ -30,45 +25,22 @@ const CONFIG = {};
3025
const processConfig = () => {
3126
for (const [key, value] of Object.entries(RAW_CONFIG)) {
3227
if (!value) {
33-
if (value === 'USERNAME' || value === 'PASSWORD') continue;
28+
if (key === 'USERNAME' || key === 'PASSWORD') {
29+
throw new Error(`Invalid USERNAME or PASSWORD!`);
30+
};
3431
throw new Error(
3532
`Invalid configuration value: ${value} for ${key}.`,
3633
);
3734
}
38-
switch (key) {
39-
case 'KEYS':
40-
CONFIG[key] = value.split(',');
41-
break;
42-
default:
43-
CONFIG[key] = value;
44-
}
35+
CONFIG[key] = value;
4536
}
4637
};
4738

48-
const handleUbuntu = async () => {
49-
const filterValues = {
50-
cloud: process.env.CLOUD || null,
51-
zone: process.env.ZONE || null,
52-
version: process.env.VERSION || null,
53-
architecture: process.env.ARCHITECTURE || null,
54-
instanceType: process.env.INSTANCE_TYPE || null,
55-
release: process.env.RELEASE || null,
56-
};
57-
58-
const filter = {};
59-
Object.keys(filterValues).forEach((value) => {
60-
if (filterValues[value]) filter[value] = filterValues[value];
61-
});
62-
const ubuntu = new Ubuntu(filter);
63-
const latestUbuntu = await ubuntu.latest;
64-
const keyValuePairs = {};
65-
CONFIG.KEYS.forEach((key) => {
66-
keyValuePairs[key] = latestUbuntu.id;
67-
});
68-
69-
return keyValuePairs;
70-
};
71-
39+
/**
40+
* Clone repository and checkout the feature branch
41+
* @param {string} branchName - feature branch name
42+
* @return {object}
43+
*/
7244
const initializeRepo = async (branchName) => {
7345
const repository = new Repository({
7446
repository: CONFIG.REPOSITORY,
@@ -81,57 +53,37 @@ const initializeRepo = async (branchName) => {
8153
return repository;
8254
};
8355

84-
const throwError = (resolved) => {
85-
resolved.forEach((process) => {
86-
if (process.status === 'rejected') {
87-
console.error('An error has occurred.');
88-
throw new Error(JSON.stringify(process.reason));
89-
}
90-
});
91-
};
92-
93-
const TYPE_PROCESSORS = {
94-
ubuntu: handleUbuntu,
56+
/**
57+
* Define handle types
58+
*/
59+
const PROCESSOR_TYPES = {
60+
ubuntu: handlers.handleUbuntu,
61+
helmfile: handlers.handleHelmfile,
9562
};
9663

97-
const main = async () => {
64+
/**
65+
* Main function
66+
*/
67+
(async () => {
9868
try {
9969
processConfig();
10070
} catch (err) {
10171
console.error('Config processor has failed!', err);
10272
process.exit(1);
10373
}
104-
const processor = await Promise.allSettled([
105-
TYPE_PROCESSORS[CONFIG.TYPE](),
106-
// TODO: option for supplying custom branch name and custom prefix
107-
initializeRepo(`${CONFIG.BRANCH_PREFIX}/${CONFIG.BRANCH_NAME}`),
108-
]);
109-
throwError(processor);
110-
console.log(`Successfully executed processor ${CONFIG.TYPE}.`);
111-
112-
const repository = processor[1].value;
113-
const filePath = `${repository.path}/${CONFIG.FILE}`;
114-
const keyValuePairs = processor[0].value;
115-
116-
try {
117-
const file = new File({ filePath, keyValuePairs });
118-
await file.run();
119-
} catch (err) {
120-
console.error('Updating file has failed!', err);
121-
process.exit(1);
122-
}
123-
console.log(`File "${filePath}" has been successfully updated.`);
12474

12575
try {
76+
const repository = await initializeRepo(
77+
`${CONFIG.BRANCH_PREFIX}/${CONFIG.BRANCH_NAME}`,
78+
);
79+
const fullFilePath = `${repository.path}/${CONFIG.FILE}`;
80+
await PROCESSOR_TYPES[CONFIG.TYPE](fullFilePath);
81+
console.log(`Successfully executed processor ${CONFIG.TYPE}.`);
12682
await repository.push(`update ${CONFIG.TYPE}`);
12783
await repository.createPullRequest();
84+
console.log('Pull-request created.');
12885
} catch (err) {
129-
console.error(`Opening pull request with changes has failed!`, err);
86+
console.error(`${CONFIG.TYPE} processor failed.`, err);
13087
process.exit(1);
13188
}
132-
console.log(
133-
`Successfully pushed branch "${repository.branchName}" to remote.`,
134-
);
135-
};
136-
137-
main();
89+
})();

0 commit comments

Comments
 (0)