Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(server): build using esbuild, publish container, nginx #138

Merged
merged 13 commits into from
Nov 26, 2023
Merged
22 changes: 22 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,25 @@ updates:
patterns:
- '@alwatr/*'
- 'fract'

- package-ecosystem: docker
directory: /packages/nginx
reviewers:
- AliMD
schedule:
interval: daily
labels:
- ci
- priority-low
- maintenance

- package-ecosystem: docker
directory: /packages/server
reviewers:
- AliMD
schedule:
interval: daily
labels:
- ci
- priority-low
- maintenance
116 changes: 116 additions & 0 deletions .github/workflows/publish-container.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
# yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json

name: Build & Publish Containers

on:
workflow_dispatch:

push:
branches:
- next

pull_request:

release:
types:
- created

env:
USER: alwatr

jobs:
build:
if: github.repository_owner == 'Alwatr'

name: Build & Publish Containers
runs-on: ubuntu-latest

strategy:
fail-fast: false
matrix:
include:
- path: server
- path: nginx

permissions:
contents: read
packages: write
id-token: write

steps:
- name: ⤵️ Checkout repository
uses: actions/[email protected]

- name: ❔ Check Container files changed
id: file_change
if: ${{ github.event_name != 'release' && github.event_name != 'workflow_dispatch' }}
uses: dorny/[email protected]
with:
filters: |
container_folder:
./packages/${{ matrix.path }}/*

- name: 🏗 Install cosign
if: ${{ github.event_name != 'pull_request' && steps.file_change.outputs.container_folder != 'false' }}
uses: sigstore/[email protected]

- name: 🏗 Setup Docker Buildx
if: ${{ steps.file_change.outputs.container_folder != 'false' }}
uses: docker/[email protected]

- name: 🏗 Cache Docker Layers
if: ${{ steps.file_change.outputs.container_folder != 'false' }}
uses: actions/cache@v3
with:
path: /tmp/.buildx-cache
key: container/${{ matrix.path }}

- name: 🏗 Log into docker hub registry
if: ${{ github.event_name != 'pull_request' && steps.file_change.outputs.container_folder != 'false' }}
uses: docker/[email protected]
with:
username: ${{env.USER}}
password: ${{secrets.DOCKER_HUB_TOKEN}}

- name: 🏗 Log into ghcr.io registry
if: ${{ github.event_name != 'pull_request' && steps.file_change.outputs.container_folder != 'false' }}
uses: docker/[email protected]
with:
registry: ghcr.io
username: ${{env.USER}}
password: ${{secrets.GITHUB_TOKEN}}

- name: 🏗 Extract metadata
if: ${{ steps.file_change.outputs.container_folder != 'false' }}
id: meta
uses: docker/[email protected]
with:
github-token: ${{secrets.GITHUB_TOKEN}}
images: |
name=ghcr.io/${{env.USER}}/${{matrix.path}},enable=true
name=docker.io/${{env.USER}}/${{matrix.path}},enable=true
tags: |
type=semver,enable=true,pattern={{major}}
type=semver,enable=true,pattern={{major}}.{{minor}}
type=semver,enable=true,pattern={{version}}
type=ref,enable=true,event=branch

- name: 🚀 Build and push container image
if: ${{ steps.file_change.outputs.container_folder != 'false' }}
id: build_and_push
uses: docker/[email protected]
with:
context: ./packages/${{matrix.path}}
push: ${{ github.event_name != 'pull_request' }}
tags: ${{steps.meta.outputs.tags}}
cache-from: type=local,src=/tmp/.buildx-cache
cache-to: type=local,dest=/tmp/.buildx-cache
build-args: |
BUILD_DATE=${{github.event.repository.updated_at}}
BUILD_REV=${{github.sha}}

# - name: 🏗 Sign the image with GitHub OIDC Token
# if: ${{ github.event_name != 'pull_request' && steps.file_change.outputs.container_folder != 'false' }}
# env:
# COSIGN_EXPERIMENTAL: 'true'
# run: echo "${{steps.meta.outputs.tags}}" | xargs -I {} cosign sign --yes {}@${{steps.build_and_push.outputs.digest}}
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,5 @@ build

# dotenv environment variables file
.env

!build.js
File renamed without changes.
64 changes: 64 additions & 0 deletions packages/api/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
FROM docker.io/library/node:20-alpine as builder

WORKDIR /app

RUN corepack enable

COPY . .
RUN if [ -f *.lock ]; then \
yarn install --immutable; \
else \
yarn install; \
fi;

ENV NODE_ENV production

RUN yarn build:ts

# Build target package
ARG packageSource='packages/api'
RUN set -ex;\
if [ -z "$packageSource" ]; then\
echo 'packageSource not defined'>&2;\
exit 1;\
fi;
RUN set -ex;\
cd "$packageSource"; pwd; ls -lahF;\
yarn build;

# ---

FROM docker.io/library/node:20-alpine as service

WORKDIR /app

CMD ["yarn", "serve"]

ENV NODE_ENV production
ENV NODE_OPTIONS --enable-source-maps
ENV HOST 0.0.0.0
ENV PORT 80
EXPOSE 80

# Copy builded files from last stage
ARG packageSource='packages/api'
COPY --from=builder ${packageSource}/package.json ./
COPY --from=builder ${packageSource}/dist ./dist

# RUN pwd; ls -lAhF;

ARG BUILD_REV
ARG BUILD_DATE
LABEL org.opencontainers.image.title="alwatr/storage-api" \
org.opencontainers.image.description="Alwatr Storage API, Elegant micro in-memory json-like storage nanoservice with disk backed, Fastest NoSQL Database." \
org.opencontainers.image.base.name="docker.io/library/node:20-alpine" \
org.opencontainers.image.version="4.0.0-rc.0" \
org.opencontainers.image.ref.name="20-alpine" \
org.opencontainers.image.licenses="MIT" \
org.opencontainers.image.created=${BUILD_DATE} \
org.opencontainers.image.revision=${BUILD_REV} \
org.opencontainers.image.vendor="Alwatr" \
org.opencontainers.image.source="https://github.com/Alwatr/storage" \
org.opencontainers.image.url="https://github.com/Alwatr/storage" \
org.opencontainers.image.documentation="https://github.com/Alwatr/storage" \
org.opencontainers.image.authors="S. Ali Mihandoost <[email protected]> (https://ali.mihandoost.com), S. Amir Mohammad Najafi <[email protected]> (https://njfamirm.ir/)"
2 changes: 1 addition & 1 deletion packages/server/README.md → packages/api/README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
# Alwatr Storage Server (Nanoservice)
# Alwatr Storage API

Elegant micro in-memory json-like storage nanoservice with disk backed, Fastest NoSQL Database.
64 changes: 64 additions & 0 deletions packages/api/build.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import {rm} from 'fs/promises';
import {createLogger} from '@alwatr/logger';
import {context, analyzeMetafile} from 'esbuild';

const logger = createLogger('@alwatr/storage-api-build', true);

const srcDir = 'src';
const outDir = 'dist';
const srcFilename = 'index';

async function build(cleanMode, watchMode, debugMode, prettyMode) {
logger.logMethodArgs?.('build', {cleanMode, watchMode, debugMode, prettyMode});

const esbuildContext = await context({
entryPoints: [`${srcDir}/${srcFilename}.ts`],
logLevel: 'info',
platform: 'node',
target: 'es2018',
format: 'esm',
conditions: debugMode ? ['development'] : undefined,
minify: !prettyMode,
treeShaking: true,
sourcemap: true,
sourcesContent: debugMode,
bundle: true,
splitting: false,
charset: 'utf8',
legalComments: 'none',
metafile: true,
outbase: srcDir,
outdir: outDir,
// entryNames: watchMode ? '[name]' : '[dir]/[name]'
});

if (cleanMode) {
logger.logOther?.('🧹 Cleaning...');
await rm(outDir, {recursive: true, force: true});
}

if (watchMode) {
logger.logOther?.('👀 Watching...');
esbuildContext.watch();
} else {
logger.logOther?.('🚀 Building...');
const buildInfo = await esbuildContext.rebuild();
await esbuildContext.dispose();

if (debugMode) {
for (const [outFile, outInfo] of Object.entries(buildInfo.metafile?.outputs ?? {})) {
const size = Math.round(outInfo.bytes / 1024);
logger.logOther?.(`📦 ${outFile} ${size}kb`);
}
}

logger.logOther?.('✅ Done.');
}
}

const cleanMode = process.argv.includes('--clean');
const watchMode = process.argv.includes('--watch');
const debugMode = process.argv.includes('--debug');
const prettyMode = process.argv.includes('--pretty');

build(cleanMode, watchMode, debugMode, prettyMode);
File renamed without changes.
33 changes: 20 additions & 13 deletions packages/server/package.json → packages/api/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@alwatr/storage-server",
"name": "@alwatr/storage-api",
"version": "4.0.0-rc.0",
"description": "Alwatr Storage Server, Elegant micro in-memory json-like storage nanoservice with disk backed, Fastest NoSQL Database.",
"description": "Alwatr Storage API, Elegant micro in-memory json-like storage nanoservice with disk backed, Fastest NoSQL Database.",
"type": "module",
"keywords": [
"database",
Expand All @@ -28,7 +28,7 @@
"repository": {
"type": "git",
"url": "https://github.com/Alwatr/storage",
"directory": "packages/server"
"directory": "packages/api"
},
"homepage": "https://github.com/Alwatr/storage#readme",
"bugs": {
Expand All @@ -38,19 +38,21 @@
"b": "yarn run build",
"c": "yarn run clean",
"cb": "run-s clean build",
"cw": "run-s clean watch",
"s": "yarn run start",
"w": "yarn run watch",
"l": "yarn lint",
"lint": "run-s 'lint:*'",
"lint:ts": "tsc --build",
"start": "NODE_OPTIONS=--enable-source-maps run-s clean build serve",
"build": "yarn run build:ts",
"build:ts": "tsc --build",
"build:es": "esbuild src/index.ts --platform=node --target=node19 --bundle --format=esm --minify --sourcemap --outdir=dist --out-extension:.js=.mjs",
"clean": "rm -rf dist build .tsbuildinfo",
"serve": "yarn node --enable-source-maps dist/index.mjs",
"serve:debug": "yarn node --inspect --enable-source-maps dist/index.mjs",
"build": "yarn run build:es",
"build:es": "yarn node ./build.js",
"clean": "rm -rf dist .tsbuildinfo",
"serve": "yarn node --enable-source-maps dist/index.js",
"serve:debug": "yarn node --inspect --enable-source-maps dist/index.js",
"watch": "run-s clean build && run-p watch:es watch:node",
"watch:node": "nodemon -w dist/ --enable-source-maps dist/index.mjs",
"watch:debug-node": "nodemon -w dist/ --inspect --enable-source-maps dist/index.mjs",
"watch:ts": "yarn run build:ts --watch --preserveWatchOutput",
"watch:node": "nodemon -w dist/ --enable-source-maps dist/index.js",
"watch:debug-node": "nodemon -w dist/ --inspect --enable-source-maps dist/index.js",
"watch:es": "yarn run build:es --watch"
},
"devDependencies": {
Expand All @@ -59,6 +61,11 @@
"@alwatr/storage-engine": "workspace:^",
"@alwatr/type": "^1.2.1",
"@alwatr/util": "^1.3.1",
"@types/node": "^20.10.0"
"@types/node": "^20.10.0",
"esbuild": "^0.19.7",
"nodemon": "^3.0.1",
"npm-run-all": "^4.1.5",
"tslib": "^2.6.2",
"typescript": "^5.3.2"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {resolve} from 'node:path';

import {createLogger} from '@alwatr/logger';

export const logger = createLogger('storage-server');
export const logger = createLogger('storage-api');

export const config = {
nanoServer: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@ import './route/patch.js';
import './route/storage.js';
import './route/touch.js';

logger.logOther?.('..:: Alwatr Storage Server ::..');
logger.logOther?.('..:: Alwatr Storage API ::..');
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@
"composite": true,
"tsBuildInfoFile": ".tsbuildinfo",
"rootDir": "src",
"outDir": "build"
// "noEmit": true
"noEmit": true
},

"include": ["src/**/*.ts"],
Expand Down
3 changes: 3 additions & 0 deletions packages/nginx/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
*
!etc/nginx/
!data/
Loading
Loading