Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
336 changes: 336 additions & 0 deletions .gitverse/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,336 @@
name: CI (Gitverse mirror)

on:
pull_request:
push:
branches:
- main
workflow_dispatch:

permissions:
contents: read

jobs:
license:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4

- name: License validator
uses: ./.github/actions/license

lint:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4

- name: ESLint
uses: ./.github/actions/eslint

- name: Stylelint
uses: ./.github/actions/stylelint

typescript:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Detect TypeScript-impacting changes
id: typescript_changes
env:
BASE_SHA: ${{ github.event.pull_request.base.sha || github.event.before }}
HEAD_SHA: ${{ github.event.pull_request.head.sha || github.sha }}
run: |
if [ -z "$BASE_SHA" ] || printf '%s\n' "$BASE_SHA" | grep -Eq '^0+$'; then
echo "run_typescript=true" >> "$GITHUB_OUTPUT"
exit 0
fi

changed_files="$(git diff --name-only "$BASE_SHA" "$HEAD_SHA")"
printf '%s\n' "$changed_files"

if printf '%s\n' "$changed_files" | grep -Eq '^(src/|package\.json$|pnpm-lock\.yaml$|tsconfig\.json$|vite\.config\.ts$|vitest\.config\.ts$|\.github/actions/typescript/)'; then
echo "run_typescript=true" >> "$GITHUB_OUTPUT"
else
echo "run_typescript=false" >> "$GITHUB_OUTPUT"
fi

- name: Skip TypeScript
if: steps.typescript_changes.outputs.run_typescript != 'true'
run: echo "Skipping TypeScript because this change does not affect TypeScript inputs."

- name: TypeScript
if: steps.typescript_changes.outputs.run_typescript == 'true'
uses: ./.github/actions/typescript

unit-tests:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Detect unit-test-impacting changes
id: unit_changes
env:
BASE_SHA: ${{ github.event.pull_request.base.sha || github.event.before }}
HEAD_SHA: ${{ github.event.pull_request.head.sha || github.sha }}
run: |
if [ -z "$BASE_SHA" ] || printf '%s\n' "$BASE_SHA" | grep -Eq '^0+$'; then
echo "run_unit_tests=true" >> "$GITHUB_OUTPUT"
exit 0
fi

changed_files="$(git diff --name-only "$BASE_SHA" "$HEAD_SHA")"
printf '%s\n' "$changed_files"

if printf '%s\n' "$changed_files" | grep -Eq '^(src/|tests/|package\.json$|pnpm-lock\.yaml$|tsconfig\.json$|vite\.config\.ts$|vitest\.config\.ts$)'; then
echo "run_unit_tests=true" >> "$GITHUB_OUTPUT"
else
echo "run_unit_tests=false" >> "$GITHUB_OUTPUT"
fi

- name: Skip unit tests
if: steps.unit_changes.outputs.run_unit_tests != 'true'
run: echo "Skipping unit tests because this change does not affect unit-test inputs."

- name: Setup pnpm
if: steps.unit_changes.outputs.run_unit_tests == 'true'
uses: pnpm/action-setup@v2
with:
version: 10.10.0

- name: Install dependencies
if: steps.unit_changes.outputs.run_unit_tests == 'true'
run: pnpm install --frozen-lockfile

- name: Run unit tests
if: steps.unit_changes.outputs.run_unit_tests == 'true'
run: pnpm test:unit

- name: Archive test results
if: always() && steps.unit_changes.outputs.run_unit_tests == 'true'
uses: actions/upload-artifact@v4
with:
name: test-results
path: reports/unit/
retention-days: 5

build:
needs: [license, lint, typescript, unit-tests]
runs-on: ubuntu-latest
outputs:
head_sha: ${{ steps.set_build_metadata.outputs.head_sha }}
short_sha: ${{ steps.set_build_metadata.outputs.short_sha }}
chrome_artifact: ${{ steps.set_build_metadata.outputs.chrome_artifact }}
firefox_artifact: ${{ steps.set_build_metadata.outputs.firefox_artifact }}
firefox_sources_artifact: ${{ steps.set_build_metadata.outputs.firefox_sources_artifact }}
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup pnpm
uses: pnpm/action-setup@v2
with:
version: 10.10.0

