Skip to content

Commit

Permalink
feat: build docker image (#7)
Browse files Browse the repository at this point in the history
  • Loading branch information
Julusian authored Feb 16, 2024
1 parent 97db64c commit 5261403
Show file tree
Hide file tree
Showing 19 changed files with 223 additions and 77 deletions.
2 changes: 2 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
node_modules
packages/*/*/dist
127 changes: 125 additions & 2 deletions .github/workflows/node.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ jobs:
package-name:
- "@sofie-prompter-editor/shared-model"
- "@sofie-prompter-editor/shared-lib"
- "@sofie-prompter-editor/apps-app"
- "@sofie-prompter-editor/apps-backend"
- "@sofie-prompter-editor/apps-client"

Expand Down Expand Up @@ -59,7 +58,6 @@ jobs:
package-name:
- "@sofie-prompter-editor/shared-model"
- "@sofie-prompter-editor/shared-lib"
- "@sofie-prompter-editor/apps-app"
- "@sofie-prompter-editor/apps-backend"
- "@sofie-prompter-editor/apps-client"

Expand All @@ -84,3 +82,128 @@ jobs:
yarn lerna run --scope ${{ matrix.package-name }} --stream test
env:
CI: true

build-docker-image:
name: Build docker image
runs-on: ubuntu-latest
timeout-minutes: 30

steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- name: Determine if images should be published to DockerHub
id: dockerhub
run: |
# HACK: Never publish to dockerhub for now
# check if a release branch, or main, or a tag
# if [[ "${{ github.ref }}" =~ ^refs/heads/release([0-9]+)$ || "${{ github.ref }}" == "refs/heads/main" || "${{ github.ref }}" == "refs/tags/*" ]]
# then
# DOCKERHUB_PUBLISH="1"
# else
DOCKERHUB_PUBLISH="0"
# fi
# debug output
echo "dockerhub-publish $DOCKERHUB_PUBLISH"
echo "dockerhub-publish=$DOCKERHUB_PUBLISH" >> $GITHUB_OUTPUT
- name: Check if push to GHCR is enabled
id: check-ghcr
env:
GHCR_ENABLED: ${{ vars.GHCR_ENABLED }}
run: |
echo "Enable push to GHCR: ${{ env.GHCR_ENABLED != '' }}"
echo "enable=${{ env.GHCR_ENABLED != '' }}" >> $GITHUB_OUTPUT
- name: Check if there is access to repo secrets (needed for build and push)
if: steps.dockerhub.outputs.dockerhub-publish == '1' || steps.check-ghcr.outputs.enable == 'true'
id: check-build-and-push
env:
SECRET_ACCESS: ${{ secrets.GITHUB_TOKEN }}
run: |
echo "Enable build and push: ${{ env.SECRET_ACCESS != '' }}"
echo "enable=${{ env.SECRET_ACCESS != '' }}" >> $GITHUB_OUTPUT
- name: Get the Docker tag for GHCR
id: ghcr-tag
if: steps.check-ghcr.outputs.enable == 'true'
uses: docker/metadata-action@v5
with:
images: |
ghcr.io/${{ github.repository }}
tags: |
type=schedule
type=ref,event=branch
type=ref,event=tag
type=raw,value=latest,enable={{is_default_branch}}
- name: Get the Docker tag for DockerHub
id: dockerhub-tag
if: steps.check-build-and-push.outputs.enable == 'true'
uses: docker/metadata-action@v5
with:
images: |
${{ secrets.DOCKERHUB_IMAGE_PREFIX }}
tags: |
type=schedule
type=ref,event=branch
type=ref,event=tag
type=raw,value=latest,enable={{is_default_branch}}
- name: Use Node.js
uses: actions/setup-node@v4
if: steps.check-build-and-push.outputs.enable == 'true'
with:
node-version-file: ".node-version"
- name: Set up Docker Buildx
if: steps.check-build-and-push.outputs.enable == 'true'
uses: docker/setup-buildx-action@v3
- name: Login to DockerHub
if: steps.check-build-and-push.outputs.enable == 'true' && steps.dockerhub.outputs.dockerhub-publish == '1'
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Login to GitHub Container Registry
if: steps.check-build-and-push.outputs.enable == 'true' && steps.check-ghcr.outputs.enable == 'true'
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push to GHCR
if: steps.check-build-and-push.outputs.enable == 'true' && steps.check-ghcr.outputs.enable == 'true' && steps.ghcr-tag.outputs.tags != 0
uses: docker/build-push-action@v5
with:
push: true
provenance: false
labels: ${{ steps.ghcr-tag.outputs.labels }}
tags: "${{ steps.ghcr-tag.outputs.tags }}"
- name: Build and push to DockerHub
if: steps.check-build-and-push.outputs.enable == 'true' && steps.dockerhub.outputs.dockerhub-publish == '1'
uses: docker/build-push-action@v5
with:
push: true
provenance: false
labels: ${{ steps.dockerhub-tag.outputs.labels }}
tags: "${{ steps.dockerhub-tag.outputs.tags }}"
- name: Get image for Trivy scanning
id: trivy-image
if: steps.check-build-and-push.outputs.enable == 'true' && steps.check-ghcr.outputs.enable == 'true' && steps.ghcr-tag.outputs.tags != 0
run: |
image=$(echo ${{ steps.ghcr-tag.outputs.tags }} | head -n 1)
echo "image=$image" >> $GITHUB_OUTPUT
- name: Trivy scanning
if: steps.check-build-and-push.outputs.enable == 'true' && steps.check-ghcr.outputs.enable == 'true' && steps.ghcr-tag.outputs.tags != 0
uses: aquasecurity/[email protected]
with:
image-ref: "${{ steps.trivy-image.outputs.image }}"
format: "table"
output: trivy-scan-result.txt
ignore-unfixed: true
severity: "CRITICAL,HIGH"
- name: Post all Trivy scan results to Github Summary as a table
if: steps.check-build-and-push.outputs.enable == 'true' && steps.check-ghcr.outputs.enable == 'true' && steps.ghcr-tag.outputs.tags != 0
env:
CODE_BLOCK: "```"
run: |
echo "# Trivy scan results" >> $GITHUB_STEP_SUMMARY
echo $CODE_BLOCK >> $GITHUB_STEP_SUMMARY
cat trivy-scan-result.txt >> $GITHUB_STEP_SUMMARY
echo $CODE_BLOCK >> $GITHUB_STEP_SUMMARY
19 changes: 19 additions & 0 deletions .github/workflows/prune-container-images.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
name: "Prune container images"

on:
workflow_dispatch:
schedule:
- cron: '24 11 * * *'

jobs:
prune-container-images:
uses: nrkno/sofie-github-workflows/.github/workflows/prune-container-images.yml@main
with:
dry-run: false
prune-untagged: true
package-name: sofie-prompter-editor
tags-to-keep-regex: |
^release(\d+)
^r(\d+)
secrets:
prune-token: ${{ secrets.GHCR_PRUNE_TOKEN }}
1 change: 1 addition & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package.json
27 changes: 27 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# BUILD IMAGE
FROM node:20
WORKDIR /opt/prompter

COPY . .

RUN corepack enable
RUN yarn install --immutable
RUN yarn build
RUN yarn workspaces focus --production @sofie-prompter-editor/apps-backend # purge dev-dependencies

# perform some cleanup
RUN rm -R packages/apps/client/node_modules || true

# DEPLOY IMAGE
FROM node:20-alpine
RUN apk add --no-cache tzdata

COPY --from=0 /opt/prompter/package.json /opt/prompter/package.json
COPY --from=0 /opt/prompter/node_modules /opt/prompter/node_modules
COPY --from=0 /opt/prompter/packages/apps /opt/prompter/packages/apps
COPY --from=0 /opt/prompter/packages/shared /opt/prompter/packages/shared
COPY docker-entrypoint.sh /

WORKDIR /opt/prompter/packages/apps/backend
EXPOSE 5600/TCP
ENTRYPOINT ["/docker-entrypoint.sh"]
14 changes: 14 additions & 0 deletions docker-entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/usr/bin/env sh
set -e

# load environment variables from file
if [ ! -z "$PROMPTER_ENV_FILE" ]
then
echo "Loading environment variables from $PROMPTER_ENV_FILE"
set -o allexport
source "$PROMPTER_ENV_FILE"
set +o allexport
fi

# launch the app
node dist/index.js $@
1 change: 0 additions & 1 deletion packages/apps/app/.gitignore

This file was deleted.

7 changes: 0 additions & 7 deletions packages/apps/app/jest.config.js

This file was deleted.

31 changes: 0 additions & 31 deletions packages/apps/app/package.json

This file was deleted.

1 change: 0 additions & 1 deletion packages/apps/app/src/index.ts

This file was deleted.

6 changes: 0 additions & 6 deletions packages/apps/app/tsconfig.json

This file was deleted.

19 changes: 16 additions & 3 deletions packages/apps/backend/src/api-server/ApiServer.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { RealTimeConnection, feathers } from '@feathersjs/feathers'
import { koa, rest, bodyParser, errorHandler, serveStatic, cors } from '@feathersjs/koa'
import { koa, rest, bodyParser, errorHandler, serveStatic, cors, FeathersKoaContext } from '@feathersjs/koa'
import socketio from '@feathersjs/socketio'
import { EventEmitter } from 'eventemitter3'
import { ServiceTypes, SystemStatus } from '@sofie-prompter-editor/shared-model'
Expand All @@ -16,6 +16,7 @@ import { ViewPortFeathersService, ViewPortService } from './services/ViewPortSer
import { OutputSettingsFeathersService, OutputSettingsService } from './services/OutputSettingsService.js'
import { ControllerFeathersService, ControllerService } from './services/ControllerService.js'
import { SystemStatusFeathersService, SystemStatusService } from './services/SystemStatusService.js'
import { fileURLToPath } from 'node:url'

export type ApiServerEvents = {
connection: []
Expand Down Expand Up @@ -45,15 +46,27 @@ export class ApiServer extends EventEmitter<ApiServerEvents> {
super()
this.log = log.category('ApiServer')

this.app.use(serveStatic('src'))
const serveStaticMiddleware = serveStatic(fileURLToPath(new URL('../../../client/dist', import.meta.url)))
this.app.use(serveStaticMiddleware)

this.app.use(
cors({
origin: '*', // TODO: cors
})
)

this.app.use(errorHandler())
const errorHandlerMiddleware = errorHandler()
this.app.use((ctx: FeathersKoaContext, next) => {
if (ctx.path.startsWith('/api/') || ctx.path === '/api') {
return errorHandlerMiddleware(ctx, next)
} else if (ctx.status === 404) {
// Force serve the index as this is a SPA
ctx.path = '/index.html'
return serveStaticMiddleware(ctx, next)
} else {
next()
}
})
this.app.use(bodyParser())
this.app.configure(rest())
this.app.configure(socketio({ cors: { origin: '*' } })) // TODO: cors
Expand Down
3 changes: 0 additions & 3 deletions packages/apps/backend/src/http-server/index.ts

This file was deleted.

5 changes: 2 additions & 3 deletions packages/apps/client/src/api/ApiConnection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import {
ServiceTypes,
Services,
} from '@sofie-prompter-editor/shared-model'
import { DEFAULT_DEV_API_HOST, DEFAULT_DEV_API_PORT } from '@sofie-prompter-editor/shared-lib'
import { AddTypeToProperties, FeathersTypedService } from './lib.ts'

interface APIConnectionEvents {
Expand All @@ -40,10 +39,10 @@ export class APIConnection extends EventEmitter<APIConnectionEvents> {

private app: Application<AddTypeToProperties<ServiceTypes, SocketService>, unknown>

constructor(public readonly host = DEFAULT_DEV_API_HOST, public readonly port = DEFAULT_DEV_API_PORT) {
constructor() {
super()

const socket = io(`${host}:${port}`)
const socket = io()
socket.on('connect', () => {
this.connected = true
this.emit('connected')
Expand Down
4 changes: 2 additions & 2 deletions packages/apps/client/src/stores/RootAppStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,8 @@ export const RootAppStore = new RootAppStoreClass()

export interface APIConnection extends EventEmitter {
readonly connected: boolean
readonly host: string
readonly port: number
// readonly host: string
// readonly port: number

readonly systemStatus: FeathersTypedService<SystemStatusServiceDefinition.Service>
readonly controller: FeathersTypedService<ControllerServiceDefinition.Service>
Expand Down
6 changes: 6 additions & 0 deletions packages/apps/client/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ export default defineConfig({
src: '/src',
},
},
server: {
proxy: {
'/api': 'http://localhost:5600',
'/socket.io': 'http://localhost:5600',
},
},
optimizeDeps: {
include: ['packages/shared/*/dist/*'],
},
Expand Down
1 change: 0 additions & 1 deletion packages/shared/lib/src/constants.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
export const DEFAULT_DEV_API_PORT = 5600
export const DEFAULT_DEV_API_HOST = '127.0.0.1'
18 changes: 9 additions & 9 deletions packages/shared/model/src/client-server-api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,18 +27,18 @@ export {
}

export enum Services {
Example = 'example',
Example = 'api/example',

SystemStatus = 'systemStatus',
SystemStatus = 'api/systemStatus',

Playlist = 'playlist',
Rundown = 'rundown',
Segment = 'segment',
Part = 'part',
Playlist = 'api/playlist',
Rundown = 'api/rundown',
Segment = 'api/segment',
Part = 'api/part',

Controller = 'controller',
OutputSettings = 'outputSettings',
ViewPort = 'viewPort',
Controller = 'api/controller',
OutputSettings = 'api/outputSettings',
ViewPort = 'api/viewPort',
}
export type ServiceTypes = {
[Services.Example]: ExampleServiceDefinition.Service
Expand Down
Loading

0 comments on commit 5261403

Please sign in to comment.