diff --git a/.github/actions/fetch-frontend-artifact/action.yml b/.github/actions/fetch-frontend-artifact/action.yml new file mode 100644 index 00000000..3a1efbaa --- /dev/null +++ b/.github/actions/fetch-frontend-artifact/action.yml @@ -0,0 +1,32 @@ +# Pinned actions (bump tag and SHA together when upgrading): +# actions/download-artifact@v5.0.0 634f93cb2916e3fdff6788551b99b062d0335ce0 +name: Fetch frontend artifact +description: Download a prebuilt meshchatx/public artifact and verify required paths + +inputs: + artifact-name: + description: Artifact name from the reusable frontend-build workflow + required: true + path: + description: Destination directory for meshchatx/public contents + required: false + default: meshchatx/public + +runs: + using: composite + steps: + - name: Download frontend artifact + uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 + with: + name: ${{ inputs.artifact-name }} + path: ${{ inputs.path }} + + - name: Verify frontend artifact contents + shell: bash + env: + FRONTEND_PATH: ${{ inputs.path }} + run: | + set -euo pipefail + test -f "${FRONTEND_PATH}/index.html" + test -d "${FRONTEND_PATH}/assets" + test -d "${FRONTEND_PATH}/reticulum-docs-bundled/current" diff --git a/.github/actions/setup-dev-environment/action.yml b/.github/actions/setup-dev-environment/action.yml new file mode 100644 index 00000000..7ba80554 --- /dev/null +++ b/.github/actions/setup-dev-environment/action.yml @@ -0,0 +1,37 @@ +name: Set up development environment +description: Python/UV, Node/pnpm, and full project dependencies for CI jobs + +inputs: + python-version: + description: Python version + required: true + uv-version: + description: UV version installed from PyPI + required: false + default: "0.11.15" + node-version: + description: Node.js version + required: true + pnpm-version: + description: pnpm version activated through corepack + required: false + default: "11.1.2" + +runs: + using: composite + steps: + - name: Set up Python and UV + uses: ./.github/actions/setup-python-uv + with: + python-version: ${{ inputs.python-version }} + uv-version: ${{ inputs.uv-version }} + + - name: Set up Node and pnpm + uses: ./.github/actions/setup-node-pnpm + with: + node-version: ${{ inputs.node-version }} + pnpm-version: ${{ inputs.pnpm-version }} + + - name: Install dependencies + shell: bash + run: bash scripts/ci/github-install-deps.sh diff --git a/.github/actions/setup-python-uv/action.yml b/.github/actions/setup-python-uv/action.yml new file mode 100644 index 00000000..dbe23c93 --- /dev/null +++ b/.github/actions/setup-python-uv/action.yml @@ -0,0 +1,36 @@ +# Pinned actions (bump tag and SHA together when upgrading): +# actions/setup-python@v6.2.0 a309ff8b426b58ec0e2a45f0f869d46889d02405 +# actions/cache@v4.2.0 1bd1e32a3bdc45362d1e726936510720a7c30a57 +name: Set up Python and UV +description: Python runtime, pinned UV installer, and UV download cache + +inputs: + python-version: + description: Python version + required: true + uv-version: + description: UV version installed from PyPI + required: false + default: "0.11.15" + +runs: + using: composite + steps: + - name: Set up Python + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 + with: + python-version: ${{ inputs.python-version }} + + - name: Install UV (PyPI pin) + shell: bash + env: + UV_VERSION: ${{ inputs.uv-version }} + run: bash scripts/ci/github-install-uv.sh + + - name: Cache UV downloads + uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 + with: + path: ~/.cache/uv + key: ${{ runner.os }}-uv-${{ hashFiles('uv.lock') }} + restore-keys: | + ${{ runner.os }}-uv- diff --git a/.github/dependabot.yml b/.github/dependabot.yml index e344dc72..91094bda 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -12,3 +12,19 @@ updates: - electron - electron-* - "@electron/*" + + - package-ecosystem: github-actions + directory: / + schedule: + interval: weekly + open-pull-requests-limit: 10 + groups: + actions: + patterns: + - actions/* + - docker/* + - github/* + - sigstore/* + - pypa/* + - benchmark-action/* + - slsa-framework/* diff --git a/.github/workflows/android-apk-tag.yml b/.github/workflows/android-apk-tag.yml index b5c59f97..f64be54c 100644 --- a/.github/workflows/android-apk-tag.yml +++ b/.github/workflows/android-apk-tag.yml @@ -114,17 +114,9 @@ jobs: python-version: ${{ env.PYTHON_VERSION }} - name: Download frontend artifact - uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 + uses: ./.github/actions/fetch-frontend-artifact with: - name: ${{ env.FRONTEND_ARTIFACT_NAME }} - path: meshchatx/public - - - name: Verify frontend artifact contents - run: | - set -euo pipefail - test -f meshchatx/public/index.html - test -d meshchatx/public/assets - test -d meshchatx/public/reticulum-docs-bundled/current + artifact-name: ${{ env.FRONTEND_ARTIFACT_NAME }} - name: Install Android wheel build dependencies run: | diff --git a/.github/workflows/android-build.yml b/.github/workflows/android-build.yml index e73a6b31..01b37c3f 100644 --- a/.github/workflows/android-build.yml +++ b/.github/workflows/android-build.yml @@ -35,7 +35,7 @@ permissions: actions: write concurrency: - group: ${{ github.workflow }}-${{ github.ref }} + group: android-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} cancel-in-progress: true env: @@ -142,17 +142,9 @@ jobs: python-version: ${{ env.PYTHON_VERSION }} - name: Download frontend artifact - uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 + uses: ./.github/actions/fetch-frontend-artifact with: - name: ${{ env.FRONTEND_ARTIFACT_NAME }} - path: meshchatx/public - - - name: Verify frontend artifact contents - run: | - set -euo pipefail - test -f meshchatx/public/index.html - test -d meshchatx/public/assets - test -d meshchatx/public/reticulum-docs-bundled/current + artifact-name: ${{ env.FRONTEND_ARTIFACT_NAME }} - name: Install Android wheel build dependencies run: | diff --git a/.github/workflows/bench.yml b/.github/workflows/bench.yml index f4707da2..92f9adb4 100644 --- a/.github/workflows/bench.yml +++ b/.github/workflows/bench.yml @@ -5,8 +5,6 @@ # # Pinned first-party actions (bump tag and SHA together when upgrading): # actions/checkout@v6.0.1 8e8c483db84b4bee98b60c0593521ed34d9990e8 -# actions/setup-python@v6.2.0 a309ff8b426b58ec0e2a45f0f869d46889d02405 -# actions/setup-node@v6.1.0 395ad3262231945c25e8478fd5baf05154b1d79f # actions/cache@v4.2.0 1bd1e32a3bdc45362d1e726936510720a7c30a57 # benchmark-action/github-action-benchmark@v1.22.0 # a60cea5bc7b49e15c1f58f411161f99e0df48372 @@ -21,7 +19,7 @@ on: - dev concurrency: - group: ${{ github.workflow }}-${{ github.ref }} + group: bench-${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true permissions: @@ -43,33 +41,14 @@ jobs: - name: Checkout uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 - - name: Set up Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 + - name: Set up development environment + uses: ./.github/actions/setup-dev-environment with: python-version: ${{ env.PYTHON_VERSION }} - - - name: Install UV (PyPI pin) - env: - UV_VERSION: ${{ env.UV_VERSION }} - run: bash scripts/ci/github-install-uv.sh - - - name: Cache UV downloads - uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 - with: - path: ~/.cache/uv - key: ${{ runner.os }}-uv-${{ hashFiles('uv.lock') }} - restore-keys: | - ${{ runner.os }}-uv- - - - name: Set up Node and pnpm - uses: ./.github/actions/setup-node-pnpm - with: + uv-version: ${{ env.UV_VERSION }} node-version: ${{ env.NODE_VERSION }} pnpm-version: ${{ env.PNPM_VERSION }} - - name: Install dependencies - run: bash scripts/ci/github-install-deps.sh - - name: Setup Task run: sh scripts/ci/setup-task.sh @@ -100,10 +79,6 @@ jobs: output-file-path: bench_results.json external-data-json-path: ./cache/benchmark-data.json github-token: ${{ secrets.GITHUB_TOKEN }} - # GitHub shared runners have 20-40% variance even with identical - # code. alert-threshold posts a comment; fail-threshold fails - # the job. Sub-ms operations are especially noisy so we keep - # the comment bar at 2x and the hard-fail bar at 3x. alert-threshold: "200%" fail-threshold: "300%" fail-on-alert: true diff --git a/.github/workflows/build-linux-packages.yml b/.github/workflows/build-linux-packages.yml index 695c5eca..2a5ed97d 100644 --- a/.github/workflows/build-linux-packages.yml +++ b/.github/workflows/build-linux-packages.yml @@ -1,13 +1,9 @@ # Linux packaging build test: AppImage, deb, rpm, Flatpak (branches and PRs). -# Tagged release assets run in .github/workflows/build-release.yml with draft. +# Tagged release assets run in build-release.yml with draft. # # Pinned first-party actions (bump tag and SHA together when upgrading): # actions/checkout@v6.0.1 8e8c483db84b4bee98b60c0593521ed34d9990e8 -# actions/setup-python@v6.2.0 a309ff8b426b58ec0e2a45f0f869d46889d02405 -# actions/setup-node@v6.1.0 395ad3262231945c25e8478fd5baf05154b1d79f # actions/upload-artifact@v5.0.0 330a01c490aca151604b8cf639adc76d48f6c5d4 -# actions/download-artifact@v5.0.0 634f93cb2916e3fdff6788551b99b062d0335ce0 -# actions/cache@v4.2.0 1bd1e32a3bdc45362d1e726936510720a7c30a57 name: Build Linux packages @@ -25,13 +21,14 @@ on: - ".github/workflows/build-linux-packages.yml" - ".github/workflows/build-release.yml" - ".github/workflows/frontend-build.yml" + - ".github/actions/**" workflow_dispatch: permissions: contents: read concurrency: - group: ${{ github.workflow }}-${{ github.ref }} + group: linux-packages-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} cancel-in-progress: true env: @@ -52,10 +49,18 @@ jobs: artifact_name: meshchatx-frontend-linux-pkg-${{ github.run_id }}-${{ github.run_attempt }} retention_days: 1 - linux-test-x64: - name: Linux build test (x64) + linux-test: + name: Linux build test (${{ matrix.arch }}) needs: frontend - runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + include: + - arch: x64 + runner: ubuntu-latest + - arch: arm64 + runner: ubuntu-24.04-arm + runs-on: ${{ matrix.runner }} timeout-minutes: 120 permissions: contents: read @@ -67,23 +72,11 @@ jobs: - name: Checkout uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 - - name: Set up Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 + - name: Set up Python and UV + uses: ./.github/actions/setup-python-uv with: python-version: ${{ env.PYTHON_VERSION }} - - - name: Install UV (PyPI pin) - env: - UV_VERSION: ${{ env.UV_VERSION }} - run: bash scripts/ci/github-install-uv.sh - - - name: Cache UV downloads - uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 - with: - path: ~/.cache/uv - key: ${{ runner.os }}-uv-${{ hashFiles('uv.lock') }} - restore-keys: | - ${{ runner.os }}-uv- + uv-version: ${{ env.UV_VERSION }} - name: Set up Node and pnpm uses: ./.github/actions/setup-node-pnpm @@ -94,21 +87,13 @@ jobs: - name: Linux packaging APT dependencies run: bash scripts/ci/github-apt-linux-packaging.sh - - name: Install project dependencies + - name: Install dependencies run: bash scripts/ci/github-install-deps.sh - - name: Download frontend artifact - uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 + - name: Fetch frontend artifact + uses: ./.github/actions/fetch-frontend-artifact with: - name: ${{ env.FRONTEND_ARTIFACT_NAME }} - path: meshchatx/public - - - name: Verify frontend artifact contents - run: | - set -euo pipefail - test -f meshchatx/public/index.html - test -d meshchatx/public/assets - test -d meshchatx/public/reticulum-docs-bundled/current + artifact-name: ${{ env.FRONTEND_ARTIFACT_NAME }} - name: Setup Task run: sh scripts/ci/setup-task.sh @@ -116,82 +101,10 @@ jobs: - name: Build release-assets run: bash scripts/ci/github-build-linux-release-assets.sh - - name: Upload Linux build-test artifact (x64) + - name: Upload Linux build-test artifact (${{ matrix.arch }}) uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 with: - name: meshchatx-linux-build-test-x64-${{ github.ref_name }}-${{ github.run_id }} - path: release-assets/ - if-no-files-found: warn - retention-days: 1 - - linux-test-arm64: - name: Linux build test (arm64) - needs: frontend - runs-on: ubuntu-24.04-arm - timeout-minutes: 120 - permissions: - contents: read - actions: write - env: - FRONTEND_ARTIFACT_NAME: ${{ needs.frontend.outputs.artifact_name }} - MESHCHATX_FRONTEND_PREBUILT: "1" - steps: - - name: Checkout - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 - - - name: Set up Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 - with: - python-version: ${{ env.PYTHON_VERSION }} - - - name: Install UV (PyPI pin) - env: - UV_VERSION: ${{ env.UV_VERSION }} - run: bash scripts/ci/github-install-uv.sh - - - name: Cache UV downloads - uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 - with: - path: ~/.cache/uv - key: ${{ runner.os }}-uv-${{ hashFiles('uv.lock') }} - restore-keys: | - ${{ runner.os }}-uv- - - - name: Set up Node and pnpm - uses: ./.github/actions/setup-node-pnpm - with: - node-version: ${{ env.NODE_VERSION }} - pnpm-version: ${{ env.PNPM_VERSION }} - - - name: Linux packaging APT dependencies - run: bash scripts/ci/github-apt-linux-packaging.sh - - - name: Install project dependencies - run: bash scripts/ci/github-install-deps.sh - - - name: Download frontend artifact - uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 - with: - name: ${{ env.FRONTEND_ARTIFACT_NAME }} - path: meshchatx/public - - - name: Verify frontend artifact contents - run: | - set -euo pipefail - test -f meshchatx/public/index.html - test -d meshchatx/public/assets - test -d meshchatx/public/reticulum-docs-bundled/current - - - name: Setup Task - run: sh scripts/ci/setup-task.sh - - - name: Build release-assets - run: bash scripts/ci/github-build-linux-release-assets.sh - - - name: Upload Linux build-test artifact (arm64) - uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 - with: - name: meshchatx-linux-build-test-arm64-${{ github.ref_name }}-${{ github.run_id }} + name: meshchatx-linux-build-test-${{ matrix.arch }}-${{ github.ref_name }}-${{ github.run_id }} path: release-assets/ if-no-files-found: warn retention-days: 1 @@ -231,45 +144,18 @@ jobs: org.freedesktop.Sdk//25.08 \ org.electronjs.Electron2.BaseApp//25.08 - - name: Set up Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 + - name: Set up development environment + uses: ./.github/actions/setup-dev-environment with: python-version: ${{ env.PYTHON_VERSION }} - - - name: Install UV (PyPI pin) - env: - UV_VERSION: ${{ env.UV_VERSION }} - run: bash scripts/ci/github-install-uv.sh - - - name: Cache UV downloads - uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 - with: - path: ~/.cache/uv - key: ${{ runner.os }}-uv-${{ hashFiles('uv.lock') }} - restore-keys: | - ${{ runner.os }}-uv- - - - name: Set up Node and pnpm - uses: ./.github/actions/setup-node-pnpm - with: + uv-version: ${{ env.UV_VERSION }} node-version: ${{ env.NODE_VERSION }} pnpm-version: ${{ env.PNPM_VERSION }} - - name: Install dependencies - run: bash scripts/ci/github-install-deps.sh - - - name: Download frontend artifact - uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 + - name: Fetch frontend artifact + uses: ./.github/actions/fetch-frontend-artifact with: - name: ${{ env.FRONTEND_ARTIFACT_NAME }} - path: meshchatx/public - - - name: Verify frontend artifact contents - run: | - set -euo pipefail - test -f meshchatx/public/index.html - test -d meshchatx/public/assets - test -d meshchatx/public/reticulum-docs-bundled/current + artifact-name: ${{ env.FRONTEND_ARTIFACT_NAME }} - name: Build flatpak bundle run: bash scripts/ci/github-build-linux-flatpak.sh diff --git a/.github/workflows/build-release.yml b/.github/workflows/build-release.yml index 340226a6..1f0abb96 100644 --- a/.github/workflows/build-release.yml +++ b/.github/workflows/build-release.yml @@ -15,8 +15,9 @@ # actions/cache@v4.2.0 1bd1e32a3bdc45362d1e726936510720a7c30a57 # actions/setup-java@v4.7.1 c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # -# SLSA generator (must stay @vX.Y.Z semver per upstream): +# SLSA generator (pinned to v2.1.0 commit): # slsa-framework/slsa-github-generator/generator_generic_slsa3.yml@v2.1.0 +# f7dd8c54c2067bafc12ca7a55595d5ee9b75204a name: Build release @@ -81,9 +82,19 @@ jobs: run_unit_tests: true linux-release: - name: Linux release assets (x64) + name: Linux release assets (${{ matrix.arch }}) needs: frontend - runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + include: + - arch: x64 + runner: ubuntu-latest + setup_trivy: true + - arch: arm64 + runner: ubuntu-24.04-arm + setup_trivy: false + runs-on: ${{ matrix.runner }} timeout-minutes: 120 permissions: contents: read @@ -95,23 +106,11 @@ jobs: - name: Checkout uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 - - name: Set up Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 + - name: Set up Python and UV + uses: ./.github/actions/setup-python-uv with: python-version: ${{ env.PYTHON_VERSION }} - - - name: Install UV (PyPI pin) - env: - UV_VERSION: ${{ env.UV_VERSION }} - run: bash scripts/ci/github-install-uv.sh - - - name: Cache UV downloads - uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 - with: - path: ~/.cache/uv - key: ${{ runner.os }}-uv-${{ hashFiles('uv.lock') }} - restore-keys: | - ${{ runner.os }}-uv- + uv-version: ${{ env.UV_VERSION }} - name: Set up Node and pnpm uses: ./.github/actions/setup-node-pnpm @@ -122,114 +121,40 @@ jobs: - name: Linux packaging APT dependencies run: bash scripts/ci/github-apt-linux-packaging.sh - - name: Install project dependencies + - name: Install dependencies run: bash scripts/ci/github-install-deps.sh - - name: Download frontend artifact - uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 + - name: Fetch frontend artifact + uses: ./.github/actions/fetch-frontend-artifact with: - name: ${{ env.FRONTEND_ARTIFACT_NAME }} - path: meshchatx/public - - - name: Verify frontend artifact contents - run: | - set -euo pipefail - test -f meshchatx/public/index.html - test -d meshchatx/public/assets - test -d meshchatx/public/reticulum-docs-bundled/current + artifact-name: ${{ env.FRONTEND_ARTIFACT_NAME }} - name: Setup Task + if: matrix.setup_trivy run: sh scripts/ci/setup-task.sh - name: Apt update (for Trivy .deb) + if: matrix.setup_trivy run: sh scripts/ci/exec-priv.sh apt-get update -qq - name: Setup Trivy + if: matrix.setup_trivy run: sh scripts/ci/setup-trivy.sh - name: Build release-assets run: bash scripts/ci/github-build-linux-release-assets.sh - - name: Upload Linux release artifact (x64) + - name: Upload Linux release artifact (${{ matrix.arch }}) uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 with: - name: meshchatx-linux-release-x64-${{ github.ref_name }}-${{ github.run_id }} - path: release-assets/ - if-no-files-found: error - retention-days: 30 - - linux-release-arm64: - name: Linux release assets (arm64) - needs: frontend - runs-on: ubuntu-24.04-arm - timeout-minutes: 120 - permissions: - contents: read - actions: write - env: - FRONTEND_ARTIFACT_NAME: ${{ needs.frontend.outputs.artifact_name }} - MESHCHATX_FRONTEND_PREBUILT: "1" - steps: - - name: Checkout - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 - - - name: Set up Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 - with: - python-version: ${{ env.PYTHON_VERSION }} - - - name: Install UV (PyPI pin) - env: - UV_VERSION: ${{ env.UV_VERSION }} - run: bash scripts/ci/github-install-uv.sh - - - name: Cache UV downloads - uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 - with: - path: ~/.cache/uv - key: ${{ runner.os }}-uv-${{ hashFiles('uv.lock') }} - restore-keys: | - ${{ runner.os }}-uv- - - - name: Set up Node and pnpm - uses: ./.github/actions/setup-node-pnpm - with: - node-version: ${{ env.NODE_VERSION }} - pnpm-version: ${{ env.PNPM_VERSION }} - - - name: Linux packaging APT dependencies - run: bash scripts/ci/github-apt-linux-packaging.sh - - - name: Install project dependencies - run: bash scripts/ci/github-install-deps.sh - - - name: Download frontend artifact - uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 - with: - name: ${{ env.FRONTEND_ARTIFACT_NAME }} - path: meshchatx/public - - - name: Verify frontend artifact contents - run: | - set -euo pipefail - test -f meshchatx/public/index.html - test -d meshchatx/public/assets - test -d meshchatx/public/reticulum-docs-bundled/current - - - name: Build release-assets - run: bash scripts/ci/github-build-linux-release-assets.sh - - - name: Upload Linux release artifact (arm64) - uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 - with: - name: meshchatx-linux-release-arm64-${{ github.ref_name }}-${{ github.run_id }} + name: meshchatx-linux-release-${{ matrix.arch }}-${{ github.ref_name }}-${{ github.run_id }} path: release-assets/ if-no-files-found: error retention-days: 30 collect-linux-slsa-subjects: name: SLSA subjects + cosign (Linux) - needs: [linux-release, linux-release-arm64] + needs: [linux-release] if: startsWith(github.ref, 'refs/tags/') runs-on: ubuntu-latest outputs: @@ -542,7 +467,7 @@ jobs: id-token: write contents: write actions: read - uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.1.0 + uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@f7dd8c54c2067bafc12ca7a55595d5ee9b75204a with: base64-subjects: ${{ needs.collect-linux-slsa-subjects.outputs.hashes }} upload-assets: false @@ -560,7 +485,7 @@ jobs: id-token: write contents: write actions: read - uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.1.0 + uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@f7dd8c54c2067bafc12ca7a55595d5ee9b75204a with: base64-subjects: ${{ needs.collect-desktop-slsa-subjects.outputs.hashes }} upload-assets: false @@ -609,7 +534,7 @@ jobs: id-token: write contents: write actions: read - uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.1.0 + uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@f7dd8c54c2067bafc12ca7a55595d5ee9b75204a with: base64-subjects: ${{ needs.collect-android-flatpak-slsa-subjects.outputs.hashes }} upload-assets: false @@ -619,7 +544,6 @@ jobs: name: Draft GitHub release (all assets + SLSA) needs: - linux-release - - linux-release-arm64 - collect-linux-slsa-subjects - slsa-provenance-linux - build-release @@ -633,7 +557,6 @@ jobs: !cancelled() && startsWith(github.ref, 'refs/tags/') && needs.linux-release.result == 'success' && - needs.linux-release-arm64.result == 'success' && needs.collect-linux-slsa-subjects.result == 'success' && needs.slsa-provenance-linux.result == 'success' && (needs.build-release.result == 'success' || needs.build-release.result == 'failure') && diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml deleted file mode 100644 index 854597ae..00000000 --- a/.github/workflows/build.yml +++ /dev/null @@ -1,144 +0,0 @@ -# Native build verification (Windows + macOS). -# -# Pulls the prebuilt meshchatx/public artifact produced by the reusable -# Frontend build workflow so that each platform job only has to compile the -# cx_Freeze backend and run electron-builder. -# -# Pinned first-party actions (bump tag and SHA together when upgrading): -# actions/checkout@v6.0.1 8e8c483db84b4bee98b60c0593521ed34d9990e8 -# actions/setup-python@v6.2.0 a309ff8b426b58ec0e2a45f0f869d46889d02405 -# actions/setup-node@v6.1.0 395ad3262231945c25e8478fd5baf05154b1d79f -# actions/download-artifact@v5.0.0 634f93cb2916e3fdff6788551b99b062d0335ce0 - -name: Build - -on: - push: - branches: - - dev - pull_request: - branches: - - dev - workflow_dispatch: - -permissions: - contents: read - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -env: - FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true - NODE_OPTIONS: --max-old-space-size=8192 - PYTHON_VERSION: "3.14" - NODE_VERSION: "24" - UV_VERSION: "0.11.15" - PNPM_VERSION: "11.1.2" - -jobs: - frontend: - name: Build frontend artifact - uses: ./.github/workflows/frontend-build.yml - permissions: - contents: read - with: - artifact_name: meshchatx-frontend-build-${{ github.run_id }}-${{ github.run_attempt }} - retention_days: 1 - - build-test: - name: Build test (${{ matrix.label }}) - needs: frontend - permissions: - contents: read - strategy: - fail-fast: false - matrix: - include: - - os: windows-latest - label: windows - timeout: 120 - build_script: scripts/ci/github-build-windows.sh - - os: macos-latest - label: macos - timeout: 180 - build_script: scripts/ci/github-build-macos.sh - runs-on: ${{ matrix.os }} - timeout-minutes: ${{ matrix.timeout }} - defaults: - run: - shell: bash - env: - FRONTEND_ARTIFACT_NAME: ${{ needs.frontend.outputs.artifact_name }} - MESHCHATX_FRONTEND_PREBUILT: "1" - steps: - - name: Checkout - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 - - - name: Set up Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 - with: - python-version: ${{ env.PYTHON_VERSION }} - - - name: Install UV (PyPI pin) - env: - UV_VERSION: ${{ env.UV_VERSION }} - run: bash scripts/ci/github-install-uv.sh - - - name: Set up Node and pnpm - uses: ./.github/actions/setup-node-pnpm - with: - node-version: ${{ env.NODE_VERSION }} - pnpm-version: ${{ env.PNPM_VERSION }} - - - name: Install dependencies - run: bash scripts/ci/github-install-deps.sh - - - name: Install Rosetta (Apple Silicon) - if: matrix.label == 'macos' - run: /usr/sbin/softwareupdate --install-rosetta --agree-to-license || true - - - name: Ensure x86_64 Homebrew (/usr/local) for universal slice - if: matrix.label == 'macos' - run: bash scripts/ci/github-ensure-macos-x86-64-homebrew.sh - - - name: Set up Python x64 for cx_Freeze universal slice - id: python_x64 - if: matrix.label == 'macos' - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 - with: - python-version: ${{ env.PYTHON_VERSION }} - architecture: x64 - update-environment: false - - - name: Install x86_64 codec2 for pycodec2 (universal slice) - if: matrix.label == 'macos' - run: | - set -euo pipefail - arch -x86_64 /usr/local/bin/brew install codec2 - - - name: Install Rust x86_64-apple-darwin target (cbor2 x64 slice) - if: matrix.label == 'macos' - run: bash scripts/ci/github-macos-rust-x64-target.sh - - - name: Install project deps into x64 Python (mac universal cx_Freeze) - if: matrix.label == 'macos' - env: - PY_X64: ${{ steps.python_x64.outputs.python-path }} - run: bash scripts/ci/github-install-macos-x64-python-deps.sh - - - name: Download frontend artifact - uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 - with: - name: ${{ env.FRONTEND_ARTIFACT_NAME }} - path: meshchatx/public - - - name: Verify frontend artifact contents - run: | - set -euo pipefail - test -f meshchatx/public/index.html - test -d meshchatx/public/assets - test -d meshchatx/public/reticulum-docs-bundled/current - - - name: Build distributables - run: bash "${{ matrix.build_script }}" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fbc53b42..2dec3718 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,16 +1,14 @@ -# Linux CI: lint, frontend/backend tests, localization, and a Linux build check. +# Primary CI: lint, tests, localization, Linux build check, E2E, and native builds (dev). # -# The frontend bundle is produced once by the reusable Frontend build workflow -# and downloaded by the Linux build-check job (and by the platform build/release -# workflows) instead of being rebuilt on every job. +# The frontend bundle is built once via the reusable frontend-build workflow and +# downloaded by downstream jobs instead of rebuilding on every runner. # # Pinned first-party actions (bump tag and SHA together when upgrading): # actions/checkout@v6.0.1 8e8c483db84b4bee98b60c0593521ed34d9990e8 # actions/setup-python@v6.2.0 a309ff8b426b58ec0e2a45f0f869d46889d02405 -# actions/setup-node@v6.1.0 395ad3262231945c25e8478fd5baf05154b1d79f # actions/upload-artifact@v5.0.0 330a01c490aca151604b8cf639adc76d48f6c5d4 # actions/download-artifact@v5.0.0 634f93cb2916e3fdff6788551b99b062d0335ce0 -# actions/cache@v4.2.0 1bd1e32a3bdc45362d1e726936510720a7c30a57 + name: CI on: @@ -27,7 +25,7 @@ permissions: contents: read concurrency: - group: ${{ github.workflow }}-${{ github.ref }} + group: ci-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} cancel-in-progress: true env: @@ -75,33 +73,14 @@ jobs: - name: Checkout uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 - - name: Set up Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 + - name: Set up development environment + uses: ./.github/actions/setup-dev-environment with: python-version: ${{ env.PYTHON_VERSION }} - - - name: Install UV (PyPI pin) - env: - UV_VERSION: ${{ env.UV_VERSION }} - run: bash scripts/ci/github-install-uv.sh - - - name: Cache UV downloads - uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 - with: - path: ~/.cache/uv - key: ${{ runner.os }}-uv-${{ hashFiles('uv.lock') }} - restore-keys: | - ${{ runner.os }}-uv- - - - name: Set up Node and pnpm - uses: ./.github/actions/setup-node-pnpm - with: + uv-version: ${{ env.UV_VERSION }} node-version: ${{ env.NODE_VERSION }} pnpm-version: ${{ env.PNPM_VERSION }} - - name: Install dependencies - run: bash scripts/ci/github-install-deps.sh - - name: Run matrix task run: | set -euo pipefail @@ -143,45 +122,18 @@ jobs: - name: Checkout uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 - - name: Set up Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 + - name: Set up development environment + uses: ./.github/actions/setup-dev-environment with: python-version: ${{ env.PYTHON_VERSION }} - - - name: Install UV (PyPI pin) - env: - UV_VERSION: ${{ env.UV_VERSION }} - run: bash scripts/ci/github-install-uv.sh - - - name: Cache UV downloads - uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 - with: - path: ~/.cache/uv - key: ${{ runner.os }}-uv-${{ hashFiles('uv.lock') }} - restore-keys: | - ${{ runner.os }}-uv- - - - name: Set up Node and pnpm - uses: ./.github/actions/setup-node-pnpm - with: + uv-version: ${{ env.UV_VERSION }} node-version: ${{ env.NODE_VERSION }} pnpm-version: ${{ env.PNPM_VERSION }} - - name: Install dependencies - run: bash scripts/ci/github-install-deps.sh - - - name: Download frontend artifact - uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 + - name: Fetch frontend artifact + uses: ./.github/actions/fetch-frontend-artifact with: - name: ${{ env.FRONTEND_ARTIFACT_NAME }} - path: meshchatx/public - - - name: Verify frontend artifact contents - run: | - set -euo pipefail - test -f meshchatx/public/index.html - test -d meshchatx/public/assets - test -d meshchatx/public/reticulum-docs-bundled/current + artifact-name: ${{ env.FRONTEND_ARTIFACT_NAME }} - name: Compile backend sources run: uv run python -m compileall meshchatx/ @@ -222,33 +174,43 @@ jobs: test -n "$(ls -A .artifacts/linux-build-check/build/exe)" echo "Linux build artifact download + content validation passed." - e2e: - name: E2E smoke - runs-on: ubuntu-latest - timeout-minutes: 20 + native-build: + name: Native build (${{ matrix.label }}) + if: >- + github.ref == 'refs/heads/dev' || + (github.event_name == 'pull_request' && github.base_ref == 'dev') + needs: frontend permissions: contents: read + strategy: + fail-fast: false + matrix: + include: + - os: windows-latest + label: windows + timeout: 120 + build_script: scripts/ci/github-build-windows.sh + - os: macos-latest + label: macos + timeout: 180 + build_script: scripts/ci/github-build-macos.sh + runs-on: ${{ matrix.os }} + timeout-minutes: ${{ matrix.timeout }} + defaults: + run: + shell: bash + env: + FRONTEND_ARTIFACT_NAME: ${{ needs.frontend.outputs.artifact_name }} + MESHCHATX_FRONTEND_PREBUILT: "1" steps: - name: Checkout uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 - - name: Set up Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 + - name: Set up Python and UV + uses: ./.github/actions/setup-python-uv with: python-version: ${{ env.PYTHON_VERSION }} - - - name: Install UV (PyPI pin) - env: - UV_VERSION: ${{ env.UV_VERSION }} - run: bash scripts/ci/github-install-uv.sh - - - name: Cache UV downloads - uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 - with: - path: ~/.cache/uv - key: ${{ runner.os }}-uv-${{ hashFiles('uv.lock') }} - restore-keys: | - ${{ runner.os }}-uv- + uv-version: ${{ env.UV_VERSION }} - name: Set up Node and pnpm uses: ./.github/actions/setup-node-pnpm @@ -259,5 +221,64 @@ jobs: - name: Install dependencies run: bash scripts/ci/github-install-deps.sh + - name: Install Rosetta (Apple Silicon) + if: matrix.label == 'macos' + run: /usr/sbin/softwareupdate --install-rosetta --agree-to-license || true + + - name: Ensure x86_64 Homebrew (/usr/local) for universal slice + if: matrix.label == 'macos' + run: bash scripts/ci/github-ensure-macos-x86-64-homebrew.sh + + - name: Set up Python x64 for cx_Freeze universal slice + id: python_x64 + if: matrix.label == 'macos' + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 + with: + python-version: ${{ env.PYTHON_VERSION }} + architecture: x64 + update-environment: false + + - name: Install x86_64 codec2 for pycodec2 (universal slice) + if: matrix.label == 'macos' + run: | + set -euo pipefail + arch -x86_64 /usr/local/bin/brew install codec2 + + - name: Install Rust x86_64-apple-darwin target (cbor2 x64 slice) + if: matrix.label == 'macos' + run: bash scripts/ci/github-macos-rust-x64-target.sh + + - name: Install project deps into x64 Python (mac universal cx_Freeze) + if: matrix.label == 'macos' + env: + PY_X64: ${{ steps.python_x64.outputs.python-path }} + run: bash scripts/ci/github-install-macos-x64-python-deps.sh + + - name: Fetch frontend artifact + uses: ./.github/actions/fetch-frontend-artifact + with: + artifact-name: ${{ env.FRONTEND_ARTIFACT_NAME }} + + - name: Build distributables + run: bash "${{ matrix.build_script }}" + + e2e: + name: E2E smoke + runs-on: ubuntu-latest + timeout-minutes: 20 + permissions: + contents: read + steps: + - name: Checkout + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 + + - name: Set up development environment + uses: ./.github/actions/setup-dev-environment + with: + python-version: ${{ env.PYTHON_VERSION }} + uv-version: ${{ env.UV_VERSION }} + node-version: ${{ env.NODE_VERSION }} + pnpm-version: ${{ env.PNPM_VERSION }} + - name: Run Playwright smoke E2E run: bash scripts/ci/github-e2e.sh diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index b064471f..c61f5c23 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -44,7 +44,7 @@ permissions: id-token: write concurrency: - group: ${{ github.workflow }}-${{ github.ref }} + group: docker-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} cancel-in-progress: true env: diff --git a/.github/workflows/pypi.yml b/.github/workflows/pypi.yml index 5cfb925c..5e5a18b4 100644 --- a/.github/workflows/pypi.yml +++ b/.github/workflows/pypi.yml @@ -16,8 +16,9 @@ # actions/upload-artifact@v5.0.0 330a01c490aca151604b8cf639adc76d48f6c5d4 # actions/download-artifact@v5.0.0 634f93cb2916e3fdff6788551b99b062d0335ce0 # -# SLSA generator (must stay @vX.Y.Z semver per upstream): +# SLSA generator (pinned to v2.1.0 commit): # slsa-framework/slsa-github-generator/generator_generic_slsa3.yml@v2.1.0 +# f7dd8c54c2067bafc12ca7a55595d5ee9b75204a # # Third-party pin (resolve before bumping release/v1): # curl -sS "https://api.github.com/repos/pypa/gh-action-pypi-publish/commits/release/v1" | jq -r '.sha' @@ -80,18 +81,10 @@ jobs: with: python-version: ${{ env.PYTHON_VERSION }} - - name: Download frontend artifact - uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 + - name: Fetch frontend artifact + uses: ./.github/actions/fetch-frontend-artifact with: - name: ${{ env.FRONTEND_ARTIFACT_NAME }} - path: meshchatx/public - - - name: Verify frontend bundle in tree - run: | - set -euo pipefail - test -f meshchatx/public/index.html - test -d meshchatx/public/assets - test -d meshchatx/public/reticulum-docs-bundled/current + artifact-name: ${{ env.FRONTEND_ARTIFACT_NAME }} - name: Install build run: python -m pip install -U pip "build>=1.2.0" @@ -173,7 +166,7 @@ jobs: id-token: write contents: write actions: read - uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.1.0 + uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@f7dd8c54c2067bafc12ca7a55595d5ee9b75204a with: base64-subjects: ${{ needs.build.outputs.hashes }} upload-assets: false diff --git a/.github/workflows/security-scan.yml b/.github/workflows/security-scan.yml deleted file mode 100644 index bcfc2d94..00000000 --- a/.github/workflows/security-scan.yml +++ /dev/null @@ -1,91 +0,0 @@ -# Security scans migrated from .gitea/workflows/scan.yml. -# -# Pinned first-party actions (bump tag and SHA together when upgrading): -# actions/checkout@v6.0.1 8e8c483db84b4bee98b60c0593521ed34d9990e8 -# actions/setup-python@v6.2.0 a309ff8b426b58ec0e2a45f0f869d46889d02405 -# actions/setup-node@v6.1.0 395ad3262231945c25e8478fd5baf05154b1d79f -# actions/cache@v4.2.0 1bd1e32a3bdc45362d1e726936510720a7c30a57 - -# FIXME: CVE-2026-3219 affects pip through 26.0.1 waiting for next release to fix for now we ignore it - -name: Security scans - -on: - schedule: - - cron: "30 12 * * 1" - push: - branches: - - master - - dev - workflow_dispatch: - -permissions: - contents: read - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -env: - FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true - PYTHON_VERSION: "3.14" - NODE_VERSION: "24" - UV_VERSION: "0.11.15" - PNPM_VERSION: "11.1.2" - COSIGN_VERSION: "3.0.6" - # Official .deb; setup-trivy.sh verifies sigstore + SHA256 (see build-release.yml). - TRIVY_VERSION: "0.69.3" - -jobs: - scan: - runs-on: ubuntu-latest - timeout-minutes: 45 - permissions: - contents: read - steps: - - name: Checkout - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 - - - name: Set up Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 - with: - python-version: ${{ env.PYTHON_VERSION }} - - - name: Install UV (PyPI pin) - env: - UV_VERSION: ${{ env.UV_VERSION }} - run: bash scripts/ci/github-install-uv.sh - - - name: Cache UV downloads - uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 - with: - path: ~/.cache/uv - key: ${{ runner.os }}-uv-${{ hashFiles('uv.lock') }} - restore-keys: | - ${{ runner.os }}-uv- - - - name: Set up Node and pnpm - uses: ./.github/actions/setup-node-pnpm - with: - node-version: ${{ env.NODE_VERSION }} - pnpm-version: ${{ env.PNPM_VERSION }} - - - name: Install dependencies - run: bash scripts/ci/github-install-deps.sh - - - name: pip-audit - run: | - uv run pip install --upgrade "pip>=26.0" pip-audit - uv run pip-audit --ignore-vuln CVE-2026-3219 - - - name: Apt update (for Trivy .deb) - run: sh scripts/ci/exec-priv.sh apt-get update -qq - - - name: Setup Trivy - run: sh scripts/ci/setup-trivy.sh - - - name: Trivy filesystem scan (dependencies) - run: sh scripts/ci/trivy-fs-scan.sh - - - name: Trivy Dockerfile misconfiguration - run: trivy config --exit-code 1 Dockerfile diff --git a/.github/workflows/codeql.yml b/.github/workflows/security.yml similarity index 62% rename from .github/workflows/codeql.yml rename to .github/workflows/security.yml index d6418c89..4e0bdf2d 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/security.yml @@ -1,20 +1,26 @@ +# Dependency audits, filesystem/container config scans, and CodeQL analysis. +# # Pinned first-party actions (bump tag and SHA together when upgrading): # actions/checkout@v6.0.1 8e8c483db84b4bee98b60c0593521ed34d9990e8 -# actions/setup-python@v6.2.0 a309ff8b426b58ec0e2a45f0f869d46889d02405 -# actions/setup-node@v6.1.0 395ad3262231945c25e8478fd5baf05154b1d79f # actions/download-artifact@v5.0.0 634f93cb2916e3fdff6788551b99b062d0335ce0 # github/codeql-action/init@v4.31.6 95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # github/codeql-action/analyze@v4.31.6 95e58e9a2cdfd71adc6e0353d5c52f41a045d225 -# actions/cache@v4.2.0 1bd1e32a3bdc45362d1e726936510720a7c30a57 +# +# FIXME: CVE-2026-3219 affects pip through 26.0.1; ignored until next pip release. -name: "CodeQL Advanced" +name: Security on: push: - branches: ["master", "dev"] + branches: + - master + - dev pull_request: - branches: ["master", "dev"] + branches: + - master + - dev schedule: + - cron: "30 12 * * 1" - cron: "35 18 * * 3" workflow_dispatch: @@ -22,7 +28,7 @@ permissions: contents: read concurrency: - group: ${{ github.workflow }}-${{ github.ref }} + group: security-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} cancel-in-progress: true env: @@ -32,8 +38,44 @@ env: NODE_VERSION: "24" UV_VERSION: "0.11.15" PNPM_VERSION: "11.1.2" + TRIVY_VERSION: "0.69.3" jobs: + dependency-audit: + name: Dependency and config scan + runs-on: ubuntu-latest + timeout-minutes: 45 + permissions: + contents: read + steps: + - name: Checkout + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 + + - name: Set up development environment + uses: ./.github/actions/setup-dev-environment + with: + python-version: ${{ env.PYTHON_VERSION }} + uv-version: ${{ env.UV_VERSION }} + node-version: ${{ env.NODE_VERSION }} + pnpm-version: ${{ env.PNPM_VERSION }} + + - name: pip-audit + run: | + uv run pip install --upgrade "pip>=26.0" pip-audit + uv run pip-audit --ignore-vuln CVE-2026-3219 + + - name: Apt update (for Trivy .deb) + run: sh scripts/ci/exec-priv.sh apt-get update -qq + + - name: Setup Trivy + run: sh scripts/ci/setup-trivy.sh + + - name: Trivy filesystem scan (dependencies) + run: sh scripts/ci/trivy-fs-scan.sh + + - name: Trivy Dockerfile misconfiguration + run: trivy config --exit-code 1 Dockerfile + frontend: name: Build frontend artifact (CodeQL) uses: ./.github/workflows/frontend-build.yml @@ -43,16 +85,15 @@ jobs: artifact_name: meshchatx-frontend-codeql-${{ github.run_id }}-${{ github.run_attempt }} retention_days: 1 - analyze: - name: Analyze (${{ matrix.language }}) - runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }} + codeql: + name: CodeQL (${{ matrix.language }}) + runs-on: ubuntu-latest timeout-minutes: 360 permissions: security-events: write packages: read actions: read contents: read - strategy: fail-fast: false matrix: @@ -65,7 +106,6 @@ jobs: build-mode: none - language: python build-mode: none - steps: - name: Checkout repository uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 @@ -81,8 +121,8 @@ jobs: with: category: "/language:${{matrix.language}}" - analyze-javascript: - name: Analyze (javascript-typescript) + codeql-javascript: + name: CodeQL (javascript-typescript) runs-on: ubuntu-latest needs: [frontend] timeout-minutes: 360 @@ -98,45 +138,18 @@ jobs: - name: Checkout repository uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 - - name: Set up Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 + - name: Set up development environment + uses: ./.github/actions/setup-dev-environment with: python-version: ${{ env.PYTHON_VERSION }} - - - name: Install UV (PyPI pin) - env: - UV_VERSION: ${{ env.UV_VERSION }} - run: bash scripts/ci/github-install-uv.sh - - - name: Cache UV downloads - uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 - with: - path: ~/.cache/uv - key: ${{ runner.os }}-uv-${{ hashFiles('uv.lock') }} - restore-keys: | - ${{ runner.os }}-uv- - - - name: Set up Node and pnpm - uses: ./.github/actions/setup-node-pnpm - with: + uv-version: ${{ env.UV_VERSION }} node-version: ${{ env.NODE_VERSION }} pnpm-version: ${{ env.PNPM_VERSION }} - - name: Install dependencies - run: bash scripts/ci/github-install-deps.sh - - - name: Download frontend artifact - uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 + - name: Fetch frontend artifact + uses: ./.github/actions/fetch-frontend-artifact with: - name: ${{ env.FRONTEND_ARTIFACT_NAME }} - path: meshchatx/public - - - name: Verify frontend artifact contents - run: | - set -euo pipefail - test -f meshchatx/public/index.html - test -d meshchatx/public/assets - test -d meshchatx/public/reticulum-docs-bundled/current + artifact-name: ${{ env.FRONTEND_ARTIFACT_NAME }} - name: Initialize CodeQL uses: github/codeql-action/init@95e58e9a2cdfd71adc6e0353d5c52f41a045d225