Compare commits

...

32 Commits

Author SHA1 Message Date
Eli Bosley
46d4564b63 feat: remove artifact comment 2023-08-31 16:24:43 -04:00
Eli Bosley
005a7c0f52 feat: remove build-cache step 2023-08-31 16:19:45 -04:00
Eli Bosley
c270e86377 fix: tag script issues 2023-08-31 16:13:07 -04:00
Eli Bosley
ee0293eaae fix: allow segfault retries on coverage 2023-08-31 13:20:17 -04:00
Eli Bosley
3863659093 feat: fix tag 2023-08-31 12:09:39 -04:00
Eli Bosley
1fe76f3ed4 feat: extract tag fetch logic to file 2023-08-31 11:59:17 -04:00
Eli Bosley
bd65db1c88 fix: tagged step 2023-08-31 11:44:03 -04:00
Eli Bosley
5860bf128b revert: back to alpine-sdk 2023-08-31 11:38:16 -04:00
Eli Bosley
b5a6b7c484 feat: test passing tag to build step 2023-08-31 11:34:53 -04:00
Eli Bosley
878ad60a50 fix: missing registry 2023-08-31 11:20:33 -04:00
Eli Bosley
404756bb48 fix: copy all files on build 2023-08-31 11:19:49 -04:00
Eli Bosley
ab0174c2e2 fix: rearrange build 2023-08-31 11:17:32 -04:00
Eli Bosley
478b5dce2b feat: build step fixed 2023-08-31 11:12:53 -04:00
Eli Bosley
8e0bf02962 fix: local registry 2023-08-31 11:05:17 -04:00
Eli Bosley
0250b9e46f fix: use local registry 2023-08-31 11:01:56 -04:00
Eli Bosley
ef49072cdb feat: load image after build 2023-08-31 10:56:58 -04:00
Eli Bosley
98d9bebd44 fix: branch name 2023-08-31 10:53:40 -04:00
Eli Bosley
7d9704af5e feat: test GHA build caching 2023-08-31 10:52:46 -04:00
Eli Bosley
4ea00ed3ad feat: simplify package install 2023-08-31 10:42:37 -04:00
Eli Bosley
e1f77df400 feat: remove build args 2023-08-31 10:40:15 -04:00
Eli Bosley
d5f8c73b13 fix: curly braces 2023-08-31 10:38:14 -04:00
Eli Bosley
ee868b11e4 fix: tag in build step 2023-08-31 10:37:22 -04:00
Eli Bosley
14f5cbdfd3 fix: tagging 2023-08-31 10:33:23 -04:00
Eli Bosley
3b4e454ace fix: tag fixed 2023-08-31 10:29:12 -04:00
Eli Bosley
a09ea7b036 fix: env var extraction 2023-08-31 10:26:19 -04:00
Eli Bosley
3cfa302530 fix: use buildx 2023-08-31 10:25:15 -04:00
Eli Bosley
002e800360 feat: use docker build step 2023-08-31 10:23:35 -04:00
Eli Bosley
53cea624d5 feat: tag image properly 2023-08-31 10:14:20 -04:00
Eli Bosley
2e25117635 fix: repo name 2023-08-31 10:09:45 -04:00
Eli Bosley
1522d44ab7 feat: secret key update 2023-08-30 16:52:08 -04:00
Eli Bosley
63c1a60e90 feat: push to aws 2023-08-30 16:50:53 -04:00
Eli Bosley
6c0aea6dd2 feat: try to quicken builds by using docker and sharing image 2023-08-30 16:35:25 -04:00
12 changed files with 255 additions and 126 deletions

View File

