name: Workspace release checks on: pull_request: push: branches: [main] tags: ["v*"] workflow_dispatch: permissions: contents: read concurrency: group: release-checks-${{ github.ref }} cancel-in-progress: false jobs: workspace: runs-on: ubuntu-24.04 container: image: fedora:44 options: --init timeout-minutes: 60 env: CARGO_BUILD_JOBS: "2" CARGO_INCREMENTAL: "0" CARGO_PROFILE_DEV_DEBUG: "0" CARGO_PROFILE_TEST_DEBUG: "0" XDG_RUNTIME_DIR: /tmp/ferese-release-runtime steps: - name: Install desktop build and test dependencies run: | dnf install -y --allowerasing python3 python3-gobject python3-pillow git curl gcc gcc-c++ make cmake pkgconf-pkg-config \ wayland-devel wayland-protocols-devel libxkbcommon-devel libinput-devel systemd-devel libseat-devel \ mesa-libgbm-devel mesa-libEGL-devel mesa-dri-drivers mesa-vulkan-drivers libdrm-devel fontconfig-devel \ freetype-devel expat-devel dbus-daemon dbus-tools desktop-file-utils foot pam xorg-x11-xauth \ clang clang-devel pipewire-devel pipewire wireplumber polkit polkit-libs libei \ xdg-desktop-portal xdg-desktop-portal-gtk weston \ gstreamer1-devel gstreamer1-plugins-base gstreamer1-plugins-good pipewire-gstreamer - name: Create private test runtime directory run: install -d -m 0700 "$XDG_RUNTIME_DIR" - uses: actions/checkout@v6 - name: Install pinned Rust and checks run: | curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs -o /tmp/rustup.sh sh /tmp/rustup.sh -y --profile minimal --default-toolchain 1.95.0 --component rustfmt --component clippy echo "$HOME/.cargo/bin" >> "$GITHUB_PATH" - name: Check formatting and all workspace lints run: | cargo fmt --all --check cargo clippy --locked --workspace --all-targets -- -D warnings - name: Build desktop binaries and test the complete workspace run: | cargo build --locked --workspace cargo test --locked --workspace --no-fail-fast - name: Check release tag matches the workspace version if: startsWith(github.ref, 'refs/tags/') env: RELEASE_TAG: ${{ github.ref_name }} run: | python3 - <<'PYTHON' import os, tomllib with open("Cargo.toml", "rb") as source: version = tomllib.load(source)["workspace"]["package"]["version"] assert os.environ["RELEASE_TAG"] == "v" + version, "Tag must match workspace.package.version" PYTHON - name: Test capture privacy and failure recovery env: LIBGL_ALWAYS_SOFTWARE: "1" EGL_PLATFORM: surfaceless run: | cargo test --locked -p ferese state::capture_privacy::tests -- --ignored cargo test --locked -p ferese backends::direct::capture::tests::capture_recomposes_cursor_without_touching_the_display_target -- --ignored cargo test --locked -p ferese winit::tests::capture_failure_restores_display_target_and_subsequent_frames_render -- --ignored - name: Test native shell, visibility and resize behavior run: python3 scripts/ci/run-native-checks.py --suite desktop --log-dir native-logs - name: Upload native test logs if: always() uses: actions/upload-artifact@v4 with: name: native-test-logs path: native-logs if-no-files-found: ignore - name: Test installer, session recovery and private portal contracts run: python3 -m unittest discover -s scripts/tests -v publish: name: Publish validated tag needs: workspace if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') runs-on: ubuntu-24.04 permissions: contents: write steps: - uses: actions/github-script@v8 with: script: | const tag = context.ref.slice('refs/tags/'.length); const repo = context.repo; const commit = await github.rest.repos.getCommit({...repo, ref: tag}); if (commit.data.sha !== context.sha) { throw new Error('Release tag moved after validation'); } let release; try { release = (await github.rest.repos.getReleaseByTag({...repo, tag})).data; } catch (error) { if (error.status !== 404) throw error; } if (release?.draft) { await github.rest.repos.updateRelease({...repo, release_id: release.id, draft: false}); } else if (!release) { await github.rest.repos.createRelease({ ...repo, tag_name: tag, name: tag, generate_release_notes: true, prerelease: tag.includes('-') }); } else { core.notice(`Release ${tag} is already published`); }