name: Node CI on: push: branches: - "**" tags: - "v**" pull_request: workflow_dispatch: permissions: contents: read jobs: lint-core: name: Typecheck and Lint Core runs-on: ubuntu-latest timeout-minutes: 15 steps: - uses: actions/checkout@v6 with: persist-credentials: false - name: Use Node.js uses: actions/setup-node@v6 with: node-version-file: ".node-version" - uses: ./.github/actions/setup-meteor - name: restore node_modules uses: actions/cache@v5 with: path: | node_modules meteor/node_modules packages/node_modules key: ${{ runner.os }}-${{ hashFiles('yarn.lock', 'meteor/yarn.lock', 'meteor/.meteor/release', 'packages/yarn.lock') }} - name: Prepare Environment run: | corepack enable yarn config set cacheFolder /home/runner/lint-core-cache yarn # setup zodern:types. No linters are setup, so this simply installs the packages yarn meteor lint yarn build:packages env: CI: true - name: Run typecheck and linter run: | cd meteor yarn ci:lint env: CI: true test-core: name: Test Core runs-on: ubuntu-latest timeout-minutes: 30 steps: - uses: actions/checkout@v6 with: persist-credentials: false - name: Use Node.js uses: actions/setup-node@v6 with: node-version-file: ".node-version" - uses: ./.github/actions/setup-meteor - name: restore node_modules uses: actions/cache@v5 with: path: | node_modules meteor/node_modules packages/node_modules key: ${{ runner.os }}-${{ hashFiles('yarn.lock', 'meteor/yarn.lock', 'meteor/.meteor/release', 'packages/yarn.lock') }} - name: Prepare Environment run: | corepack enable yarn config set cacheFolder /home/runner/test-core-cache yarn # setup zodern:types. No linters are setup, so this simply installs the packages yarn meteor lint yarn build:packages env: CI: true - name: Run Tests run: | cd meteor NODE_OPTIONS="--max-old-space-size=6144" yarn unitci --force-exit env: CI: true - name: Send coverage if: ((github.event_name == 'pull_request') && (!startsWith(github.head_ref, 'release'))) || ((github.event_name == 'push') && (!startsWith(github.ref_name, 'release'))) uses: codecov/codecov-action@v6 env: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} build-core: # TODO - should this be dependant on tests or something passing if we are on a tag? name: Build Core and publish docker image runs-on: ubuntu-latest timeout-minutes: 30 permissions: contents: read packages: write steps: - uses: actions/checkout@v6 with: persist-credentials: false - name: Use Node.js uses: actions/setup-node@v6 with: node-version-file: ".node-version" - uses: ./.github/actions/setup-meteor - name: restore node_modules uses: actions/cache@v5 with: path: | node_modules meteor/node_modules packages/node_modules key: ${{ runner.os }}-${{ hashFiles('yarn.lock', 'meteor/yarn.lock', 'meteor/.meteor/release', 'packages/yarn.lock') }} - name: Prepare Environment run: | corepack enable yarn install # setup zodern:types. No linters are setup, so this simply installs the packages yarn meteor lint - name: Build libs run: | yarn build:packages - name: Build webui run: | cd packages/webui yarn build - name: Persist Built Version information run: | cd meteor yarn inject-git-hash - name: Prepare webui for meteor build run: | rm -Rf meteor/public cp -R packages/webui/dist meteor/public - name: Meteor Build run: | cd meteor NODE_OPTIONS="--max-old-space-size=4096" METEOR_DEBUG_BUILD=1 meteor build --allow-superuser --directory . mv bundle/programs/web.browser/assets/ bundle/programs/web.browser/app/assets/ || true - name: Meteor Bundle NPM Build run: | cd meteor/bundle/programs/server meteor npm install - name: Set up Docker Buildx uses: docker/setup-buildx-action@v4 # Check how the image should be built and pushed - name: Determine if images should be published to DockerHub id: dockerhub run: | # 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: ${{ secrets.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.DOCKERHUB_IMAGE_PREFIX }} run: | echo "Enable build and push: ${{ env.SECRET_ACCESS != '' }}" echo "enable=${{ env.SECRET_ACCESS != '' }}" >> $GITHUB_OUTPUT # No-push build if no destination - name: Build without push if: steps.check-build-and-push.outputs.enable != 'true' uses: docker/build-push-action@v7 with: context: . file: ./meteor/Dockerfile.circle push: false provenance: false # GHCR build - name: Get the Docker tag for GHCR id: ghcr-tag if: steps.check-build-and-push.outputs.enable == 'true' uses: docker/metadata-action@v6 with: images: | ghcr.io/${{ github.repository }}-server-core tags: | type=schedule type=ref,event=branch type=ref,event=tag type=raw,value=latest,enable={{is_default_branch}} - 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@v4 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@v7 with: context: . file: ./meteor/Dockerfile.circle push: true provenance: false labels: ${{ steps.ghcr-tag.outputs.labels }} tags: "${{ steps.ghcr-tag.outputs.tags }}" github-token: ${{ github.token }} # Dockerhub push - name: Get the Docker tag for DockerHub id: dockerhub-tag if: steps.check-build-and-push.outputs.enable == 'true' uses: docker/metadata-action@v6 with: images: | ${{ secrets.DOCKERHUB_IMAGE_PREFIX }}server-core tags: | type=schedule type=ref,event=branch type=ref,event=tag type=raw,value=latest,enable={{is_default_branch}} - name: Login to DockerHub if: steps.check-build-and-push.outputs.enable == 'true' && steps.dockerhub.outputs.dockerhub-publish == '1' uses: docker/login-action@v4 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - 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@v7 with: context: . file: ./meteor/Dockerfile.circle push: true provenance: false labels: ${{ steps.dockerhub-tag.outputs.labels }} tags: ${{ steps.dockerhub-tag.outputs.tags }} build-gateways: # TODO - should this be dependant on tests or something passing if we are on a tag? name: Build gateways runs-on: ubuntu-latest timeout-minutes: 30 strategy: fail-fast: false matrix: gateway-name: [playout-gateway, mos-gateway, "live-status-gateway"] permissions: contents: read packages: write steps: - uses: actions/checkout@v6 with: persist-credentials: false - name: Use Node.js uses: actions/setup-node@v6 with: node-version-file: ".node-version" - name: restore node_modules uses: actions/cache@v5 with: path: | packages/node_modules key: ${{ runner.os }}-${{ hashFiles('packages/yarn.lock') }} - name: Build run: | corepack enable cd packages yarn install yarn build:single ${{ matrix.gateway-name }}/tsconfig.build.json yarn run pinst --disable yarn workspaces focus ${{ matrix.gateway-name }} --production - name: Set up Docker Buildx uses: docker/setup-buildx-action@v4 # Check how the image should be built and pushed - name: Determine if images should be published to DockerHub id: dockerhub run: | # 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: ${{ secrets.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.DOCKERHUB_IMAGE_PREFIX }} run: | echo "Enable build and push: ${{ env.SECRET_ACCESS != '' }}" echo "enable=${{ env.SECRET_ACCESS != '' }}" >> $GITHUB_OUTPUT # No-push build if no destination - name: Build without push if: steps.check-build-and-push.outputs.enable != 'true' uses: docker/build-push-action@v7 with: context: ./packages file: ./packages/${{ matrix.gateway-name }}/Dockerfile.circle push: false provenance: false # GHCR build - name: Get the Docker tag for GHCR id: ghcr-tag if: steps.check-build-and-push.outputs.enable == 'true' uses: docker/metadata-action@v6 with: images: | ghcr.io/${{ github.repository }}-${{ matrix.gateway-name }} tags: | type=schedule type=ref,event=branch type=ref,event=tag type=raw,value=latest,enable={{is_default_branch}} - 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@v4 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@v7 with: context: ./packages file: ./packages/${{ matrix.gateway-name }}/Dockerfile.circle push: true provenance: false labels: ${{ steps.ghcr-tag.outputs.labels }} tags: "${{ steps.ghcr-tag.outputs.tags }}" # Dockerhub push - name: Get the Docker tag for DockerHub id: dockerhub-tag if: steps.check-build-and-push.outputs.enable == 'true' uses: docker/metadata-action@v6 with: images: | ${{ secrets.DOCKERHUB_IMAGE_PREFIX }}${{ matrix.gateway-name }} tags: | type=schedule type=ref,event=branch type=ref,event=tag type=raw,value=latest,enable={{is_default_branch}} - name: Login to DockerHub if: steps.check-build-and-push.outputs.enable == 'true' && steps.dockerhub.outputs.dockerhub-publish == '1' uses: docker/login-action@v4 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - 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@v7 with: context: ./packages file: ./packages/${{ matrix.gateway-name }}/Dockerfile.circle push: true provenance: false labels: ${{ steps.dockerhub-tag.outputs.labels }} tags: "${{ steps.dockerhub-tag.outputs.tags }}" lint-packages: name: Lint Packages runs-on: ubuntu-latest timeout-minutes: 15 steps: - uses: actions/checkout@v6 with: persist-credentials: false - name: Use Node.js uses: actions/setup-node@v6 with: node-version-file: ".node-version" - uses: ./.github/actions/setup-meteor - name: restore node_modules uses: actions/cache@v5 with: path: | node_modules meteor/node_modules packages/node_modules key: ${{ runner.os }}-${{ hashFiles('yarn.lock', 'meteor/yarn.lock', 'meteor/.meteor/release', 'packages/yarn.lock') }} - name: Prepare Environment run: | corepack enable yarn config set cacheFolder /home/runner/publish-docs-cache yarn install # setup zodern:types. No linters are setup, so this simply installs the packages yarn meteor lint cd packages yarn build:all env: CI: true - name: Run typecheck and linter run: | cd packages yarn lint env: CI: true test-packages: name: Test Package ${{ matrix.package-name }} (Node ${{ matrix.node-version }}) runs-on: ubuntu-latest timeout-minutes: 15 strategy: fail-fast: false matrix: package-name: - blueprints-integration - server-core-integration - shared-lib # - live-status-gateway-api # no tests yet - openapi node-version: [22.x] include: # include additional configs, to run certain packages only for a certain version of node - node-version: 22.x package-name: corelib send-coverage: true - node-version: 22.x package-name: job-worker send-coverage: true # No tests for some gateways yet # - node-version: 22.x # package-name: playout-gateway # send-coverage: true - node-version: 22.x package-name: mos-gateway send-coverage: true - node-version: 22.x package-name: live-status-gateway send-coverage: true - node-version: 22.x package-name: webui send-coverage: true tsconfig-name: tsconfig.json # manual meteor-lib as it only needs a couple of versions - node-version: 22.x package-name: meteor-lib send-coverage: true steps: - uses: actions/checkout@v6 with: persist-credentials: false - name: Use Node.js ${{ matrix.node-version }} uses: actions/setup-node@v6 with: node-version: ${{ matrix.node-version }} - name: restore node_modules uses: actions/cache@v5 with: path: | packages/node_modules key: ${{ runner.os }}-${{ hashFiles('packages/yarn.lock') }} - name: Prepare Environment run: | corepack enable cd packages yarn config set cacheFolder /home/runner/test-packages-cache yarn install if [ "${{ matrix.package-name }}" = "openapi" ]; then yarn workspace @sofie-automation/openapi run build else yarn build:single ${{ matrix.package-name }}/${{ matrix.tsconfig-name || 'tsconfig.build.json' }} fi env: CI: true - name: Run tests run: | cd packages/${{ matrix.package-name }} yarn unit env: CI: true - name: Send coverage if: (matrix.node-version == '22.x' || matrix.send-coverage == true) && (((github.event_name == 'pull_request') && (!startsWith(github.head_ref, 'release'))) || ((github.event_name == 'push') && (!startsWith(github.ref_name, 'release')))) uses: codecov/codecov-action@v6 env: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} asyncapi-generation: name: AsyncAPI Generation runs-on: ubuntu-latest timeout-minutes: 15 steps: - uses: actions/checkout@v6 with: persist-credentials: false - name: Use Node.js uses: actions/setup-node@v6 with: node-version-file: ".node-version" - name: Prepare Environment run: | corepack enable cd packages yarn env: CI: true - name: Run generator run: | cd packages/live-status-gateway-api yarn gendocs yarn genserver yarn generate-schema-types env: CI: true openapi-generation: name: OpenAPI Generation runs-on: ubuntu-latest timeout-minutes: 15 steps: - uses: actions/checkout@v6 with: persist-credentials: false - name: Use Node.js uses: actions/setup-node@v6 with: node-version-file: ".node-version" - name: Prepare Environment run: | corepack enable cd packages yarn env: CI: true - name: Build OpenAPI client library run: | cd packages/openapi yarn build env: CI: true - name: Generate OpenAPI docs and server run: | cd packages/openapi yarn gendocs yarn genserver env: CI: true build-docs: name: Build Docs runs-on: ubuntu-latest timeout-minutes: 15 # This is just to ensure the docs build, another job performs the build & publish steps: - uses: actions/checkout@v6 with: persist-credentials: false - name: Use Node.js uses: actions/setup-node@v6 with: node-version-file: ".node-version" - uses: ./.github/actions/setup-meteor - name: restore node_modules uses: actions/cache@v5 with: path: | packages/node_modules key: ${{ runner.os }}-${{ hashFiles('packages/yarn.lock') }} - name: Prepare Environment run: | corepack enable yarn config set cacheFolder /home/runner/publish-docs-cache yarn install # setup zodern:types. No linters are setup, so this simply installs the packages yarn meteor lint cd packages yarn build:all env: CI: true - name: Run docusaurus run: | cd packages/documentation yarn docs:build env: CI: true - name: Run typedoc run: | cd packages yarn docs:typedoc cp docs documentation/build/typedoc -R env: CI: true check-for-multiple-library-versions: name: Check for multiple library versions runs-on: ubuntu-latest timeout-minutes: 15 steps: - uses: actions/checkout@v6 with: persist-credentials: false - name: Use Node.js uses: actions/setup-node@v6 with: node-version-file: ".node-version" - uses: ./.github/actions/setup-meteor - name: restore node_modules uses: actions/cache@v5 with: path: | node_modules meteor/node_modules packages/node_modules key: ${{ runner.os }}-${{ hashFiles('yarn.lock', 'meteor/yarn.lock', 'meteor/.meteor/release', 'packages/yarn.lock') }} - name: Prepare Environment run: | corepack enable yarn config set cacheFolder /home/runner/check-for-multiple-library-versions-cache yarn env: CI: true - name: Run check run: | yarn validate:versions env: CI: true