Skip to content

Commit

Permalink
[Upload] All files
Browse files Browse the repository at this point in the history
  • Loading branch information
mist8kengas committed Apr 3, 2022
1 parent d95a48b commit 642317d
Show file tree
Hide file tree
Showing 13 changed files with 561 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
HELMSMAN_HTTP_PORT=5000
HELMSMAN_HTTP_ADDR="localhost"
HELMSMAN_WEBHOOK_SECRET=""
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
node_modules
dist
var
.env
*.tsbuildinfo
4 changes: 4 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
node_modules
dist
package*.json
tsconfig*
11 changes: 11 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"arrowParens": "always",
"bracketSpacing": true,
"endOfLine": "crlf",
"quoteProps": "as-needed",
"semi": true,
"singleQuote": true,
"tabWidth": 4,
"trailingComma": "es5",
"useTabs": false
}
71 changes: 71 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# Helmsman

CI/CD from GitHub to your own servers

### Description

Helmsman is a microservice that allows you to have CI/CD features on your own server

### Prerequisites/Dependencies

- Public-facing server via port forwarding or reverse proxying (nginx/ngrok)
- [Node](https://nodejs.org/)
- [Node Package Manager (npm)](https://www.npmjs.com/)

### Installation

```bash
# download/clone the repository
git clone https://github.com/mist8kengas/helmsman

# install the required packages
npm install

# build the program
npm run build

# start Helmsman
npm start
```

### Configuration (.env file)

Copy the contents of the example environment file `.env.example` to `.env` and modify the contents:
| Variable | Description | Required | Default |
| --------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------- |
| **HELMSMAN_HTTP_PORT** | Port the web server listens to | | `5000` |
| **HELMSMAN_HTTP_ADDR** | Address the web server listens to | | `localhost` |
| **HELMSMAN_WEBHOOK_SECRET** | Secret used in the webhook on your GitHub repository. [How to set your secret token](https://docs.github.com/en/developers/webhooks-and-events/webhooks/securing-your-webhooks#setting-your-secret-token) | Yes | _N/A_ |

### Configuration (setting up CI/CD)

When you first run the program, an empty JSON file `ci_cd.json` will be created automatically in the `./var/config` directory, this is where you will configure your CI/CD

The structure of this file is:

```json
{
"<username>/<repository>": {
"<event>": "<command>"
}
}
```

- `<username>/<repository>` is the full name of the repository (eg: [mist8kengas/helmsman](https://github.com/mist8kengas/helmsman))
- `<event>` refers to the name of the event that triggered the webhook (eg: `ping`, `push`, `release`, etc.) [See all the possible event names here](https://docs.github.com/en/developers/webhooks-and-events/webhooks/webhook-events-and-payloads)
- `<command>` will be executed by the program, so be careful what you put in here. Similar to command-execution via CLI (eg: `echo "Hello!"`)

### Creating the webhook

Once you have finished configuring Helmsman, it's time to create the webhook on your GitHub repository

1. Go to the Settings of your repository
2. Under 'Code and automation', click on 'Webhooks'
3. Click 'Add webhook'
4. Set 'Payload URL' to the public URL of Helmsman with appended path `/webhook` (eg: `https://example.com/webhook`)
5. Set 'Content type' to `application/json`
6. Set 'Secret' to the secret you set in your `.env` file
7. Select which events would you like to be sent to Helmsman
8. Click on 'Add webhook' and you're set!

_**NOTE** If you are not using SSL: After you have finished adding the webhook, edit your webhook and disable 'SSL verification'._
168 changes: 168 additions & 0 deletions src/github.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
interface User {
name: string;
email: string;
username: string;
}

interface Commit {
id: string;
timestamp: string;
message: string;
author: {
name: string;
email: string;
};
url: string;
distinct: boolean;
added: string[];
modified: string[];
removed: string[];
}

interface Webhook {
ref: string;
before: string;
after: string;
created: boolean;
deleted: boolean;
forced: boolean;
head_commit: {
id: string;
tree_id: string;
distict: boolean;
message: string;
timestamp: string;
url: string;
author: User;
committer: User;
added: string[];
removed: string[];
modified: string[];
};
base_ref: string;
compare: string;
commits: Commit[];
pusher: {
name: string;
email: string;
};
repository: {
id: number;
node_id: string;
name: string;
full_name: string;
private: boolean;
owner: {
name: string;
email: string;
login: string;
id: number;
node_id: string;
avatar_url: string;
gravatar_id: string;
url: string;
html_url: string;
followers_url: string;
following_url: string;
gists_url: string;
starred_url: string;
subscriptions_url: string;
organizations_url: string;
repos_url: string;
events_url: string;
received_events_url: string;
type: 'User';
site_admin: boolean;
};
html_url: string;
description: string | null;
fork: boolean;
url: string;
forks_url: string;
keys_url: string;
collaborators_url: string;
teams_url: string;
hooks_url: string;
issue_events_url: string;
events_url: string;
assignees_url: string;
branches_url: string;
tags_url: string;
blobs_url: string;
git_tags_url: string;
git_refs_url: string;
trees_url: string;
statuses_url: string;
languages_url: string;
stargazers_url: string;
contributors_url: string;
subscribers_url: string;
subscription_url: string;
commits_url: string;
git_commits_url: string;
comments_url: string;
issue_comment_url: string;
contents_url: string;
compare_url: string;
merges_url: string;
archive_url: string;
downloads_url: string;
issues_url: string;
pulls_url: string;
milestones_url: string;
notifications_url: string;
labels_url: string;
releases_url: string;
deployments_url: string;
created_at: number;
updated_at: string;
pushed_at: number;
git_url: string;
ssh_url: string;
clone_url: string;
svn_url: string;
homepage: string | null;
size: number;
stargazers_count: number;
watchers_count: number;
language: string;
has_issues: boolean;
has_projects: boolean;
has_downloads: boolean;
has_wiki: boolean;
has_pages: boolean;
forks_count: number;
mirror_url: string | null;
archived: boolean;
disabled: boolean;
open_issues_count: number;
license: string | null;
forks: number;
open_issues: number;
watchers: number;
default_branch: string;
stargazers: number;
master_branch: string;
};
organization?: object;
sender: {
login: string;
id: number;
node_id: string;
avatar_url: string;
gravatar_id: string;
url: string;
html_url: string;
followers_url: string;
following_url: string;
gists_url: string;
starred_url: string;
subscriptions_url: string;
organizations_url: string;
repos_url: string;
events_url: string;
received_events_url: string;
type: 'User';
site_admin: boolean;
};
}
14 changes: 14 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import logger from './utils/logger.js';

// import server
import './server/index.js';

// setup - check if ci.json exists
import { existsSync, writeFileSync } from 'fs';
if (!existsSync('./var/config/ci_cd.json')) {
writeFileSync('./var/config/ci_cd.json', '{}');
logger(
`Created file "./var/config/ci_cd.json" because it does not exist`,
'info'
);
}
35 changes: 35 additions & 0 deletions src/server/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import express from 'express';
const app = express();

import 'colors';
import logger from '../utils/logger.js';

// import .env
import * as env from 'dotenv';
env.config({ encoding: 'utf8' });
const { HELMSMAN_HTTP_PORT = '5000', HELMSMAN_HTTP_ADDR = 'localhost' } =
process.env;

// parse POST data
import bodyParser from 'body-parser';
app.use(bodyParser.raw({ inflate: true, type: () => !0 }));

import route_Webhook from './routes/webhook.js';
app.use('/webhook', route_Webhook);

// responses
import response from './response.js';
app.use(response);

// listen
app.listen(+HELMSMAN_HTTP_PORT, HELMSMAN_HTTP_ADDR, () => {
console.log(
'[server]'.green,
'Listening on',
`http://${HELMSMAN_HTTP_ADDR}:${HELMSMAN_HTTP_PORT}`.yellow.underline
);
logger(
`Listening on http://${HELMSMAN_HTTP_ADDR}:${HELMSMAN_HTTP_PORT}`,
'info'
);
});
28 changes: 28 additions & 0 deletions src/server/response.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { NextFunction, Request, Response } from 'express';

const response: { [index: number]: string } = {
'200': 'OK',
'201': 'Created',
'202': 'Accepted',
'400': 'Bad Request',
'401': 'Unauthorized',
'403': 'Forbidden',
'404': 'Not Found',
'405': 'Not Allowed',
'500': 'Internal Server Error',
'503': 'Service Unavailable',
};

export default function ResponseHandler(
status: number,
req: Request,
res: Response,
next: NextFunction
) {
if (!response[status]) return next();
res.status(status).json({
status,
message: response[status],
time: ~~(Date.now() / 1e3),
});
}
Loading

0 comments on commit 642317d

Please sign in to comment.