From bafb380fc85024958be1eaae6abb6b8d89b0794b Mon Sep 17 00:00:00 2001 From: Alexa <53471801+Alexa-RR@users.noreply.github.com> Date: Sun, 25 Oct 2026 12:11:08 +0200 Subject: [PATCH 1/3] ci: build on push only for client-facing changes Push builds used to rebuild both platforms for any Jenkinsfile or ci/jenkins/ change, and every build publishes to the downloads page. Now only DorkNet.ClientMod/ and tools/build_pc.py (PC) or DorkNet.Quest/ (Quest) changes rebuild, and Markdown never counts; CI-only changes take a manual run. The README gives the matching Git path filter for the job, so other pushes don't start a run at all. --- Jenkinsfile | 18 ++++++++++++------ ci/jenkins/README.md | 14 +++++++++++--- 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index ef53ee8..9a9190d 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -9,8 +9,9 @@ // from the agent's environment (ARCHIVE_PC_REPO / ARCHIVE_QUEST_REPO), each // overridable per run. A build is picked by snapshot tags. // -// On a push, only the platforms whose code changed are rebuilt. A manual run -// picks the platforms with PLATFORMS. See ci/jenkins/README.md. +// A push builds only the platforms whose client code changed (never for +// docs or CI-only changes). A manual run picks the platforms with PLATFORMS. +// See ci/jenkins/README.md. // // Finished builds are renamed for players and published to the downloads bucket // (ci/downloads) unless PUBLISH_DOWNLOADS is off. The build scripts keep their @@ -76,10 +77,15 @@ pipeline { for (cs in currentBuild.changeSets) { for (entry in cs.items) changed.addAll(entry.affectedPaths) } - def touches = { prefixes -> changed.any { p -> prefixes.any { p.startsWith(it) } } } - def common = ['Jenkinsfile', 'ci/jenkins/'] - buildPc = touches(common + ['DorkNet.ClientMod/', 'tools/build_pc.py']) - buildQuest = touches(common + ['DorkNet.Quest/']) + // Only client-facing changes rebuild (and so republish) a + // platform; Markdown doesn't count. The job's Git path filter + // uses the same paths, so other pushes don't start a run at all. + // A CI-only change (Jenkinsfile, ci/) takes a manual run. + def touches = { prefixes -> + changed.any { p -> !p.toLowerCase().endsWith('.md') && prefixes.any { p.startsWith(it) } } + } + buildPc = touches(['DorkNet.ClientMod/', 'tools/build_pc.py']) + buildQuest = touches(['DorkNet.Quest/']) echo "Push build; ${changed.size()} changed file(s)" } else { buildPc = params.PLATFORMS in ['both', 'pc'] diff --git a/ci/jenkins/README.md b/ci/jenkins/README.md index 0540fec..7d27eb7 100644 --- a/ci/jenkins/README.md +++ b/ci/jenkins/README.md @@ -60,10 +60,18 @@ Resolve a table for another build locally with `build.py build --dump-cs`. ## Triggers -- **Push** to the branch (GitHub webhook) rebuilds only what changed: - - `DorkNet.ClientMod/` and the PC scripts rebuild PC; +- **Push** to the branch (GitHub webhook) builds only for client-facing + changes, and only the platform they touch: + - `DorkNet.ClientMod/` and `tools/build_pc.py` rebuild PC; - `DorkNet.Quest/` rebuilds Quest; - - `Jenkinsfile` and `ci/jenkins/` rebuild both. + - Markdown files never count; server, docs and CI-only pushes (including + the `Jenkinsfile` and `ci/`) build nothing. Run those manually. + + Set the same filter on the job so other pushes don't start a run at all: + under the job's **Git** source, add **Additional Behaviours → Polling + ignores commits in certain paths** with included regions + `DorkNet[.]ClientMod/.*`, `DorkNet[.]Quest/.*`, `tools/build_pc[.]py` (one + per line) and excluded region `.*[.]md`. - **Build with Parameters** runs a manual build: - `PLATFORMS` (both / pc / quest), and `PC_FULL_CLIENT` for the full PC client; - snapshot tags, and per-run repository overrides; From e29707deeb8fa7d62ce2cb0382874cccd99382f4 Mon Sep 17 00:00:00 2001 From: Alexa <53471801+Alexa-RR@users.noreply.github.com> Date: Sun, 25 Oct 2026 12:49:09 +0200 Subject: [PATCH 2/3] ci: keep the checkout so the path filter can skip non-client pushes The job's path filter needs the last build's checkout to compare against. The pipeline deleted the whole workspace after each run, so Jenkins polled with "Working Directory does not exist", assumed changes, and started a run for every push (builds #6 and #7: zero changed files). Delete only out/ and quest-work/ instead. --- Jenkinsfile | 13 +++++++++---- ci/jenkins/README.md | 5 ++++- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 9a9190d..865ecfa 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -226,10 +226,15 @@ pipeline { archiveArtifacts artifacts: 'out/downloads/**', allowEmptyArchive: true, fingerprint: true } cleanup { - // Runs after archiving. Keeps the restic cache and restored stock - // builds ($DORKNET_CACHE on the agent, outside the workspace); drops - // the workspace's build output and scratch. - cleanWs(deleteDirs: true, notFailBuild: true) + // Runs after archiving. Drops the build output and scratch (several + // GB) but keeps the Git checkout: the job's path filter compares + // pushes against it, and without a workspace Jenkins treats every + // push as a change and starts a run. The restic cache and restored + // stock builds live outside the workspace ($DORKNET_CACHE). + cleanWs(deleteDirs: true, notFailBuild: true, patterns: [ + [pattern: 'out/**', type: 'INCLUDE'], + [pattern: 'quest-work/**', type: 'INCLUDE'], + ]) } } } diff --git a/ci/jenkins/README.md b/ci/jenkins/README.md index 7d27eb7..98dcd39 100644 --- a/ci/jenkins/README.md +++ b/ci/jenkins/README.md @@ -71,7 +71,10 @@ Resolve a table for another build locally with `build.py build --dump-cs`. under the job's **Git** source, add **Additional Behaviours → Polling ignores commits in certain paths** with included regions `DorkNet[.]ClientMod/.*`, `DorkNet[.]Quest/.*`, `tools/build_pc[.]py` (one - per line) and excluded region `.*[.]md`. + per line) and excluded region `.*[.]md`. The filter compares against the + last build's checkout, so the pipeline keeps it and deletes only `out/` + and its scratch folders after each run; without a checkout, Jenkins treats + every push as a change. - **Build with Parameters** runs a manual build: - `PLATFORMS` (both / pc / quest), and `PC_FULL_CLIENT` for the full PC client; - snapshot tags, and per-run repository overrides; From 503d838fd150effad2100e201738848871281f46 Mon Sep 17 00:00:00 2001 From: Alexa <53471801+Alexa-RR@users.noreply.github.com> Date: Sun, 25 Oct 2026 13:51:26 +0200 Subject: [PATCH 3/3] ci: treat .markdown like .md in push builds From the local CodeRabbit review: a Markdown-only push using the .markdown extension still rebuilt Quest. Exclude both extensions in the push planner and in the documented job path filter. --- Jenkinsfile | 4 ++-- ci/jenkins/README.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 865ecfa..e6aef2d 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -78,11 +78,11 @@ pipeline { for (entry in cs.items) changed.addAll(entry.affectedPaths) } // Only client-facing changes rebuild (and so republish) a - // platform; Markdown doesn't count. The job's Git path filter + // platform; Markdown (.md, .markdown) doesn't count. The job's Git path filter // uses the same paths, so other pushes don't start a run at all. // A CI-only change (Jenkinsfile, ci/) takes a manual run. def touches = { prefixes -> - changed.any { p -> !p.toLowerCase().endsWith('.md') && prefixes.any { p.startsWith(it) } } + changed.any { p -> !(p.toLowerCase() ==~ /.*\.(md|markdown)/) && prefixes.any { p.startsWith(it) } } } buildPc = touches(['DorkNet.ClientMod/', 'tools/build_pc.py']) buildQuest = touches(['DorkNet.Quest/']) diff --git a/ci/jenkins/README.md b/ci/jenkins/README.md index 98dcd39..53f2754 100644 --- a/ci/jenkins/README.md +++ b/ci/jenkins/README.md @@ -64,14 +64,14 @@ Resolve a table for another build locally with `build.py build --dump-cs`. changes, and only the platform they touch: - `DorkNet.ClientMod/` and `tools/build_pc.py` rebuild PC; - `DorkNet.Quest/` rebuilds Quest; - - Markdown files never count; server, docs and CI-only pushes (including + - Markdown files (`.md`, `.markdown`) never count; server, docs and CI-only pushes (including the `Jenkinsfile` and `ci/`) build nothing. Run those manually. Set the same filter on the job so other pushes don't start a run at all: under the job's **Git** source, add **Additional Behaviours → Polling ignores commits in certain paths** with included regions `DorkNet[.]ClientMod/.*`, `DorkNet[.]Quest/.*`, `tools/build_pc[.]py` (one - per line) and excluded region `.*[.]md`. The filter compares against the + per line) and excluded region `.*[.](md|markdown)`. The filter compares against the last build's checkout, so the pipeline keeps it and deletes only `out/` and its scratch folders after each run; without a checkout, Jenkins treats every push as a change.