diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..3aa2470 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,7 @@ +* +!Containerfile +!package.json +!yarn.lock +!.yarnrc.yml +!.yarn/releases/ +!.yarn/releases/** diff --git a/.github/actions/package-extension/action.yml b/.github/actions/package-extension/action.yml deleted file mode 100644 index 9507cad..0000000 --- a/.github/actions/package-extension/action.yml +++ /dev/null @@ -1,33 +0,0 @@ -name: Package Extension -description: Install system dependencies, setup Yarn, and package the extension ZIP. - -inputs: - node-version: - description: Node.js version to install. - required: false - default: '22' - apt-packages: - description: Ubuntu packages needed to build the extension. - required: false - default: gettext zip gnome-shell python3-gi gir1.2-glib-2.0 - -runs: - using: composite - steps: - - name: Install just - uses: extractions/setup-just@v4 - - - name: Install system dependencies - shell: bash - run: | - sudo apt-get update - sudo apt-get install -y ${{ inputs.apt-packages }} - - - name: Setup Yarn - uses: ./.github/actions/setup-yarn - with: - node-version: ${{ inputs.node-version }} - - - name: Build extension zip - shell: bash - run: just package diff --git a/.github/actions/setup-yarn/action.yml b/.github/actions/setup-yarn/action.yml deleted file mode 100644 index e74c28e..0000000 --- a/.github/actions/setup-yarn/action.yml +++ /dev/null @@ -1,25 +0,0 @@ -name: Setup Yarn -description: Enable Corepack, setup Node.js, and install Yarn dependencies. - -inputs: - node-version: - description: Node.js version to install. - required: false - default: '22' - -runs: - using: composite - steps: - - name: Enable Corepack - shell: bash - run: corepack enable - - - name: Setup Node.js - uses: actions/setup-node@v6 - with: - node-version: ${{ inputs.node-version }} - cache: yarn - - - name: Install dependencies - shell: bash - run: yarn install --immutable diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 34a9a96..9544b39 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,22 +5,76 @@ on: merge_group: workflow_call: +permissions: + contents: read + packages: write + concurrency: group: ci-${{ github.ref }} cancel-in-progress: true jobs: + ci-image: + name: CI image + runs-on: ubuntu-latest + outputs: + name: ${{ steps.image.outputs.name }} + steps: + - uses: actions/checkout@v7 + + - name: Log in to GHCR + uses: docker/login-action@v4 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Resolve CI image + id: image + run: | + IMAGE="$(bash scripts/ci-image-name.sh)" + echo "name=$IMAGE" >> "$GITHUB_OUTPUT" + + if docker manifest inspect "$IMAGE" >/dev/null 2>&1; then + echo "exists=true" >> "$GITHUB_OUTPUT" + else + echo "exists=false" >> "$GITHUB_OUTPUT" + fi + + - uses: docker/setup-qemu-action@v4 + if: steps.image.outputs.exists != 'true' + + - uses: docker/setup-buildx-action@v4 + if: steps.image.outputs.exists != 'true' + + - name: Build and publish CI image + if: steps.image.outputs.exists != 'true' + uses: docker/build-push-action@v7 + with: + context: . + file: Containerfile + platforms: linux/amd64,linux/arm64 + push: true + tags: | + ${{ steps.image.outputs.name }} + ghcr.io/luminusos/aurora-shell-ci:sha-${{ github.sha }} + cache-from: type=gha + cache-to: type=gha,mode=max + lint: name: Validate runs-on: ubuntu-latest + needs: [ci-image] + container: + image: ${{ needs.ci-image.outputs.name }} + credentials: + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} steps: - uses: actions/checkout@v7 - - name: Setup Yarn - uses: ./.github/actions/setup-yarn - - - name: Install just - uses: extractions/setup-just@v4 + - name: Install dependencies + run: just deps - name: Validate run: just validate @@ -28,116 +82,79 @@ jobs: unit-tests: name: Unit & regression tests runs-on: ubuntu-latest + needs: [ci-image] + container: + image: ${{ needs.ci-image.outputs.name }} + credentials: + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} steps: - uses: actions/checkout@v7 - - name: Setup Yarn - uses: ./.github/actions/setup-yarn + - name: Install dependencies + run: just deps - name: Run unit tests - run: yarn test:unit + run: just unit-test build: name: Build runs-on: ubuntu-latest - needs: [lint] + needs: [ci-image, lint] + container: + image: ${{ needs.ci-image.outputs.name }} + credentials: + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} steps: - uses: actions/checkout@v7 - - name: Package extension - uses: ./.github/actions/package-extension + - name: Install dependencies + run: just deps + + - name: Build extension package + run: just package - name: Upload extension zip - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: extension-zip path: dist/target/aurora-shell@luminusos.github.io.shell-extension.zip retention-days: 1 integration-tests: - name: Integration tests (GNOME ${{ matrix.gnome-version }}) + name: Integration tests runs-on: ubuntu-latest - needs: [build, unit-tests] - strategy: - fail-fast: false - matrix: - include: - - gnome-version: '50' - container: 'fedora:44' + needs: [ci-image, build, unit-tests] container: - image: ${{ matrix.container }} + image: ${{ needs.ci-image.outputs.name }} + credentials: + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} options: --privileged steps: - uses: actions/checkout@v7 - name: Download extension zip - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v8 with: name: extension-zip path: dist/target/ - - name: Install gnome-shell and test dependencies - run: | - dnf upgrade -y - dnf install -y --setopt=install_weak_deps=False \ - gnome-shell \ - dbus-daemon \ - mesa-dri-drivers \ - xorg-x11-server-Xvfb \ - python3-dbusmock - - name: Run integration tests env: + DISPLAY: ':0' + GDK_DEBUG: no-portals LIBGL_ALWAYS_SOFTWARE: '1' + WAYLAND_DISPLAY: gnome-shell-test-display XDG_RUNTIME_DIR: /tmp/xdg-runtime - DISPLAY: ':0' - WAYLAND_DISPLAY: 'gnome-shell-test-display' - # gnome-shell-perf-helper is a GTK4 app that times out (~25 s) trying - # to reach org.freedesktop.host.portal.Registry, which is not - # available in a headless test environment. no-portals skips that - # lookup so the helper connects directly to the Wayland display and - # can exit gnome-shell cleanly. - GDK_DEBUG: 'no-portals' run: | - mkdir -p /tmp/xdg-runtime - chmod 700 /tmp/xdg-runtime - - # Start a system D-Bus so GNOME Shell can reach Gio.DBus.system. + install -d -m 0700 "$XDG_RUNTIME_DIR" mkdir -p /run/dbus dbus-daemon --system --fork --nopidfile - - # Mock org.freedesktop.login1 on the system bus. GNOME Shell 50's - # LoginManagerSystemd and EndSessionDialog create a proxy for this - # name synchronously at startup; without it the session crashes with - # "Launch helper exited with unknown return code 1". python3 -m dbusmock --system --template logind & + logind_pid=$! + trap 'kill "$logind_pid" 2>/dev/null || true' EXIT sleep 1 - - PASS=0; FAIL=0 - for script in tests/shell/aurora*.js; do - echo "==> $script" - # dbus-update-activation-environment pushes display vars into the - # session bus daemon so that D-Bus-activated services (e.g. - # xdg-desktop-portal-gtk) inherit them and can connect to the - # Wayland compositor. GDK_DEBUG=no-portals is also propagated so - # that gnome-shell-perf-helper (GTK4) skips the portal registry - # lookup that would otherwise time out in a headless environment. - if dbus-run-session bash -c ' - dbus-update-activation-environment \ - DISPLAY WAYLAND_DISPLAY XDG_RUNTIME_DIR LIBGL_ALWAYS_SOFTWARE \ - GDK_DEBUG - exec gnome-shell-test-tool \ - --headless \ - --extension dist/target/aurora-shell@luminusos.github.io.shell-extension.zip \ - "$1" - ' -- "$script"; then - echo " PASS" - PASS=$((PASS + 1)) - else - echo " FAIL" - FAIL=$((FAIL + 1)) - fi - done - echo "" - echo "Results: $PASS passed, $FAIL failed" - [ "$FAIL" -eq 0 ] + bash scripts/run-shell-tests.sh \ + dist/target/aurora-shell@luminusos.github.io.shell-extension.zip diff --git a/.github/workflows/pre-release.yml b/.github/workflows/pre-release.yml index d5bcf8d..d17d13c 100644 --- a/.github/workflows/pre-release.yml +++ b/.github/workflows/pre-release.yml @@ -6,20 +6,28 @@ on: permissions: contents: write + packages: write concurrency: group: pre-release-main cancel-in-progress: true jobs: + ci: + uses: ./.github/workflows/ci.yml + pre-release: name: Create nightly pre-release runs-on: ubuntu-latest + needs: [ci] steps: - uses: actions/checkout@v7 - - name: Package extension - uses: ./.github/actions/package-extension + - name: Download extension zip + uses: actions/download-artifact@v8 + with: + name: extension-zip + path: dist/target/ - name: Read version metadata id: metadata diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 81343b8..a033303 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -7,6 +7,7 @@ on: permissions: contents: write + packages: write jobs: ci: @@ -22,7 +23,7 @@ jobs: - uses: actions/checkout@v7 - name: Download extension zip - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v8 with: name: extension-zip path: dist/target/ diff --git a/.gitignore b/.gitignore index b136b65..1dd8660 100644 --- a/.gitignore +++ b/.gitignore @@ -12,8 +12,6 @@ node_modules/ # Build output dist/ -dist-gjsify/ -dist-gjsify-probe/ # npm (legacy) package-lock.json @@ -42,4 +40,4 @@ docs/ # IA Stuff .agents/ -skills-lock.json \ No newline at end of file +skills-lock.json diff --git a/AGENTS.md b/AGENTS.md index ed36142..56179b0 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -13,13 +13,14 @@ or `just shexli` unless the task specifically requires that validation. 1. **Run `just validate`** — type-checks the source, lints, and checks formatting. Fix any reported errors. 2. **Run `just shexli`** — packages the extension and runs the extensions.gnome.org static analyzer on the generated ZIP. Review every finding. Some `warning` or `manual_review` findings can be false positives or accepted GNOME-review tradeoffs, but they must be called out explicitly; fix any real regression before finishing. 3. **Run targeted integration tests:** - * If you modified only **one module**, run only the integration test for that module (e.g., `just test tests/shell/auroraTrayIcons.js`). - * If you made **formatting-only changes** (Prettier) and have already passed the tests in a previous turn, you only need to run `just validate` and `just shexli`. - * If you made **architectural or cross-cutting changes**, run `just toolbox test-all`. + - If you modified only **one module**, run only the integration test for that module (e.g., `just test tests/shell/auroraTrayIcons.js`). + - If you made **formatting-only changes** (Prettier) and have already passed the tests in a previous turn, you only need to run `just validate` and `just shexli`. + - If you made **architectural or cross-cutting changes**, run `just toolbox test-all`. **IMPORTANT:** Never execute the `test` command (or `test-all`) chained with another command using `&&`. Always run it as a separate standalone turn. To read only the relevant output from a `test-all` run (pass/fail summary): + ```sh just toolbox test-all 2>&1 | grep -E "PASS:|FAIL:|Results:" ``` @@ -28,16 +29,14 @@ Do not leave a task incomplete if either command reports errors or failures. ## Commands -- **Install deps:** `just deps` — runs `yarn install`; use once or when updating packages +- **Install deps:** `just deps` — runs `yarn install --immutable`; use once or after changing branches - **Build:** `just build` — compiles TypeScript and SCSS, copies metadata/schemas, and compiles `.mo` files - **Package:** `just package` — packs the extension as a `.zip` in `dist/target/` (depends on `build`) -- **Install:** `just install` — installs the already-packaged `.zip` to GNOME Shell (requires `just package` first) -- **Full install:** `just full-install` — packages + installs in one step -- **All:** `just all` — clean + full-install +- **Install:** `just install` — packages and installs the `.zip` to GNOME Shell - **Uninstall:** `just uninstall` — disables and removes the extension - **Run (host):** `just run` — packages, installs, then launches a devkit GNOME Shell session - **Run (toolbox):** `just toolbox run` — packages/installs on the host, then runs GNOME Shell inside the Fedora toolbox -- **Create toolbox:** `just toolbox create` — create the `aurora-shell-devel` Fedora toolbox +- **Create toolbox:** `just toolbox create` — creates `aurora-shell-devel` from the same Fedora/GNOME image used by CI - **Remove toolbox:** `just toolbox remove` — delete the toolbox - **Validate:** `just validate` — runs tsc, ESLint, Prettier check, and Stylelint - **Shexli:** `just shexli` — packages the extension and runs the extensions.gnome.org static analyzer on the generated ZIP @@ -46,13 +45,13 @@ Do not leave a task incomplete if either command reports errors or failures. - **View logs:** `just logs` — shows recent `aurora` entries from the current boot journal - **Clean:** `just clean` — removes `dist/` - **Deep clean:** `just distclean` — removes `dist/` and `node_modules/` -- **Unit tests:** `just unit-test` — runs unit tests via `yarn test:unit` (vitest) +- **Unit tests:** `just unit-test` — runs unit tests with Node's test runner - **Coverage:** `just coverage` — runs unit tests with coverage report - **Single integration test:** `just test