Proyecto App Linux

This commit is contained in:
2026-05-03 23:43:09 +02:00
commit 7482733843
1248 changed files with 189750 additions and 0 deletions
+12
View File
@@ -0,0 +1,12 @@
# These are supported funding model platforms
github: [4gray]
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
custom: []
+35
View File
@@ -0,0 +1,35 @@
---
name: "\U0001F41E Bug report"
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Desktop (please complete the following information):**
- PWA or Electron/Tauri application
- OS: [e.g. Linux]
- Browser [e.g. chrome, safari]
- Version [e.g. 0.16.0]
- Feature: [e.g. M3U playlist, Xtream Code, Stalker Portal]
**Additional context**
Add any other context about the problem here.
@@ -0,0 +1,20 @@
---
name: "\U0001F680 Feature request"
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.
+420
View File
@@ -0,0 +1,420 @@
name: Build and Make Electron App
on:
push:
branches:
- master
tags:
- 'v*.*.*'
pull_request:
branches:
- master
workflow_dispatch:
jobs:
build:
name: Build on ${{ matrix.os }} ${{ matrix.arch }}
runs-on: ${{ matrix.runner }}
timeout-minutes: 60
strategy:
matrix:
include:
# macOS builds - separate runners to avoid native module conflicts
- os: macos
runner: macos-15-intel
arch: x64
- os: macos
runner: macos-latest
arch: arm64
# Linux and Windows
- os: linux
runner: ubuntu-22.04
linux_profile: standard
- os: linux
runner: ubuntu-24.04
linux_profile: flatpak
- os: windows
runner: windows-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install pnpm
uses: pnpm/action-setup@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '22'
cache: 'pnpm'
- name: Install Linux system dependencies
if: matrix.os == 'linux'
run: |
sudo apt-get update
sudo apt-get install --no-install-recommends -y rpm libarchive-tools flatpak flatpak-builder appstream
# Configure Flatpak
# 1. Add the Flathub repository (source of runtimes)
flatpak remote-add --if-not-exists --user flathub https://flathub.org/repo/flathub.flatpakrepo
# 2. Install the standard Freedesktop Platform and SDK (required by electron-builder)
# We install version 24.08 as a safe default, electron-builder might pick what it needs
flatpak install --user -y flathub org.freedesktop.Platform//24.08 org.freedesktop.Sdk//24.08
- name: Select Linux packaging targets for CI profile
if: matrix.os == 'linux'
run: |
node -e "
const fs = require('fs');
const path = 'electron-builder.json';
const config = JSON.parse(fs.readFileSync(path, 'utf8'));
const targets = Array.isArray(config.linux?.target) ? config.linux.target : [];
const profile = '${{ matrix.linux_profile }}';
if (profile === 'standard') {
config.linux.target = targets.filter((entry) => String(entry.target).toLowerCase() !== 'flatpak');
} else if (profile === 'flatpak') {
config.linux.target = targets.filter((entry) => String(entry.target).toLowerCase() === 'flatpak');
}
fs.writeFileSync(path, JSON.stringify(config, null, 4) + '\n');
"
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Build frontend
run: pnpm nx build web --skip-nx-cache
- name: Build backend
run: pnpm run build:backend
- name: Validate AppStream metadata
if: matrix.os == 'linux'
run: appstreamcli validate --pedantic --no-net apps/electron-backend/linux/com.fourgray.iptvnator.metainfo.xml
- name: Build website
if: matrix.os == 'linux'
run: pnpm nx build website --skip-nx-cache
- name: Verify AppStream website assets
if: matrix.os == 'linux'
shell: bash
run: |
set -euo pipefail
for screenshot in player playlists epg settings; do
if ! find dist/apps/website -path "*/appstream/${screenshot}.png" -print -quit | grep -q .; then
echo "::error::Missing AppStream website asset for ${screenshot}.png"
exit 1
fi
done
- name: Override macOS arch in electron-builder.json
if: matrix.os == 'macos'
run: |
# Replace the mac arch array with just the target architecture
node -e "
const fs = require('fs');
const pkg = JSON.parse(fs.readFileSync('electron-builder.json', 'utf8'));
pkg.mac.target.arch = ['${{ matrix.arch }}'];
fs.writeFileSync('electron-builder.json', JSON.stringify(pkg, null, 4));
"
- name: Validate macOS signing configuration
if: matrix.os == 'macos' && github.event_name != 'pull_request'
shell: bash
env:
CSC_NAME: ${{ vars.CSC_NAME }}
CSC_LINK: ${{ secrets.CSC_LINK }}
CSC_KEY_PASSWORD: ${{ secrets.CSC_KEY_PASSWORD }}
APPLE_API_KEY_CONTENT: ${{ secrets.APPLE_API_KEY }}
APPLE_API_KEY_ID: ${{ secrets.APPLE_API_KEY_ID }}
APPLE_API_ISSUER: ${{ secrets.APPLE_API_ISSUER }}
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
run: |
if [ -z "${CSC_NAME}" ]; then
echo "::error::Missing CSC_NAME repository variable for deterministic macOS code signing."
exit 1
fi
if [ -z "${CSC_LINK}" ] || [ -z "${CSC_KEY_PASSWORD}" ]; then
echo "::error::Missing CSC_LINK or CSC_KEY_PASSWORD secret for macOS code signing."
exit 1
fi
has_api_key_credentials=false
if [ -n "${APPLE_API_KEY_CONTENT}" ] || [ -n "${APPLE_API_KEY_ID}" ] || [ -n "${APPLE_API_ISSUER}" ]; then
if [ -z "${APPLE_API_KEY_CONTENT}" ] || [ -z "${APPLE_API_KEY_ID}" ] || [ -z "${APPLE_API_ISSUER}" ]; then
echo "::error::APPLE_API_KEY, APPLE_API_KEY_ID, and APPLE_API_ISSUER must all be set for App Store Connect API key notarization."
exit 1
fi
has_api_key_credentials=true
fi
has_apple_id_credentials=false
if [ -n "${APPLE_ID}" ] || [ -n "${APPLE_APP_SPECIFIC_PASSWORD}" ] || [ -n "${APPLE_TEAM_ID}" ]; then
if [ -z "${APPLE_ID}" ] || [ -z "${APPLE_APP_SPECIFIC_PASSWORD}" ] || [ -z "${APPLE_TEAM_ID}" ]; then
echo "::error::APPLE_ID, APPLE_APP_SPECIFIC_PASSWORD, and APPLE_TEAM_ID must all be set for Apple ID notarization."
exit 1
fi
has_apple_id_credentials=true
fi
if [ "${has_api_key_credentials}" = false ] && [ "${has_apple_id_credentials}" = false ]; then
echo "::error::Missing notarization credentials. Configure either APPLE_API_KEY + APPLE_API_KEY_ID + APPLE_API_ISSUER, or APPLE_ID + APPLE_APP_SPECIFIC_PASSWORD + APPLE_TEAM_ID."
exit 1
fi
- name: Prepare macOS notarization credentials
if: matrix.os == 'macos' && github.event_name != 'pull_request'
shell: bash
env:
APPLE_API_KEY_CONTENT: ${{ secrets.APPLE_API_KEY }}
APPLE_API_KEY_ID: ${{ secrets.APPLE_API_KEY_ID }}
APPLE_API_ISSUER: ${{ secrets.APPLE_API_ISSUER }}
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
run: |
if [ -n "${APPLE_API_KEY_CONTENT}" ]; then
APPLE_API_KEY_PATH="${RUNNER_TEMP}/AuthKey_${APPLE_API_KEY_ID}.p8"
printf '%s' "${APPLE_API_KEY_CONTENT}" > "${APPLE_API_KEY_PATH}"
chmod 600 "${APPLE_API_KEY_PATH}"
echo "APPLE_API_KEY=${APPLE_API_KEY_PATH}" >> "${GITHUB_ENV}"
echo "APPLE_API_KEY_ID=${APPLE_API_KEY_ID}" >> "${GITHUB_ENV}"
echo "APPLE_API_ISSUER=${APPLE_API_ISSUER}" >> "${GITHUB_ENV}"
echo "APPLE_ID=" >> "${GITHUB_ENV}"
echo "APPLE_APP_SPECIFIC_PASSWORD=" >> "${GITHUB_ENV}"
echo "APPLE_TEAM_ID=" >> "${GITHUB_ENV}"
exit 0
fi
if [ -n "${APPLE_ID}" ]; then
echo "APPLE_API_KEY=" >> "${GITHUB_ENV}"
echo "APPLE_API_KEY_ID=" >> "${GITHUB_ENV}"
echo "APPLE_API_ISSUER=" >> "${GITHUB_ENV}"
echo "APPLE_ID=${APPLE_ID}" >> "${GITHUB_ENV}"
echo "APPLE_APP_SPECIFIC_PASSWORD=${APPLE_APP_SPECIFIC_PASSWORD}" >> "${GITHUB_ENV}"
echo "APPLE_TEAM_ID=${APPLE_TEAM_ID}" >> "${GITHUB_ENV}"
fi
- name: Make Electron app (macOS)
if: matrix.os == 'macos' && github.event_name != 'pull_request'
env:
CSC_NAME: ${{ vars.CSC_NAME }}
CSC_LINK: ${{ secrets.CSC_LINK }}
CSC_KEY_PASSWORD: ${{ secrets.CSC_KEY_PASSWORD }}
DEBUG: electron-builder,electron-notarize*
run: pnpm run make:app
- name: Verify signed macOS app
if: matrix.os == 'macos' && github.event_name != 'pull_request'
shell: bash
run: |
set -euo pipefail
case "${{ matrix.arch }}" in
x64)
APP_PATH="dist/executables/mac/IPTVnator.app"
;;
arm64)
APP_PATH="dist/executables/mac-arm64/IPTVnator.app"
;;
*)
echo "::error::Unsupported macOS arch: ${{ matrix.arch }}"
exit 1
;;
esac
print_debug_attrs() {
echo "::group::Extended attributes"
xattr -lr "${APP_PATH}" | sed -n '1,120p' || true
echo "::endgroup::"
}
trap print_debug_attrs ERR
if [ ! -d "${APP_PATH}" ]; then
echo "::error::Expected app bundle not found at ${APP_PATH}"
exit 1
fi
SIGNATURE_INFO="$(codesign -dv --verbose=4 "${APP_PATH}" 2>&1)"
printf '%s\n' "${SIGNATURE_INFO}"
if printf '%s\n' "${SIGNATURE_INFO}" | grep -q 'Signature=adhoc'; then
echo "::error::macOS app is still ad-hoc signed."
exit 1
fi
if printf '%s\n' "${SIGNATURE_INFO}" | grep -q 'TeamIdentifier=not set'; then
echo "::error::macOS app is missing a TeamIdentifier."
exit 1
fi
codesign --verify --deep --strict --verbose=4 "${APP_PATH}"
spctl -a -vvv --type execute "${APP_PATH}"
xcrun stapler validate "${APP_PATH}"
- name: Make Electron app
if: matrix.os != 'macos' || github.event_name == 'pull_request'
run: pnpm run make:app
- name: Verify packaged worker layout
shell: bash
env:
PACKAGE_OS: ${{ matrix.os }}
PACKAGE_ARCH: ${{ matrix.arch || '' }}
run: pnpm run verify:package-layout -- "$PACKAGE_OS" "$PACKAGE_ARCH"
- name: Smoke test packaged Flatpak launcher
if: matrix.os == 'linux' && matrix.linux_profile == 'flatpak'
shell: bash
run: |
set -euo pipefail
FLATPAK_BUNDLE="$(find dist/executables -maxdepth 1 -name '*.flatpak' | head -n 1)"
if [ -z "${FLATPAK_BUNDLE}" ]; then
echo "::error::Flatpak bundle not found in dist/executables"
exit 1
fi
flatpak install --user --noninteractive -y "${FLATPAK_BUNDLE}"
flatpak run --command=sh com.fourgray.iptvnator -c '
set -euo pipefail
test -f /app/share/metainfo/com.fourgray.iptvnator.metainfo.xml
test -L /app/bin/iptvnator
LAUNCHER_PATH="$(readlink -f /app/bin/iptvnator)"
test -f "${LAUNCHER_PATH}"
test -f "${LAUNCHER_PATH}.bin"
grep -q '\''readlink -f "$SCRIPT_PATH"'\'' "${LAUNCHER_PATH}"
grep -q '\''exec "$SCRIPT_DIR/iptvnator.bin"'\'' "${LAUNCHER_PATH}"
'
- name: Upload artifacts (macOS)
if: matrix.os == 'macos'
uses: actions/upload-artifact@v4
with:
name: macos-${{ matrix.arch }}-artifacts
path: |
dist/executables/**/*.dmg
dist/executables/**/*.zip
retention-days: 7
- name: Upload artifacts (Linux)
if: matrix.os == 'linux' && matrix.linux_profile == 'standard'
uses: actions/upload-artifact@v4
with:
name: linux-artifacts
path: |
dist/executables/**/*.deb
dist/executables/**/*.rpm
dist/executables/**/*.snap
dist/executables/**/*.AppImage
dist/executables/**/*.tar.gz
dist/executables/**/*.pacman
retention-days: 7
- name: Upload artifacts (Flatpak)
if: matrix.os == 'linux' && matrix.linux_profile == 'flatpak'
uses: actions/upload-artifact@v4
with:
name: linux-flatpak-artifacts
path: |
dist/executables/**/*.flatpak
retention-days: 7
- name: Upload artifacts (Windows)
if: matrix.os == 'windows'
uses: actions/upload-artifact@v4
with:
name: windows-artifacts
path: |
dist/executables/**/*.exe
dist/executables/**/*.msi
dist/executables/**/*.zip
retention-days: 7
create-release:
name: Create Draft Release
needs: build
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: artifacts
- name: Display structure of downloaded files
run: ls -R artifacts
- name: Get version from package.json
id: package-version
run: echo "version=$(node -p "require('./package.json').version")" >> $GITHUB_OUTPUT
- name: Create Draft Release
uses: softprops/action-gh-release@v2
with:
draft: true
prerelease: ${{ github.event_name == 'pull_request' }}
name: Release v${{ steps.package-version.outputs.version }}
tag_name: ${{ startsWith(github.ref, 'refs/tags/') && github.ref_name || format('test-{0}', github.sha) }}
generate_release_notes: true
files: |
artifacts/macos-x64-artifacts/*-x64.dmg
artifacts/macos-x64-artifacts/*-x64.zip
artifacts/macos-arm64-artifacts/*-arm64.dmg
artifacts/macos-arm64-artifacts/*-arm64.zip
artifacts/linux-artifacts/*.AppImage
artifacts/linux-artifacts/*.deb
artifacts/linux-artifacts/*.rpm
artifacts/linux-artifacts/*.snap
artifacts/linux-artifacts/*.tar.gz
artifacts/linux-artifacts/*.pacman
artifacts/linux-flatpak-artifacts/*.flatpak
artifacts/windows-artifacts/*-setup.exe
artifacts/windows-artifacts/*.msi
artifacts/windows-artifacts/*.zip
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
publish-snap:
name: Publish to Snapcraft Store
needs: build
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/v')
env:
SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.snapcraft_token }}
steps:
- name: Download snap artifact
uses: actions/download-artifact@v4
with:
name: linux-artifacts
path: artifacts
- name: Setup Snapcraft
uses: samuelmeuli/action-snapcraft@v3
- name: Publish all snaps to edge channel
run: |
# Find and publish all snap files
for SNAP_FILE in artifacts/*.snap; do
if [ -f "$SNAP_FILE" ]; then
echo "Publishing: $SNAP_FILE"
snapcraft upload --release=edge "$SNAP_FILE"
fi
done
+41
View File
@@ -0,0 +1,41 @@
name: CI
on:
push:
branches:
- master
pull_request:
branches:
- master
workflow_dispatch:
jobs:
unit-and-typecheck:
name: Unit Tests and Typechecks
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install pnpm
uses: pnpm/action-setup@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '22'
cache: 'pnpm'
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Typecheck web and Electron entry points
run: pnpm run typecheck:ci
- name: Run curated Nx unit test suite
run: pnpm run test:unit:ci
env:
CI: true
NX_TASKS_RUNNER_DYNAMIC_OUTPUT: false
+71
View File
@@ -0,0 +1,71 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
name: "CodeQL"
on:
push:
branches: [master]
pull_request:
# The branches below must be a subset of the branches above
branches: [master]
schedule:
- cron: '0 20 * * 3'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
# Override automatic language detection by changing the below list
# Supported options are ['csharp', 'cpp', 'go', 'java', 'javascript', 'python']
language: ['javascript']
# Learn more...
# https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#overriding-automatic-language-detection
steps:
- name: Checkout repository
uses: actions/checkout@v3
with:
# We must fetch at least the immediate parents so that if this is
# a pull request then we can checkout the head.
fetch-depth: 2
# If this run was triggered by a pull request event, then checkout
# the head of the pull request instead of the merge commit.
- run: git checkout HEAD^2
if: ${{ github.event_name == 'pull_request' }}
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v3
# ℹ️ Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
+59
View File
@@ -0,0 +1,59 @@
name: Deploy Website to GitHub Pages
on:
push:
branches:
- master
paths:
- 'apps/website/**'
- '.github/workflows/deploy-website.yml'
workflow_dispatch:
permissions:
contents: read
pages: write
id-token: write
concurrency:
group: 'pages'
cancel-in-progress: true
jobs:
build:
name: Build Website
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install pnpm
uses: pnpm/action-setup@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '22'
cache: 'pnpm'
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Build website
run: pnpm nx build website
- name: Upload Pages artifact
uses: actions/upload-pages-artifact@v3
with:
path: dist/apps/website
deploy:
name: Deploy to GitHub Pages
needs: build
runs-on: ubuntu-latest
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
+39
View File
@@ -0,0 +1,39 @@
name: docker-build
on: [workflow_dispatch]
jobs:
build:
runs-on: ubuntu-latest
steps:
-
name: Checkout
uses: actions/checkout@v3
-
name: Install jq
run: sudo apt-get update && sudo apt-get install -y jq
-
name: Get version from package.json
id: package-version
run: echo "VERSION=$(cat package.json | jq -r .version)" >> $GITHUB_OUTPUT
-
name: Login to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
-
name: Build and push
uses: docker/build-push-action@v4
with:
context: .
file: ./docker/Dockerfile
push: true
tags: |
4gray/iptvnator:latest
4gray/iptvnator:${{ github.sha }}
4gray/iptvnator:${{ steps.package-version.outputs.VERSION }}
platforms: linux/amd64,linux/arm64
+98
View File
@@ -0,0 +1,98 @@
name: 'Cross-Platform E2E Tests'
on:
push:
branches:
- master
pull_request:
branches:
- master
jobs:
electron-e2e-tests:
name: Electron E2E on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
env:
NX_SKIP_NX_CACHE: true
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
steps:
- uses: actions/checkout@v4
- name: Install pnpm
uses: pnpm/action-setup@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '22'
cache: 'pnpm'
- name: Install Dependencies
run: pnpm install --frozen-lockfile
- name: Build Backend
run: pnpm nx build electron-backend
- name: Install Playwright Browsers
run: pnpm exec playwright install --with-deps
- name: Run Electron E2E Tests (Linux)
if: runner.os == 'Linux'
run: xvfb-run --auto-servernum --server-args="-screen 0 1280x960x24" pnpm nx run electron-backend-e2e:e2e
env:
CI: true
- name: Run Electron E2E Tests (Windows/Mac)
if: runner.os != 'Linux'
run: pnpm nx run electron-backend-e2e:e2e
env:
CI: true
- name: Upload Electron Test Results
if: failure()
uses: actions/upload-artifact@v4
with:
name: playwright-report-electron-${{ matrix.os }}
path: dist/playwright-report/electron-backend-e2e/
retention-days: 7
web-e2e-tests:
name: Web E2E on Ubuntu Chromium
runs-on: ubuntu-latest
env:
NX_SKIP_NX_CACHE: true
steps:
- uses: actions/checkout@v4
- name: Install pnpm
uses: pnpm/action-setup@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '22'
cache: 'pnpm'
- name: Install Dependencies
run: pnpm install --frozen-lockfile
- name: Install Chromium
run: pnpm exec playwright install --with-deps chromium
- name: Run Web E2E Tests
run: pnpm nx run web-e2e:e2e -- --project=chromium
env:
CI: true
- name: Upload Web Test Results
if: failure()
uses: actions/upload-artifact@v4
with:
name: playwright-report-web-ubuntu
path: dist/.playwright/apps/web-e2e/playwright-report/
retention-days: 7