@@ -5,13 +5,18 @@ on:
paths:
- api/**
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
lint-api:
services:
registry: # Using a local registry is ~3x faster than exporting the image to docker agent
image: registry:2
ports:
- 5000:5000
continue-on-error: true
defaults:
run:
@@ -21,58 +26,65 @@ jobs:
- name: Checkout repo
uses: actions/checkout@v3
with:
persist-credentials: false
- name: Reconfigure git to use HTTP authenti:cation
run: >
git config --global url."https://github.com/".insteadOf
ssh://git@github.com/
- name: Install node
uses: actions/setup-node@v3
persist-credentials: true
- uses: docker/setup-buildx-action@v2
with:
node-version-file: "api/.nvmrc"
# - name: Cache dependencies
# uses: actions/cache@v2
# with:
# path: ~/.npm
# key: npm-${{ hashFiles('package-lock.json') }}
# restore-keys: npm-
- name: Install libvirt-dev
run: sudo apt-get update && sudo apt-get install libvirt-dev
- name: Installing node deps
run: npm ci
- name: Lint files
run: npm run lint
# network=host driver-opt needed to push to local registry
driver-opts: network=host
- name: Build and push
uses: docker/build-push-action@v4
with:
context: api
target: builder
push: true
tags: localhost:5000/unraid-api:builder
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Lint
run: |
docker run localhost:5000/unraid-api:builder npm run lint
test-api:
services:
registry: # Using a local registry is ~3x faster than exporting the image to docker agent
image: registry:2
ports:
- 5000:5000
defaults:
run:
working-directory: api
runs-on: ubuntu-latest
steps:
- name: Checkout repo
uses: actions/checkout@v3
with:
persist-credentials: false
persist-credentials: true
- uses: docker/setup-buildx-action@v2
with:
# network=host driver-opt needed to push to local registry
driver-opts: network=host
- name: Reconfigure git to use HTTP authentication
run: >
git config --global url."https://github.com/".insteadOf
ssh://git@github.com/
- name: Build Docker Compose
- name: Build and push
uses: docker/build-push-action@v4
with:
context: api
target: builder
push: true
tags: localhost:5000/unraid-api:builder
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Test
run: |
docker network create mothership_default
docker-compose build builder
- name: Run Docker Compose
run: docker-compose run builder npm run coverage
docker run localhost:5000/unraid-api:builder npm run coverage
build-api:
services:
registry: # Using a local registry is ~3x faster than exporting the image to docker agent
image: registry:2
ports:
- 5000:5000
defaults:
run:
working-directory: api
@@ -86,31 +98,25 @@ jobs:
steps:
- name: Checkout repo
uses: actions/checkout@v3
- name: Install node
uses: actions/setup-node@v3
with:
node-version-file: "api/.nvmrc"
persist-credentials: true
- uses: docker/setup-buildx-action@v2
with:
# network=host driver-opt needed to push to local registry
driver-opts: network=host
- name: Install libvirt-dev
run: sudo apt-get update && sudo apt-get install libvirt-dev
- name: Build and push
uses: docker/build-push-action@v4
with:
context: api
target: builder
push: true
tags: localhost:5000/unraid-api:builder
cache-from: type=gha
cache-to: type=gha,mode=max
# - name: Cache dependencies
# uses: actions/cache@v2
# with:
# path: ~/.npm
# key: npm-${{ hashFiles('package-lock.json') }}
# restore-keys: npm-
- name: Installing node deps
run: npm install
- name: Install pkg
run: npm i -g pkg
- name: Build and Pack
id: build-pack-binary
run: WORKDIR=${{ github.workspace }} && npm run build-pkg
- name: Run Build
run: docker run -e GIT_SHA=$(git rev-parse --short HEAD) -e IS_TAGGED=$(git describe --tags --abbrev=0 --exact-match) -v $(pwd)/deploy:/app/deploy/ localhost:5000/unraid-api:builder npm run build-pkg
- name: Set Hashes
id: set-hashes

View File

@@ -1,11 +1,12 @@
###########################################################
# Development/Build Image
###########################################################
ARG NODE_IMAGE=node:18.17.1
FROM $NODE_IMAGE As development
FROM node:18.17.1-alpine As development
# Install build tools
RUN apt-get update -y && apt-get install -y \
# Install build tools and dependencies
RUN apk add --no-cache \
bash \
alpine-sdk \
python3 \
libvirt-dev \
jq \
@@ -13,30 +14,33 @@ RUN apt-get update -y && apt-get install -y \
RUN mkdir /var/log/unraid-api/
ARG NODE_ENV=development
ARG NPM_I_CMD=npm i
WORKDIR /app
# Set app env
ENV NODE_ENV=$NODE_ENV
ENV NODE_ENV=development
# Setup cache for pkg
ENV PKG_CACHE_PATH /app/.pkg-cache
RUN mkdir -p ${PKG_CACHE_PATH}
COPY package.json package-lock.json ./
COPY tsconfig.json tsup.config.ts ./
COPY .npmrc ./
COPY .env.production .env.staging ./
COPY tsconfig.json tsup.config.ts .eslintrc.cjs .npmrc .env.production .env.staging ./
# Install deps
RUN $NPM_I_CMD
COPY package.json package-lock.json ./
# Install pkg
RUN npm i -g pkg zx
# Install deps
RUN npm ci
EXPOSE 4000
###########################################################
# Builder Image
###########################################################
FROM development AS builder
COPY . .
CMD ["npm", "run", "build-pkg"]

View File

@@ -1,5 +1,5 @@
[api]
version="3.1.1+251f9020"
version="3.1.1+8efc0992"
[local]
[notifier]
apikey="unnotify_30994bfaccf839c65bae75f7fa12dd5ee16e69389f754c3b98ed7d5"

View File

@@ -1,5 +1,5 @@
[api]
version="3.1.1+251f9020"
version="3.1.1+8efc0992"
[local]
[notifier]
apikey="unnotify_30994bfaccf839c65bae75f7fa12dd5ee16e69389f754c3b98ed7d5"

View File

@@ -27,22 +27,18 @@ x-volumes: &volumes
networks:
mothership_default:
external: true
services:
dev:
networks:
- mothership_default
image: unraid-api-node-18
image: unraid-api:development
ports:
- "3001:3001"
build:
context: .
target: development
dockerfile: Dockerfile
args:
NODE_IMAGE: node:18.17.1
NODE_ENV: development
NPM_I_CMD: npm i
<<: *volumes
stdin_open: true
tty: true
@@ -54,15 +50,11 @@ services:
builder:
image: unraid-api-node-18
image: unraid-api:builder
build:
context: .
target: builder
dockerfile: Dockerfile
args:
NODE_IMAGE: node:18.17.1
NODE_ENV: development
NPM_I_CMD: npm i
<<: *volumes
platform: linux/amd64
profiles:
- builder

40
api/package-lock.json generated
View File

@@ -63,7 +63,6 @@
"pidusage": "^3.0.2",
"reflect-metadata": "^0.1.13",
"request": "^2.88.2",
"segfault-handler": "^1.3.0",
"semver": "^7.4.0",
"stoppable": "^1.1.0",
"subscriptions-transport-ws": "^0.11.0",
@@ -102,7 +101,7 @@
"@types/ini": "^1.3.31",
"@types/lodash": "^4.14.192",
"@types/mustache": "^4.2.2",
"@types/node": "^18.15.11",
"@types/node": "^18.17.12",
"@types/pidusage": "^2.0.2",
"@types/pify": "^5.0.1",
"@types/semver": "^7.3.13",
@@ -3260,7 +3259,8 @@
},
"node_modules/@types/node": {
"version": "18.17.12",
"license": "MIT"
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.17.12.tgz",
"integrity": "sha512-d6xjC9fJ/nSnfDeU0AMDsaJyb1iHsqCSOdi84w4u+SlN/UgQdY5tRhpMzaFYsI4mnpvgTivEaQd0yOUhAtOnEQ=="
},
"node_modules/@types/node-fetch": {
"version": "2.6.3",
@@ -4317,6 +4317,7 @@
"node_modules/bindings": {
"version": "1.5.0",
"license": "MIT",
"optional": true,
"dependencies": {
"file-uri-to-path": "1.0.0"
}
@@ -7452,7 +7453,8 @@
},
"node_modules/file-uri-to-path": {
"version": "1.0.0",
"license": "MIT"
"license": "MIT",
"optional": true
},
"node_modules/fill-range": {
"version": "7.0.1",
@@ -10705,7 +10707,8 @@
},
"node_modules/nan": {
"version": "2.17.0",
"license": "MIT"
"license": "MIT",
"optional": true
},
"node_modules/nanoassert": {
"version": "1.1.0",
@@ -12852,15 +12855,6 @@
"dev": true,
"license": "MIT"
},
"node_modules/segfault-handler": {
"version": "1.3.0",
"hasInstallScript": true,
"license": "BSD-3-Clause",
"dependencies": {
"bindings": "^1.2.1",
"nan": "^2.14.0"
}
},
"node_modules/semver": {
"version": "7.5.4",
"license": "ISC",
@@ -17608,7 +17602,9 @@
"dev": true
},
"@types/node": {
"version": "18.17.12"
"version": "18.17.12",
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.17.12.tgz",
"integrity": "sha512-d6xjC9fJ/nSnfDeU0AMDsaJyb1iHsqCSOdi84w4u+SlN/UgQdY5tRhpMzaFYsI4mnpvgTivEaQd0yOUhAtOnEQ=="
},
"@types/node-fetch": {
"version": "2.6.3",
@@ -18273,6 +18269,7 @@
},
"bindings": {
"version": "1.5.0",
"optional": true,
"requires": {
"file-uri-to-path": "1.0.0"
}
@@ -20298,7 +20295,8 @@
}
},
"file-uri-to-path": {
"version": "1.0.0"
"version": "1.0.0",
"optional": true
},
"fill-range": {
"version": "7.0.1",
@@ -22331,7 +22329,8 @@
}
},
"nan": {
"version": "2.17.0"
"version": "2.17.0",
"optional": true
},
"nanoassert": {
"version": "1.1.0"
@@ -23626,13 +23625,6 @@
"version": "1.1.0",
"dev": true
},
"segfault-handler": {
"version": "1.3.0",
"requires": {
"bindings": "^1.2.1",
"nan": "^2.14.0"
}
},
"semver": {
"version": "7.5.4",
"requires": {

View File

@@ -13,7 +13,6 @@
"pkg": {
"assets": [
"dist/index.cjs",
"node_modules/segfault-handler",
"node_modules/@vmngr/libvirt/build/Release",
"node_modules/ts-invariant/",
"src/**/*.graphql"
@@ -37,7 +36,7 @@
"lint:fix": "DEBUG=eslint:cli-engine eslint . --fix --config .eslintrc.cjs",
"test:watch": "vitest --segfault-retry=3 --no-threads",
"test": "vitest run --segfault-retry=3 --no-threads",
"coverage": "vitest run --coverage",
"coverage": "vitest run --segfault-retry=3 --coverage",
"patch:subscriptions-transport-ws": "node ./.scripts/patches/subscriptions-transport-ws.cjs",
"release": "standard-version",
"typesync": "typesync",
@@ -112,7 +111,6 @@
"pidusage": "^3.0.2",
"reflect-metadata": "^0.1.13",
"request": "^2.88.2",
"segfault-handler": "^1.3.0",
"semver": "^7.4.0",
"stoppable": "^1.1.0",
"subscriptions-transport-ws": "^0.11.0",
@@ -148,7 +146,7 @@
"@types/ini": "^1.3.31",
"@types/lodash": "^4.14.192",
"@types/mustache": "^4.2.2",
"@types/node": "^18.15.11",
"@types/node": "^18.17.12",
"@types/pidusage": "^2.0.2",
"@types/pify": "^5.0.1",
"@types/semver": "^7.3.13",

