From 8b9a3351685b657cd4b8a78119620c9f6d4d2967 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 3 Sep 2026 12:04:02 +0900 Subject: [PATCH 1/5] fix(ci): skip docs-only changes for R-CMD-check, test-fast, test-suite Org-wide audit found these workflows lack paths-ignore, triggering full CI on every docs-only push/PR and contributing to Actions queue congestion. Co-Authored-By: Claude Sonnet 5 --- .github/workflows/R-CMD-check.yaml | 6 ++++++ .github/workflows/test-fast.yaml | 6 ++++++ .github/workflows/test-suite.yaml | 6 ++++++ 3 files changed, 18 insertions(+) diff --git a/.github/workflows/R-CMD-check.yaml b/.github/workflows/R-CMD-check.yaml index 2fd552b..93ac8c5 100644 --- a/.github/workflows/R-CMD-check.yaml +++ b/.github/workflows/R-CMD-check.yaml @@ -3,8 +3,14 @@ on: push: branches: [main, master, develop] + paths-ignore: + - "docs/**" + - "*.md" pull_request: branches: [main, master, develop] + paths-ignore: + - "docs/**" + - "*.md" name: R-CMD-check diff --git a/.github/workflows/test-fast.yaml b/.github/workflows/test-fast.yaml index ea1cf69..f2068bf 100644 --- a/.github/workflows/test-fast.yaml +++ b/.github/workflows/test-fast.yaml @@ -3,8 +3,14 @@ name: test-fast on: push: branches: [main, master, develop] + paths-ignore: + - "docs/**" + - "*.md" pull_request: branches: [main, master, develop] + paths-ignore: + - "docs/**" + - "*.md" permissions: contents: read diff --git a/.github/workflows/test-suite.yaml b/.github/workflows/test-suite.yaml index 439b9b7..faf2711 100644 --- a/.github/workflows/test-suite.yaml +++ b/.github/workflows/test-suite.yaml @@ -10,8 +10,14 @@ name: test-suite on: push: branches: [main, master, develop] + paths-ignore: + - "docs/**" + - "*.md" pull_request: branches: [main, master, develop] + paths-ignore: + - "docs/**" + - "*.md" schedule: - cron: '17 3 * * 1' workflow_dispatch: From 23835a1ca22ed1642699cfbbe1597c367fcc878c Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 4 Sep 2026 21:07:05 +0900 Subject: [PATCH 2/5] ci(actions): restamp current head after startup failure From e3ce9fc5b162eea141d9b4cc44dd7c59d760ab6d Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 4 Sep 2026 21:36:13 +0900 Subject: [PATCH 3/5] chore: refresh head after Actions startup failure From dff21117d012d30d70b43b2aaf33369ffe3c6152 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Mon, 7 Sep 2026 10:26:40 +0900 Subject: [PATCH 4/5] fix(ci): keep public API contract changes covered --- .github/workflows/R-CMD-check.yaml | 18 ++++++++++----- .github/workflows/test-fast.yaml | 20 ++++++++++++----- .github/workflows/test-suite.yaml | 18 ++++++++++----- ARCHITECTURE.md | 13 ++++++++--- NEWS.md | 8 ++++++- tests/testthat/test-workflow-path-contract.R | 23 ++++++++++++++++++++ 6 files changed, 78 insertions(+), 22 deletions(-) create mode 100644 tests/testthat/test-workflow-path-contract.R diff --git a/.github/workflows/R-CMD-check.yaml b/.github/workflows/R-CMD-check.yaml index 93ac8c5..524452e 100644 --- a/.github/workflows/R-CMD-check.yaml +++ b/.github/workflows/R-CMD-check.yaml @@ -3,14 +3,20 @@ on: push: branches: [main, master, develop] - paths-ignore: - - "docs/**" - - "*.md" + paths: + - "**" + - "!docs/**" + - "!*.md" + - "!**/*.md" + - "docs/product/kaefa-core-api-contract.md" pull_request: branches: [main, master, develop] - paths-ignore: - - "docs/**" - - "*.md" + paths: + - "**" + - "!docs/**" + - "!*.md" + - "!**/*.md" + - "docs/product/kaefa-core-api-contract.md" name: R-CMD-check diff --git a/.github/workflows/test-fast.yaml b/.github/workflows/test-fast.yaml index f2068bf..d1afde6 100644 --- a/.github/workflows/test-fast.yaml +++ b/.github/workflows/test-fast.yaml @@ -3,14 +3,20 @@ name: test-fast on: push: branches: [main, master, develop] - paths-ignore: - - "docs/**" - - "*.md" + paths: + - "**" + - "!docs/**" + - "!*.md" + - "!**/*.md" + - "docs/product/kaefa-core-api-contract.md" pull_request: branches: [main, master, develop] - paths-ignore: - - "docs/**" - - "*.md" + paths: + - "**" + - "!docs/**" + - "!*.md" + - "!**/*.md" + - "docs/product/kaefa-core-api-contract.md" permissions: contents: read @@ -44,4 +50,6 @@ jobs: reporter = reporter) testthat::test_file("tests/testthat/test-core-api-contract.R", reporter = reporter) + testthat::test_file("tests/testthat/test-workflow-path-contract.R", + reporter = reporter) RSCRIPT diff --git a/.github/workflows/test-suite.yaml b/.github/workflows/test-suite.yaml index faf2711..eda8b99 100644 --- a/.github/workflows/test-suite.yaml +++ b/.github/workflows/test-suite.yaml @@ -10,14 +10,20 @@ name: test-suite on: push: branches: [main, master, develop] - paths-ignore: - - "docs/**" - - "*.md" + paths: + - "**" + - "!docs/**" + - "!*.md" + - "!**/*.md" + - "docs/product/kaefa-core-api-contract.md" pull_request: branches: [main, master, develop] - paths-ignore: - - "docs/**" - - "*.md" + paths: + - "**" + - "!docs/**" + - "!*.md" + - "!**/*.md" + - "docs/product/kaefa-core-api-contract.md" schedule: - cron: '17 3 * * 1' workflow_dispatch: diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index 6ddd063..e85d685 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -57,9 +57,16 @@ explicitly requires vendored source integration. ## Quality and Security Gates - PR merge requires review approval and resolved conversations. -- Required checks include R-CMD-check matrix and dependency review. -- If code scanning is enabled later, alerts can be tracked via GitHub code - scanning APIs. +- Organization-owned required review and security gates run on every PR through + reusable workflows in `ContextualWisdomLab/.github`. +- Local `R-CMD-check`, `test-fast`, and `test-suite` workflows run for runtime, + package, workflow, `README.Rmd`, and public API contract changes. Plain + Markdown changes are excluded, except + `docs/product/kaefa-core-api-contract.md`, because + `tests/testthat/test-core-api-contract.R` consumes that file as executable + contract input. +- `tests/testthat/test-workflow-path-contract.R` prevents the API-contract + exception from silently disappearing when the trigger paths change. ## Change Rule diff --git a/NEWS.md b/NEWS.md index 38399b7..ad99fce 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,10 @@ +# kaefa (development version) + +* Reduced local R workflow load for prose-only Markdown changes while keeping + `docs/product/kaefa-core-api-contract.md` inside the package contract checks. +* Added a regression contract for the local workflow path filters and aligned + the architecture documentation with the live central/local gate boundary. + # kaefa 0.1.428.1 ## New Features @@ -24,4 +31,3 @@ This update addresses the need to set theta priors based on empirical raw score * Added a `NEWS.md` file to track changes to the package. - diff --git a/tests/testthat/test-workflow-path-contract.R b/tests/testthat/test-workflow-path-contract.R new file mode 100644 index 0000000..95f984f --- /dev/null +++ b/tests/testthat/test-workflow-path-contract.R @@ -0,0 +1,23 @@ +workflow_lines <- function(name) { + readLines( + .kaefa_repo_file(".github", "workflows", name), + warn = FALSE + ) +} + +test_that("runtime workflows keep the public API contract in scope", { + workflows <- c("R-CMD-check.yaml", "test-fast.yaml", "test-suite.yaml") + + for (workflow in workflows) { + content <- workflow_lines(workflow) + + expect_true(sum(grepl('^ - "\\*\\*"$', content)) == 2L) + expect_true(sum(grepl('^ - "!docs/\\*\\*"$', content)) == 2L) + expect_true(sum(grepl('^ - "!\\*\\.md"$', content)) == 2L) + expect_true(sum(grepl('^ - "!\\*\\*/\\*\\.md"$', content)) == 2L) + expect_true(sum(grepl( + '^ - "docs/product/kaefa-core-api-contract\\.md"$', + content + )) == 2L) + } +}) From 5829d6033c1e504b1ed446244910acebb405634f Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Mon, 7 Sep 2026 10:34:28 +0900 Subject: [PATCH 5/5] test(ci): verify each workflow event path order --- tests/testthat/test-workflow-path-contract.R | 41 ++++++++++++++++---- 1 file changed, 33 insertions(+), 8 deletions(-) diff --git a/tests/testthat/test-workflow-path-contract.R b/tests/testthat/test-workflow-path-contract.R index 95f984f..dd43aca 100644 --- a/tests/testthat/test-workflow-path-contract.R +++ b/tests/testthat/test-workflow-path-contract.R @@ -5,19 +5,44 @@ workflow_lines <- function(name) { ) } +workflow_event_paths <- function(content, event_name) { + event_line <- match(paste0(" ", event_name, ":"), content) + if (is.na(event_line)) { + stop("Missing workflow event: ", event_name) + } + + remaining <- content[seq.int(event_line + 1L, length(content))] + paths_offset <- match(" paths:", remaining) + if (is.na(paths_offset)) { + stop("Missing paths list for workflow event: ", event_name) + } + + entries <- content[seq.int(event_line + paths_offset + 1L, length(content))] + entry_count <- rle(grepl('^ - "', entries))$lengths[1L] + if (!grepl('^ - "', entries[1L])) { + stop("Empty paths list for workflow event: ", event_name) + } + + sub('^ - "(.*)"$', "\\1", entries[seq_len(entry_count)]) +} + test_that("runtime workflows keep the public API contract in scope", { workflows <- c("R-CMD-check.yaml", "test-fast.yaml", "test-suite.yaml") + expected_paths <- c( + "**", + "!docs/**", + "!*.md", + "!**/*.md", + "docs/product/kaefa-core-api-contract.md" + ) for (workflow in workflows) { content <- workflow_lines(workflow) - expect_true(sum(grepl('^ - "\\*\\*"$', content)) == 2L) - expect_true(sum(grepl('^ - "!docs/\\*\\*"$', content)) == 2L) - expect_true(sum(grepl('^ - "!\\*\\.md"$', content)) == 2L) - expect_true(sum(grepl('^ - "!\\*\\*/\\*\\.md"$', content)) == 2L) - expect_true(sum(grepl( - '^ - "docs/product/kaefa-core-api-contract\\.md"$', - content - )) == 2L) + expect_identical(workflow_event_paths(content, "push"), expected_paths) + expect_identical( + workflow_event_paths(content, "pull_request"), + expected_paths + ) } })