- name: Install dependencies
run: pnpm install --frozen-lockfile

- name: Set build metadata
id: set_build_metadata
env:
HEAD_SHA: ${{ github.event.pull_request.head.sha || github.sha }}
run: |
SHORT_SHA="$(echo "$HEAD_SHA" | cut -c1-7)"

echo "head_sha=$HEAD_SHA" >> "$GITHUB_OUTPUT"
echo "short_sha=$SHORT_SHA" >> "$GITHUB_OUTPUT"
echo "chrome_artifact=cloudhood-chrome-$HEAD_SHA" >> "$GITHUB_OUTPUT"
echo "firefox_artifact=cloudhood-firefox-$HEAD_SHA" >> "$GITHUB_OUTPUT"
echo "firefox_sources_artifact=cloudhood-firefox-sources-$HEAD_SHA" >> "$GITHUB_OUTPUT"

- name: Build Chrome extension
run: pnpm build:chromium

- name: Check Chrome build
run: pnpm check:chrome-build

- name: Pack Chrome extension
run: |
cd build/chrome
zip -r ../../cloudhood-chrome-${{ steps.set_build_metadata.outputs.short_sha }}.zip .

- name: Build Firefox extension
env:
FIREFOX_EXTENSION_ID: ${{ vars.FIREFOX_EXTENSION_ID }}
run: pnpm build:firefox

- name: Check Firefox build
env:
FIREFOX_EXTENSION_ID: ${{ vars.FIREFOX_EXTENSION_ID }}
run: pnpm check:firefox-build

- name: Pack Firefox extension
run: |
cd build/firefox
zip -r ../../cloudhood-firefox-${{ steps.set_build_metadata.outputs.short_sha }}.zip .

- name: Build Firefox sources archive
run: pnpm build:firefox-sources

- name: Rename Firefox sources archive
run: mv cloudhood-firefox-sources.zip cloudhood-firefox-sources-${{ steps.set_build_metadata.outputs.short_sha }}.zip

- name: Upload Chrome build artifact
uses: actions/upload-artifact@v4
with:
name: ${{ steps.set_build_metadata.outputs.chrome_artifact }}
path: cloudhood-chrome-${{ steps.set_build_metadata.outputs.short_sha }}.zip
retention-days: 14

- name: Upload Firefox build artifact
uses: actions/upload-artifact@v4
with:
name: ${{ steps.set_build_metadata.outputs.firefox_artifact }}
path: cloudhood-firefox-${{ steps.set_build_metadata.outputs.short_sha }}.zip
retention-days: 14

- name: Upload Firefox sources artifact
uses: actions/upload-artifact@v4
with:
name: ${{ steps.set_build_metadata.outputs.firefox_sources_artifact }}
path: cloudhood-firefox-sources-${{ steps.set_build_metadata.outputs.short_sha }}.zip
retention-days: 14

e2e-test:
runs-on: ubuntu-latest
needs: [build]
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Detect E2E-impacting changes
id: e2e_changes
env:
BASE_SHA: ${{ github.event.pull_request.base.sha || github.event.before }}
HEAD_SHA: ${{ github.event.pull_request.head.sha || github.sha }}
run: |
if [ -z "$BASE_SHA" ] || printf '%s\n' "$BASE_SHA" | grep -Eq '^0+$'; then
echo "run_e2e=true" >> "$GITHUB_OUTPUT"
exit 0
fi

changed_files="$(git diff --name-only "$BASE_SHA" "$HEAD_SHA")"
printf '%s\n' "$changed_files"