72
api/scripts/build.mjs Executable file
View File

@@ -0,0 +1,72 @@
#!/usr/bin/env zx
import { exit } from 'process';
import { cd, $ } from 'zx';
import getTags from './get-tags.mjs'
try {
// Enable colours in output
process.env.FORCE_COLOR = '1';
// Ensure we have the correct working directory
process.env.WORKDIR = process.env.WORKDIR ?? process.env.PWD;
cd(process.env.WORKDIR);
// Clean up last deploy
await $`rm -rf ./deploy/release`;
await $`rm -rf ./deploy/pre-pack`;
await $`mkdir -p ./deploy/release/`;
await $`mkdir -p ./deploy/pre-pack/`;
// Ensure all deps are installed
await $`npm i`;
// Build Generated Types
await $`npm run codegen`;
// Build binary
await $`npm run build`;
// Copy binary + extra files to deployment directory
await $`cp ./dist/api ./deploy/pre-pack/unraid-api`;
await $`cp ./.env.production ./deploy/pre-pack/.env.production`;
await $`cp ./.env.staging ./deploy/pre-pack/.env.staging`;
// Get package details
const { name, version } = await import('../package.json', {
assert: { type: 'json' },
}).then(pkg => pkg.default);
const tags = getTags(process.env);
// Decide whether to use full version or just tag
const isTaggedRelease = tags.isTagged;
const gitShaShort = tags.shortSha;
const deploymentVersion = isTaggedRelease ? version : `${version}+${gitShaShort}`;
// Create deployment package.json
await $`echo ${JSON.stringify({ name, version: deploymentVersion })} > ./deploy/pre-pack/package.json`;
// # Create final tgz
await $`cp ./README.md ./deploy/pre-pack/`;
cd('./deploy/pre-pack');
await $`npm pack`;
// Move unraid-api.tgz to release directory
await $`mv unraid-api-${deploymentVersion}.tgz ../release`;
// Set API_VERSION output based on this command
await $`echo "::set-output name=API_VERSION::${deploymentVersion}"`;
} catch (error) {
// Error with a command
if (Object.keys(error).includes('stderr')) {
console.log(`Failed building package. Exit code: ${error.exitCode}`);
console.log(`Error: ${error.stderr}`);
} else {
// Normal js error
console.log('Failed building package.');
console.log(`Error: ${error.message}`);
}
exit(error.exitCode);
}

