diff --git a/.github/release.yaml b/.github/release.yaml new file mode 100644 index 0000000..0918ef3 --- /dev/null +++ b/.github/release.yaml @@ -0,0 +1,20 @@ +changelog: + exclude: + labels: + - exclude from release notes + categories: + - title: Maintenance + labels: + - maintenance + - title: New Features + labels: + - new feature + - title: Improvements + labels: + - improvement + - title: Bug Fixes + labels: + - bug + - title: Other + labels: + - "*" diff --git a/.github/workflows/publish-image.yaml b/.github/workflows/publish-image.yaml new file mode 100644 index 0000000..8683b8f --- /dev/null +++ b/.github/workflows/publish-image.yaml @@ -0,0 +1,62 @@ +on: + workflow_call: + inputs: + latest: + description: + Release as the latest version, tagging the images with the version number found in + package.json. + default: false + type: boolean + +jobs: + tags: + name: Compose version tags + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Parse semver number from package.json + run: | + PACKAGE_VERSION=$(cat package.json | jq '.version' | tr -d '"') + echo "MAJOR=$(echo $PACKAGE_VERSION | cut -d "." -f 1)" >> $GITHUB_ENV + echo "MINOR=$(echo $PACKAGE_VERSION | cut -d "." -f 2)" >> $GITHUB_ENV + echo "PATCH=$(echo $PACKAGE_VERSION | cut -d "." -f 3)" >> $GITHUB_ENV + - name: Compose Docker tags + run: | + echo "MAJOR_V=ghcr.io/funidata/kaiku:$MAJOR" >> $GITHUB_ENV + echo "MINOR_V=ghcr.io/funidata/kaiku:$MAJOR.$MINOR" >> $GITHUB_ENV + echo "FULL_V=ghcr.io/funidata/kaiku:$MAJOR.$MINOR.$PATCH" >> $GITHUB_ENV + - name: Compose tag list + run: echo "TAG_LIST=$MAJOR_V,$MINOR_V,$FULL_V,ghcr.io/funidata/kaiku:latest" >> $GITHUB_ENV + - name: Select correct tags + id: tags + run: + echo SELECTED_TAGS=$(if [ ${{ inputs.latest }} = true ]; then echo $TAG_LIST; else echo + "ghcr.io/funidata/kaiku:next"; fi) >> $GITHUB_OUTPUT + outputs: + tag-list: ${{ steps.tags.outputs.SELECTED_TAGS }} + + publish: + name: Publish image + needs: + - tags + runs-on: ubuntu-latest + permissions: + packages: write + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + - name: Login to GHCR + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - name: Build production image + uses: docker/build-push-action@v5 + with: + context: app + push: true + tags: ${{ needs.tags.outputs.tag-list }} diff --git a/.github/workflows/push-main.yaml b/.github/workflows/push-main.yaml index 6bf83ff..ef1af22 100644 --- a/.github/workflows/push-main.yaml +++ b/.github/workflows/push-main.yaml @@ -9,3 +9,9 @@ jobs: tests: name: Run tests uses: ./.github/workflows/run-tests.yaml + + release: + name: Publish image (next) + uses: ./.github/workflows/publish-image.yaml + needs: + - tests diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml new file mode 100644 index 0000000..f4ef4da --- /dev/null +++ b/.github/workflows/release.yaml @@ -0,0 +1,19 @@ +name: Release new version + +on: + release: + types: + - released + +jobs: + tests: + name: Run tests + uses: ./.github/workflows/run-tests.yaml + + release: + name: Publish image (latest) + uses: ./.github/workflows/publish-image.yaml + with: + latest: true + needs: + - tests diff --git a/app/.dockerignore b/app/.dockerignore new file mode 100644 index 0000000..3c3629e --- /dev/null +++ b/app/.dockerignore @@ -0,0 +1 @@ +node_modules diff --git a/app/Dockerfile b/app/Dockerfile new file mode 100644 index 0000000..6ca0294 --- /dev/null +++ b/app/Dockerfile @@ -0,0 +1,26 @@ +# Production image. +FROM node:20.17 AS build + +ENV NODE_ENV=production + +# Build backend. +WORKDIR /usr/src/app +COPY package.json package-lock.json ./ +RUN npm ci --include dev +COPY . . +RUN npm run build +RUN npm prune + +# Final build stage to pick only actually needed files into the image. +FROM node:20.17-alpine + +LABEL org.opencontainers.image.description="Kaiku backend image." + +USER node + +WORKDIR /app +COPY --from=build /usr/src/app/dist ./dist +COPY --from=build /usr/src/app/node_modules ./node_modules + +# Run database migrations before booting server. +CMD ["node", "dist/main.js"]