if printf '%s\n' "$changed_files" | grep -Eq '^(src/|tests/e2e/|docker/|docker-compose\.screenshots\.yml$|manifest\.(chromium|firefox)\.json$|package\.json$|pnpm-lock\.yaml$|playwright\.config\.ts$|vite(\.background)?\.config\.ts$|scripts/(firefox-e2e|firefox-screenshots|lib/))'; then
echo "run_e2e=true" >> "$GITHUB_OUTPUT"
else
echo "run_e2e=false" >> "$GITHUB_OUTPUT"
fi

- name: Skip E2E tests
if: steps.e2e_changes.outputs.run_e2e != 'true'
run: echo "Skipping extension E2E tests because this change does not affect extension runtime, E2E, or screenshot inputs."

- name: Setup pnpm
if: steps.e2e_changes.outputs.run_e2e == 'true'
uses: pnpm/action-setup@v2
with:
version: 10.10.0

- name: Setup Node
if: steps.e2e_changes.outputs.run_e2e == 'true'
uses: actions/setup-node@v6
with:
node-version: 20
cache: pnpm

- name: Install dependencies
if: steps.e2e_changes.outputs.run_e2e == 'true'
run: pnpm install --frozen-lockfile

- name: Download Chrome build artifact
if: steps.e2e_changes.outputs.run_e2e == 'true'
uses: actions/download-artifact@v4
with:
name: ${{ needs.build.outputs.chrome_artifact }}

- name: Extract Chrome extension
if: steps.e2e_changes.outputs.run_e2e == 'true'
run: |
mkdir -p build/chrome
unzip -o cloudhood-chrome-${{ needs.build.outputs.short_sha }}.zip -d build/chrome

- name: Download Firefox build artifact
if: steps.e2e_changes.outputs.run_e2e == 'true'
uses: actions/download-artifact@v4
with:
name: ${{ needs.build.outputs.firefox_artifact }}

- name: Extract Firefox extension
if: steps.e2e_changes.outputs.run_e2e == 'true'
run: |
mkdir -p build/firefox
unzip -o cloudhood-firefox-${{ needs.build.outputs.short_sha }}.zip -d build/firefox

- name: Build Playwright screenshot image
if: steps.e2e_changes.outputs.run_e2e == 'true'
run: docker compose -f docker-compose.screenshots.yml build screenshots

- name: Run functional E2E tests in container
if: steps.e2e_changes.outputs.run_e2e == 'true'
run: docker compose -f docker-compose.screenshots.yml run --rm screenshots sh -lc "pnpm install --frozen-lockfile && pnpm test:e2e:ci"

- name: Run Firefox functional E2E tests in container
if: steps.e2e_changes.outputs.run_e2e == 'true'
run: docker compose -f docker-compose.screenshots.yml run --rm screenshots sh -lc "pnpm install --frozen-lockfile && pnpm test:e2e:firefox"

- name: Run screenshot tests in container
if: steps.e2e_changes.outputs.run_e2e == 'true'
run: docker compose -f docker-compose.screenshots.yml run --rm screenshots sh -lc "pnpm install --frozen-lockfile && pnpm build && pnpm test:e2e:screenshots"

validate-build-artifacts:
needs: [build, e2e-test]
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Download Chrome build artifact
uses: actions/download-artifact@v4
with:
name: ${{ needs.build.outputs.chrome_artifact }}
path: dist/chrome

- name: Download Firefox build artifact
uses: actions/download-artifact@v4
with:
name: ${{ needs.build.outputs.firefox_artifact }}
path: dist/firefox

- name: Download Firefox sources artifact
uses: actions/download-artifact@v4
with:
name: ${{ needs.build.outputs.firefox_sources_artifact }}
path: dist/firefox-sources

- name: Extract builds for release checks
run: |
mkdir -p build/chrome build/firefox
unzip -o dist/chrome/cloudhood-chrome-${{ needs.build.outputs.short_sha }}.zip -d build/chrome
unzip -o dist/firefox/cloudhood-firefox-${{ needs.build.outputs.short_sha }}.zip -d build/firefox

- name: Check release builds
env:
FIREFOX_EXTENSION_ID: ${{ vars.FIREFOX_EXTENSION_ID }}
run: node scripts/check-extension-builds.mjs
Loading
Loading