33
api/scripts/get-tags.mjs Normal file
View File

@@ -0,0 +1,33 @@
import { execSync } from 'child_process';
const runCommand = (command) => {
try {
return execSync(command, { stdio: 'pipe' }).toString().trim();
} catch(error) {
console.log('Failed to get value from tag command: ', command, error.message);
return;
}
};
const getTags = (env = process.env) => {
if (env.GIT_SHA) {
return {
shortSha: env.GIT_SHA,
isTagged: Boolean(env.IS_TAGGED)
}
} else {
const gitShortSHA = runCommand('git rev-parse --short HEAD');
const isCommitTagged = runCommand('git describe --tags --abbrev=0 --exact-match') !== undefined;
console.log('gitShortSHA', gitShortSHA, 'isCommitTagged', isCommitTagged);
if (!gitShortSHA) {
throw new Error('Failing build due to missing SHA');
}
return {
shortSha: gitShortSHA,
isTagged: isCommitTagged
}
}
}
export default getTags;

11
api/src/cli.ts Normal file
View File

@@ -0,0 +1,11 @@
import 'wtfnode';
import { am } from 'am';
import { main } from '@app/cli/index';
import { internalLogger } from '@app/core/log';
void am(main, (error: unknown) => {
internalLogger.fatal((error as Error).message);
// Ensure process is exited
process.exit(1);
});

