Skip to content

Render message-route anchor before surrounding context loads #588

Render message-route anchor before surrounding context loads

Render message-route anchor before surrounding context loads #588

Workflow file for this run

name: CI
on:
push:
branches: [master, develop]
tags:
- "[0-9]+.[0-9]+.[0-9]+*"
pull_request:
workflow_dispatch:
concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true
jobs:
check:
name: Lint, Typecheck, Test
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
with:
node-version-file: .nvmrc
cache: npm
- name: Install dependencies
run: npm install
- name: TypeScript
run: npm run typecheck
- name: ESLint
run: npm run lint
# - name: Prettier
# run: npm run format:check
#
# - name: Cognitive complexity
# run: npm run lint:cc
#
# - name: Security audit
# run: npm run audit:high --workspace=web
- name: Tests
run: npm run test
- name: Knip (dead code report)
continue-on-error: true
run: npm run knip --workspace=web
- name: Build (web)
run: |
echo "${PROD_ENVS}" | base64 -d > packages/web/.env.production
npm run build --workspace=web
env:
VITE_APP_VERSION: ${{ github.sha }}
PROD_ENVS: ${{ secrets.WEB_PROD_ENVS }}
e2e:
name: E2E (Playwright)
needs: check
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
with:
node-version-file: .nvmrc
cache: npm
- name: Install dependencies
run: npm install
- name: Install Playwright Chromium
run: npx playwright install --with-deps chromium
- name: Run E2E tests
run: npm run e2e -- --project=chromium --grep-invert @live
env:
CI: true
- name: Upload Playwright report
if: failure()
uses: actions/upload-artifact@v7
with:
name: playwright-report
path: |
e2e/results
playwright-report
retention-days: 7
build-electron:
name: Build Electron (${{ matrix.os }})
needs: check
if: >
github.event_name == 'workflow_dispatch' ||
(github.event_name == 'push' &&
(github.ref == 'refs/heads/master' || github.ref_type == 'tag'))
runs-on: ${{ matrix.os }}
timeout-minutes: 30
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-latest
cmd: package:electron:linux -- --linux rpm deb AppImage
- os: windows-latest
cmd: package:electron:win
- os: macos-latest
cmd: package:electron:mac
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
with:
node-version-file: .nvmrc
cache: npm
- name: Install dependencies
run: npm install
# - name: Install Electron dependencies
# run: npm ci
# working-directory: packages/electron
# macOS: import signing certificate from secrets
# - name: Import macOS signing certificate
# if: matrix.os == 'macos-latest' && env.CSC_LINK != ''
# env:
# CSC_LINK: ${{ secrets.MAC_CSC_LINK }}
# CSC_KEY_PASSWORD: ${{ secrets.MAC_CSC_KEY_PASSWORD }}
# run: echo "Certificate imported from secrets"
- name: Build web
shell: bash
run: |
echo "${PROD_ENVS}" | base64 -d > packages/web/.env.production
npm run build --workspace=web
env:
VITE_APP_VERSION: ${{ github.sha }}
PROD_ENVS: ${{ secrets.WEB_PROD_ENVS }}
- name: Build & Package
run: |
echo "${PROD_ENVS}" | base64 -d > packages/web/.env.production
npm run ${{ matrix.cmd }}
env:
PROD_ENVS: ${{ secrets.WEB_PROD_ENVS }}
# # macOS code signing (set secrets in GitHub repo settings)
# CSC_LINK: ${{ secrets.MAC_CSC_LINK }}
# CSC_KEY_PASSWORD: ${{ secrets.MAC_CSC_KEY_PASSWORD }}
# # macOS notarization
# APPLE_ID: ${{ secrets.APPLE_ID }}
# APPLE_APP_PASSWORD: ${{ secrets.APPLE_APP_PASSWORD }}
# APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
# # Windows code signing (future)
# # CSC_LINK: ${{ secrets.WIN_CSC_LINK }}
# # CSC_KEY_PASSWORD: ${{ secrets.WIN_CSC_KEY_PASSWORD }}
- name: Collect release files
id: collect
shell: bash
run: |
mkdir -p upload
cp "packages/electron/release"/Exordos\ Workspace* upload/ 2>/dev/null || true
ls -la upload/
- name: Upload artifacts
uses: actions/upload-artifact@v7
with:
name: electron-${{ matrix.os }}
path: upload/*
retention-days: 14
publish-apt:
name: Publish apt repository
needs: build-electron
# Self-hosted: the repository host is reached from inside the network, the same
# way the Exordos element is published. A GitHub-hosted runner depends on port 22
# staying open to the internet.
runs-on: [self-hosted, vm]
if: github.ref_type == 'tag'
timeout-minutes: 10
steps:
# This runner keeps its workspace between runs. Leftovers from an earlier
# release would be uploaded again, which can resurrect a version that
# retention already dropped on the host.
- name: Reset workspace
run: rm -rf artifacts debs
- name: Download Linux artifacts
uses: actions/download-artifact@v4
with:
name: electron-ubuntu-latest
path: artifacts
# Prereleases stay out of the repository: in a deb version everything after
# the last hyphen is the revision, so 0.4.0-rc1 sorts ABOVE 0.4.0 and apt
# would offer the release candidate as the newest stable build.
- name: Select packages
id: select
run: |
set -euo pipefail
if [[ ! "${GITHUB_REF_NAME}" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "::warning::${GITHUB_REF_NAME} is a prerelease tag — not published to the apt repository"
echo "publish=false" >> "${GITHUB_OUTPUT}"
exit 0
fi
mkdir -p debs
find artifacts -maxdepth 1 -name '*.deb' -exec cp {} debs/ \;
count=$(find debs -name '*.deb' | wc -l)
echo "Packages to publish: ${count}"
ls -la debs/
if [[ "${count}" -eq 0 ]]; then
echo "::error::no .deb artifacts found for tag ${GITHUB_REF_NAME}"
exit 1
fi
echo "publish=true" >> "${GITHUB_OUTPUT}"
# The repository host holds the pool, the aptly database and the signing
# key; this job only hands it the new packages. The deploy key is bound to
# a forced command there, and to this project's package names, so it cannot
# do anything else.
- name: Upload to repository host
if: steps.select.outputs.publish == 'true'
env:
SSH_TARGET: ${{ secrets.APT_REPO_SSH_TARGET }}
SSH_KEY: ${{ secrets.APT_REPO_SSH_KEY }}
SSH_KNOWN_HOSTS: ${{ secrets.APT_REPO_SSH_KNOWN_HOSTS }}
run: |
set -euo pipefail
if [[ -z "${SSH_TARGET}" ]]; then
echo "::warning::APT_REPO_SSH_TARGET is not configured — skipping apt publication"
exit 0
fi
# Credentials go to RUNNER_TEMP, not the workspace: the runner wipes it
# per job, while the workspace outlives the run.
umask 077
printf '%s\n' "${SSH_KEY}" > "${RUNNER_TEMP}/deploy_key"
printf '%s\n' "${SSH_KNOWN_HOSTS}" > "${RUNNER_TEMP}/known_hosts"
# Only the .deb files, listed explicitly: the repository host rejects an
# upload carrying anything else, and `release` now waits for that upload,
# so a stray file in this directory would block the whole release.
find debs -maxdepth 1 -name '*.deb' -printf '%P\0' \
| tar -C debs --null --files-from=- -c \
| ssh -T \
-i "${RUNNER_TEMP}/deploy_key" \
-o IdentitiesOnly=yes \
-o UserKnownHostsFile="${RUNNER_TEMP}/known_hosts" \
-o StrictHostKeyChecking=yes \
"${SSH_TARGET}"
- name: Clean up credentials
if: always()
run: rm -f "${RUNNER_TEMP}/deploy_key" "${RUNNER_TEMP}/known_hosts"
release:
name: Create GitHub Release
# Waits for the apt publication as well: announcing a release that never reached
# the repository leaves `apt upgrade` users without the version the release notes
# promise. The remaining ordering risk is the mirror image — packages published
# while this job fails — which is recoverable by re-running it.
needs: [build-electron, publish-apt]
runs-on: ubuntu-latest
if: github.ref_type == 'tag'
timeout-minutes: 10
permissions:
contents: write
steps:
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: artifacts
pattern: electron-*
merge-multiple: true
- name: List artifacts
run: ls -la artifacts/
- name: Create Release
uses: softprops/action-gh-release@v2
with:
files: artifacts/Exordos Workspace*
generate_release_notes: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}