Compare commits

...

2 Commits

Author SHA1 Message Date
Alex Christoffer Rasmussen 147862e647 Fix opview with groups (#1814)
* create failing test

* fix: op evet used past state of the group
2025-10-08 21:19:57 +02:00
Alex Christoffer Rasmussen 12bc323e57 Fix build (#1813)
* fix resolver build

* fix docker build

* node version in docker via arg

* add step to setup auth for pnpm

* lint

---------

Co-authored-by: Joel Wetzell <jwetzell@yahoo.com>
2025-10-08 10:44:53 +02:00
11 changed files with 98 additions and 69 deletions
-1
View File
@@ -17,7 +17,6 @@
# Ignore build folders # Ignore build folders
node_modules node_modules
**/node_modules **/node_modules
**/dist
# Ignore default volumes created by running docker compose up # Ignore default volumes created by running docker compose up
ontime-db ontime-db
+9 -5
View File
@@ -13,13 +13,13 @@ jobs:
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Setup pnpm - name: Setup pnpm
uses: pnpm/action-setup@v4 uses: pnpm/action-setup@v4
- name: Get pnpm store directory - name: Get pnpm store directory
run: echo "PNPM_STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV run: echo "PNPM_STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
- name: Setup pnpm cache - name: Setup pnpm cache
uses: actions/cache@v4 uses: actions/cache@v4
with: with:
@@ -38,16 +38,20 @@ jobs:
- name: Copy server - name: Copy server
run: mkdir -p apps/cli/server && cp apps/server/dist/index.cjs apps/cli/server/index.cjs run: mkdir -p apps/cli/server && cp apps/server/dist/index.cjs apps/cli/server/index.cjs
- name: Copy client - name: Copy client
run: cp -R apps/client/build apps/cli/client run: cp -R apps/client/build apps/cli/client
- name: Copy external - name: Copy external
run: cp -R apps/server/src/external apps/cli/external run: cp -R apps/server/src/external apps/cli/external
- name: Setup pnpm auth config
run: pnpm config set '//registry.npmjs.org/:_authToken' "${NODE_AUTH_TOKEN}"
env:
NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}
- name: Publish to NPM - name: Publish to NPM
run: pnpm publish --access public --no-git-checks run: pnpm publish --access public --no-git-checks
env: env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
NPM_CONFIG_PROVENANCE: true NPM_CONFIG_PROVENANCE: true
working-directory: ./apps/cli working-directory: ./apps/cli
+49 -29
View File
@@ -6,43 +6,63 @@ on:
workflow_dispatch: workflow_dispatch:
jobs: jobs:
publish_docker: publish_docker:
runs-on: ubuntu-latest runs-on: ubuntu-latest
env: env:
CI: '' CI: ''
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Docker Login - name: Setup pnpm
uses: docker/login-action@v2.1.0 uses: pnpm/action-setup@v4
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Docker Setup Buildx - name: Get pnpm store directory
uses: docker/setup-buildx-action@v2.5.0 run: echo "PNPM_STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
- name: Build and push stable release - name: Setup pnpm cache
if: github.event.release.prerelease == false uses: actions/cache@v4
uses: docker/build-push-action@v4.0.0 with:
with: path: ${{ env.PNPM_STORE_PATH }}
context: . key: ${{ runner.os }}-pnpm-store-${{ hashFiles('pnpm-lock.yaml') }}
file: ./Dockerfile restore-keys: |
platforms: linux/amd64,linux/arm64,linux/arm/v7 ${{ runner.os }}-pnpm-store-
# Push is a shorthand for --output=type=registry
push: true
tags: ${{ secrets.DOCKERHUB_USERNAME }}/ontime:${{ github.event.release.tag_name }} , ${{ secrets.DOCKERHUB_USERNAME }}/ontime:latest
- name: Build and push pre-release - name: Install dependencies
if: github.event.release.prerelease == true run: pnpm install --frozen-lockfile
uses: docker/build-push-action@v4.0.0
with:
context: .
file: ./Dockerfile
platforms: linux/amd64,linux/arm64,linux/arm/v7
# Push is a shorthand for --output=type=registry
push: true
tags: ${{ secrets.DOCKERHUB_USERNAME }}/ontime:${{ github.event.release.tag_name }} , ${{ secrets.DOCKERHUB_USERNAME }}/ontime:nightly
- name: Build project packages
env:
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
run: pnpm build:docker
- name: Docker Login
uses: docker/login-action@v2.1.0
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Docker Setup Buildx
uses: docker/setup-buildx-action@v2.5.0
- name: Build and push stable release
if: github.event.release.prerelease == false
uses: docker/build-push-action@v4.0.0
with:
context: .
file: ./Dockerfile
platforms: linux/amd64,linux/arm64,linux/arm/v7
# Push is a shorthand for --output=type=registry
push: true
tags: ${{ secrets.DOCKERHUB_USERNAME }}/ontime:${{ github.event.release.tag_name }} , ${{ secrets.DOCKERHUB_USERNAME }}/ontime:latest
- name: Build and push pre-release
if: github.event.release.prerelease == true
uses: docker/build-push-action@v4.0.0
with:
context: .
file: ./Dockerfile
platforms: linux/amd64,linux/arm64,linux/arm/v7
# Push is a shorthand for --output=type=registry
push: true
tags: ${{ secrets.DOCKERHUB_USERNAME }}/ontime:${{ github.event.release.tag_name }} , ${{ secrets.DOCKERHUB_USERNAME }}/ontime:nightly
+4 -4
View File
@@ -2,7 +2,7 @@ name: Ontime build
on: on:
push: push:
tags: [ "*" ] tags: ['*']
workflow_dispatch: workflow_dispatch:
jobs: jobs:
@@ -11,13 +11,13 @@ jobs:
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Setup pnpm - name: Setup pnpm
uses: pnpm/action-setup@v4 uses: pnpm/action-setup@v4
- name: Get pnpm store directory - name: Get pnpm store directory
run: echo "PNPM_STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV run: echo "PNPM_STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
- name: Setup pnpm cache - name: Setup pnpm cache
uses: actions/cache@v4 uses: actions/cache@v4
with: with:
@@ -35,7 +35,7 @@ jobs:
run: pnpm build run: pnpm build
- name: Electron - Build app - name: Electron - Build app
env: env:
APPLE_ID: ${{ secrets.APPLEID }} APPLE_ID: ${{ secrets.APPLEID }}
APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLEIDPASS }} APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLEIDPASS }}
APPLE_TEAM_ID: ${{ secrets.TEAMID }} APPLE_TEAM_ID: ${{ secrets.TEAMID }}
+7 -3
View File
@@ -13,13 +13,13 @@ jobs:
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Setup pnpm - name: Setup pnpm
uses: pnpm/action-setup@v4 uses: pnpm/action-setup@v4
- name: Get pnpm store directory - name: Get pnpm store directory
run: echo "PNPM_STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV run: echo "PNPM_STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
- name: Setup pnpm cache - name: Setup pnpm cache
uses: actions/cache@v4 uses: actions/cache@v4
with: with:
@@ -34,9 +34,13 @@ jobs:
- name: Build project packages - name: Build project packages
run: pnpm build:resolver run: pnpm build:resolver
- name: Setup pnpm auth config
run: pnpm config set '//registry.npmjs.org/:_authToken' "${NODE_AUTH_TOKEN}"
env:
NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}
- name: Publish to NPM - name: Publish to NPM
run: pnpm publish --access public --no-git-checks run: pnpm publish --access public --no-git-checks
env: env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
NPM_CONFIG_PROVENANCE: true NPM_CONFIG_PROVENANCE: true
working-directory: ./apps/resolver working-directory: ./apps/resolver
+5 -5
View File
@@ -20,7 +20,7 @@ jobs:
- name: Get pnpm store directory - name: Get pnpm store directory
run: echo "PNPM_STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV run: echo "PNPM_STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
- name: Setup pnpm cache - name: Setup pnpm cache
uses: actions/cache@v4 uses: actions/cache@v4
with: with:
@@ -32,10 +32,10 @@ jobs:
- name: Install dependencies - name: Install dependencies
run: pnpm install --frozen-lockfile run: pnpm install --frozen-lockfile
# Run code quality # Run code quality
- name: Run linter - name: Run linter
run: pnpm lint run: pnpm lint
- name: Run TypeScript checks - name: Run TypeScript checks
run: pnpm typecheck run: pnpm typecheck
@@ -56,7 +56,7 @@ jobs:
- name: Get pnpm store directory - name: Get pnpm store directory
run: echo "PNPM_STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV run: echo "PNPM_STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
- name: Setup pnpm cache - name: Setup pnpm cache
uses: actions/cache@v4 uses: actions/cache@v4
with: with:
@@ -74,7 +74,7 @@ jobs:
uses: actions/cache@v4 uses: actions/cache@v4
with: with:
path: | path: |
~/.cache/ms-playwright ~/.cache/ms-playwright
key: ${{ runner.os }}-playwright-${{ env.PLAYWRIGHT_VERSION }} key: ${{ runner.os }}-playwright-${{ env.PLAYWRIGHT_VERSION }}
restore-keys: | restore-keys: |
${{ runner.os }}-playwright- ${{ runner.os }}-playwright-
+2 -1
View File
@@ -5,8 +5,9 @@ node_modules
playwright-report playwright-report
pnpm-lock.yaml
**/*.toml **/*.toml
**/*.yml
**/*.json **/*.json
!tsconfig.common.json !tsconfig.common.json
!turbo.json !turbo.json
+9 -15
View File
@@ -1,13 +1,5 @@
FROM node:22-bullseye AS builder ARG NODE_VERSION=22.15.1
ENV PNPM_HOME="/pnpm" FROM node:${NODE_VERSION}-alpine
ENV PATH="$PNPM_HOME:$PATH"
RUN npm install -g pnpm@10.11.0
COPY . /app
WORKDIR /app
RUN pnpm --filter=ontime-ui --filter=ontime-server --filter=ontime-utils --filter=ontime-types install --config.dedupe-peer-dependents=false --frozen-lockfile
RUN pnpm run build:docker
FROM node:22-alpine
# Set environment variables # Set environment variables
# Environment Variable to signal that we are running production # Environment Variable to signal that we are running production
@@ -15,16 +7,17 @@ ENV NODE_ENV=docker
# Ontime Data path # Ontime Data path
ENV ONTIME_DATA=/data/ ENV ONTIME_DATA=/data/
RUN mkdir /app
WORKDIR /app/ WORKDIR /app/
# Prepare UI # Prepare UI
COPY --from=builder /app/apps/client/build ./client/ COPY apps/client/build/ ./client/
# Prepare Backend # Prepare Backend
COPY --from=builder /app/apps/server/dist/ ./server/ COPY apps/server/dist/ ./server/
COPY --from=builder /app/apps/server/src/external/ ./external/ COPY apps/server/src/external/ ./external/
COPY --from=builder /app/apps/server/src/user/ ./user/ COPY apps/server/src/user/ ./user/
COPY --from=builder /app/apps/server/src/html/ ./html/ COPY apps/server/src/html/ ./html/
# Export default ports # Export default ports
EXPOSE 4001/tcp 8888/udp 9999/udp EXPOSE 4001/tcp 8888/udp 9999/udp
@@ -32,5 +25,6 @@ EXPOSE 4001/tcp 8888/udp 9999/udp
CMD ["node", "server/docker.cjs"] CMD ["node", "server/docker.cjs"]
# Build and run commands # Build and run commands
# pnpm build:docker
# docker buildx build . -t getontime/ontime # docker buildx build . -t getontime/ontime
# docker run -p 4001:4001 -p 8888:8888/udp -p 9999:9999/udp -v ./ontime-db:/data/ getontime/ontime # docker run -p 4001:4001 -p 8888:8888/udp -p 9999:9999/udp -v ./ontime-db:/data/ getontime/ontime
@@ -177,7 +177,7 @@ export default function Operator() {
return null; return null;
} }
const { isPast, isLoaded, isLinkedToLoaded, totalGap } = rundownMetadata[entryId]; const { isPast, isLoaded, isLinkedToLoaded, totalGap } = rundownMetadata[nestedEntryId];
// hide past events (if setting) and skipped events // hide past events (if setting) and skipped events
if ((hidePast && isPast) || nestedEntry.skip) { if ((hidePast && isPast) || nestedEntry.skip) {
+11 -5
View File
@@ -2,11 +2,16 @@ import { test, expect } from '@playwright/test';
test('smoke test operator', async ({ page }) => { test('smoke test operator', async ({ page }) => {
// make some boilerplate // make some boilerplate
await page.goto('http://localhost:4001/editor'); await page.goto('/editor');
await page.getByRole('button', { name: 'Edit' }).click(); await page.getByRole('button', { name: 'Edit' }).click();
await page.getByRole('button', { name: 'Clear all' }).click(); await page.getByRole('button', { name: 'Clear all' }).click();
await page.getByRole('button', { name: 'Delete all' }).click(); await page.getByRole('button', { name: 'Delete all' }).click();
await page.getByRole('button', { name: 'Create Event' }).click(); await page.getByRole('button', { name: 'Create Group' }).click();
await page.getByTestId('rundown-group').getByTestId('entry__title').click();
await page.getByTestId('rundown-group').getByTestId('entry__title').fill('group 1');
await page.getByTestId('rundown-group').getByTestId('entry__title').press('Enter');
await page.getByRole('button', { name: 'Event', exact: true }).nth(1).click();
await page.getByTestId('time-input-timeStart').fill('1m'); await page.getByTestId('time-input-timeStart').fill('1m');
await page.getByTestId('time-input-timeStart').press('Enter'); await page.getByTestId('time-input-timeStart').press('Enter');
@@ -24,10 +29,9 @@ test('smoke test operator', async ({ page }) => {
await page.getByTestId('entry-3').getByTestId('time-input-duration').fill('1m'); await page.getByTestId('entry-3').getByTestId('time-input-duration').fill('1m');
await page.getByTestId('entry-3').getByTestId('time-input-duration').press('Enter'); await page.getByTestId('entry-3').getByTestId('time-input-duration').press('Enter');
await page.getByRole('button', { name: 'Group' }).nth(1).click();
await page.getByRole('button', { name: 'Edit' }).click(); await page.getByRole('button', { name: 'Edit' }).click();
await page.getByTestId('entry-1').click(); await page.getByTestId('entry-1').click();
await page.getByTestId('editor-container').getByLabel('Cue').fill('--1');
await page.getByRole('button', { name: 'Event', exact: true }).nth(1).click(); await page.getByRole('button', { name: 'Event', exact: true }).nth(1).click();
await page.getByTestId('entry-1').getByTestId('entry__title').click(); await page.getByTestId('entry-1').getByTestId('entry__title').click();
@@ -51,9 +55,11 @@ test('smoke test operator', async ({ page }) => {
// start an event // start an event
await page.getByTestId('panel-timer-control').getByRole('button', { name: 'Start' }).click(); await page.getByTestId('panel-timer-control').getByRole('button', { name: 'Start' }).click();
await page.goto('http://localhost:4001/op'); await page.goto('/op');
await expect(page.getByText('group 1')).toBeInViewport();
await expect(page.getByText('title 1')).toBeInViewport(); await expect(page.getByText('title 1')).toBeInViewport();
await expect(page.getByTestId('--1')).toHaveCSS('opacity', '1'); // BUG: ensure event doesn't inherit the past state of the group
await expect(page.getByText('title 2')).toBeInViewport(); await expect(page.getByText('title 2')).toBeInViewport();
await expect(page.getByText('title 3')).toBeInViewport(); await expect(page.getByText('title 3')).toBeInViewport();
+1
View File
@@ -27,6 +27,7 @@
"typecheck": "turbo run typecheck", "typecheck": "turbo run typecheck",
"build": "turbo run build", "build": "turbo run build",
"build:docker": "cross-env NODE_ENV=docker turbo run build --filter=ontime-server --filter=ontime-ui", "build:docker": "cross-env NODE_ENV=docker turbo run build --filter=ontime-server --filter=ontime-ui",
"build:resolver": "cross-env turbo run build --filter=@getontime/resolver",
"dist-win": "turbo run dist-win", "dist-win": "turbo run dist-win",
"dist-mac": "turbo run dist-mac", "dist-mac": "turbo run dist-mac",
"dist-linux": "turbo run dist-linux", "dist-linux": "turbo run dist-linux",