View File

@@ -1,4 +1,3 @@
import { causeSegfault } from 'segfault-handler';
import { parse } from 'ts-command-line-args';
import { cliLogger } from '@app/core/log';
import { type Flags, mainOptions, options, args } from '@app/cli/options';
@@ -64,14 +63,6 @@ export const main = async (...argv: string[]) => {
// Run the command
await commandMethod(...argv);
// Only segfault in a specific mode
if (process.env.PLEASE_SEGFAULT_FOR_ME) {
// Wait 30s and then segfault
setTimeout(() => {
causeSegfault();
}, 30_000);
}
// Allow the process to exit
// Don't exit when we start though
if (!['start', 'restart'].includes(command)) {

30
api/tsup.config.ts Normal file
View File

@@ -0,0 +1,30 @@
import { execSync } from 'child_process';
import 'dotenv/config';
import { defineConfig } from 'tsup';
import { version } from './package.json';
import getTags from './scripts/get-tags.mjs'
export default defineConfig({
name: 'tsup',
target: 'node18',
entry: {
'unraid-api': 'src/cli.ts',
index: 'src/index.ts',
},
metafile: true,
splitting: false,
sourcemap: true,
clean: true,
external: ['@vmngr/libvirt'],
esbuildOptions(options) {
if (!options.define) options.define = {};
const tags = getTags(process.env);
options.define['process.env.VERSION'] = tags.isTagged
? `"${version}"`
: `"${version}+${tags.shortSha}"`;
},
});