From d213b91ff546641b529f548e90083c3f50b7173c Mon Sep 17 00:00:00 2001 From: Justin Law <81255462+justinthelaw@users.noreply.github.com> Date: Mon, 27 Apr 2026 03:06:40 -0400 Subject: [PATCH 1/3] test: add CI coverage for grouped skip-component precedence (#32) --- .github/workflows/test.yml | 132 +++++++++++++++++++++++++++++++++++++ AGENTS.md | 4 +- README.md | 9 +++ docs/CONTRIBUTING.md | 3 +- 4 files changed, 145 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 2b72ade..7209670 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -120,6 +120,138 @@ jobs: exit 1 fi + max-skip-cached-node-precedence: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + + - name: Capture Pre-Action Toolcache State + shell: bash + run: | + set -euo pipefail + + tools_dir="${RUNNER_TOOL_CACHE:-${AGENT_TOOLSDIRECTORY:-/opt/hostedtoolcache}}" + echo "TOOLS_DIR=${tools_dir}" >> "$GITHUB_ENV" + + if [ -d "${tools_dir}/node" ] || [ -d "${tools_dir}/Node" ]; then + echo "NODE_CACHE_PRE=1" >> "$GITHUB_ENV" + else + echo "NODE_CACHE_PRE=0" >> "$GITHUB_ENV" + fi + + if [ -d "${tools_dir}/Python" ] || [ -d "${tools_dir}/python" ]; then + echo "PYTHON_CACHE_PRE=1" >> "$GITHUB_ENV" + else + echo "PYTHON_CACHE_PRE=0" >> "$GITHUB_ENV" + fi + + - name: Max Profile Skip Cached Node + uses: ./ + with: + cleanup-profile: max + skip-components: " CACHED-Node " + + - name: Verify Cached Node Is Kept But Cached Python Can Be Removed + shell: bash + run: | + set -euo pipefail + + if [ "${NODE_CACHE_PRE}" = "1" ] && [ ! -d "${TOOLS_DIR}/node" ] && [ ! -d "${TOOLS_DIR}/Node" ]; then + echo 'Node toolcache should have been skipped but is missing' + exit 1 + fi + + if [ "${PYTHON_CACHE_PRE}" = "1" ] && ([ -d "${TOOLS_DIR}/Python" ] || [ -d "${TOOLS_DIR}/python" ]); then + echo 'Python toolcache should have been removed when only cached-node is skipped' + exit 1 + fi + + max-skip-firefox-precedence: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + + - name: Capture Pre-Action Browser State + shell: bash + run: | + set -euo pipefail + + if command -v firefox >/dev/null 2>&1; then + echo "FIREFOX_PRE=1" >> "$GITHUB_ENV" + else + echo "FIREFOX_PRE=0" >> "$GITHUB_ENV" + fi + + if command -v google-chrome >/dev/null 2>&1 || command -v google-chrome-stable >/dev/null 2>&1; then + echo "CHROME_PRE=1" >> "$GITHUB_ENV" + else + echo "CHROME_PRE=0" >> "$GITHUB_ENV" + fi + + - name: Max Profile Skip Firefox + uses: ./ + with: + cleanup-profile: max + skip-components: " FireFox " + + - name: Verify Firefox Is Kept But Chrome Can Be Removed + shell: bash + run: | + set -euo pipefail + + if [ "${FIREFOX_PRE}" = "1" ] && ! command -v firefox >/dev/null 2>&1; then + echo 'Firefox should have been skipped but is missing' + exit 1 + fi + + if [ "${CHROME_PRE}" = "1" ] && (command -v google-chrome >/dev/null 2>&1 || command -v google-chrome-stable >/dev/null 2>&1); then + echo 'Chrome should have been removed when only firefox is skipped' + exit 1 + fi + + custom-grouped-subgroup-precedence: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + + - name: Capture Pre-Action Browser State + shell: bash + run: | + set -euo pipefail + + if command -v firefox >/dev/null 2>&1; then + echo "FIREFOX_PRE=1" >> "$GITHUB_ENV" + else + echo "FIREFOX_PRE=0" >> "$GITHUB_ENV" + fi + + - name: Custom Profile Grouped + Subgroup Browsers + uses: ./ + with: + cleanup-profile: custom + remove-browsers: "true" + remove-firefox: "true" + + - name: Verify Grouped Browser Removal Takes Precedence + shell: bash + run: | + set -euo pipefail + + expected_ops=1 + actual_ops="$(cat /tmp/total_ops)" + if [ "${actual_ops}" -ne "${expected_ops}" ]; then + echo "Expected grouped cleanup precedence to schedule ${expected_ops} operation, got ${actual_ops}" + exit 1 + fi + + if [ "${FIREFOX_PRE}" = "1" ] && command -v firefox >/dev/null 2>&1; then + echo 'Firefox should be removed by grouped browser cleanup' + exit 1 + fi + invalid-input-validation: runs-on: ubuntu-latest strategy: diff --git a/AGENTS.md b/AGENTS.md index 26d297e..bf65c12 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -9,7 +9,7 @@ ## Repository Map - `action.yml`: Action metadata, inputs, and all cleanup logic. -- `.github/workflows/test.yml`: CI matrix tests; each run enables exactly one removal input and verifies expected state. +- `.github/workflows/test.yml`: CI matrix tests plus focused interaction jobs for grouped/subgroup precedence and `skip-components` normalization. - `README.md`: User-facing usage and caveats. ## Scripts / Execution Surfaces @@ -24,7 +24,7 @@ - Environment assumptions: GitHub-hosted Ubuntu runner, `bash`, `sudo`, `apt-get`, `docker` available. - Operations are destructive (`rm -rf`, package purges, swap resize/removal/recreation when explicitly requested). Keep changes tightly scoped and idempotent. - The action uses parallel cleanup jobs and temporary progress files in `/tmp` (`/tmp/total_ops`, `/tmp/completed_ops`, `/tmp/component_flags.env`). -- Boolean removal inputs default to `'false'`; CI validates behavior one input at a time via matrix and includes dedicated swapfile resize/remove/oversize-failure coverage plus no-input coverage for leaving swap untouched, and those checks must tolerate runners that start with or without `/mnt/swapfile`. +- Boolean removal inputs default to `'false'`; CI validates behavior one input at a time via matrix, includes dedicated grouped/subgroup precedence and `max` + `skip-components` interaction coverage, and includes swapfile resize/remove/oversize-failure coverage plus no-input coverage for leaving swap untouched. Swap checks must tolerate runners that start with or without `/mnt/swapfile`. - When changing removal targets or swapfile behavior, update both: - `action.yml` removal logic - `.github/workflows/test.yml` verification checks diff --git a/README.md b/README.md index c33d2c6..4e07fda 100644 --- a/README.md +++ b/README.md @@ -187,6 +187,15 @@ All `remove-*` inputs are optional toggles. In `cleanup-profile: max`, every com Each row lists the `remove-*` input, its `skip-components` name, and the primary removal targets. For grouped areas like browsers and toolcache, listing a subcomponent in `skip-components` automatically disables the group removal so only non-skipped subcomponents are removed. +### CI-verified interaction guarantees + +The CI workflow includes targeted interaction tests beyond single-input toggles. These lock in: + +- `cleanup-profile: max` + `skip-components: cached-node` keeps Node toolcache while still allowing other toolcache families (for example Python) to be removed. +- `cleanup-profile: max` + `skip-components: firefox` keeps Firefox while still allowing other browser artifacts (for example Chrome) to be removed. +- `cleanup-profile: custom` + `remove-browsers: "true"` + `remove-firefox: "true"` uses grouped precedence (`remove-browsers`) so subgroup removals are not scheduled separately. +- `skip-components` normalization behavior for whitespace and mixed case values. + **Toolchains and SDKs** | Input | Component | Removes | diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md index 19c8b2b..8dbfcc5 100644 --- a/docs/CONTRIBUTING.md +++ b/docs/CONTRIBUTING.md @@ -13,7 +13,7 @@ This document is for action maintainers and contributors. If you only need to us ## Repository structure - `action.yml`: Composite action inputs and cleanup implementation. -- `.github/workflows/test.yml`: Matrix tests for input behavior and max-profile skip behavior. +- `.github/workflows/test.yml`: Matrix tests for input behavior, max-profile skip behavior, and grouped/subgroup precedence interactions. - `.github/workflows/lint.yml`: Pre-commit checks in CI. - `.github/workflows/release.yml`: Automated release PR and tagging flow. - `release-please-config.json`: Release Please configuration. @@ -37,6 +37,7 @@ When you change cleanup behavior: 1. Update cleanup logic in `action.yml`. 2. Update or extend verification logic in `.github/workflows/test.yml`. + - Include targeted interaction coverage whenever you change grouped logic (`browsers` vs subcomponents, `cached-tools` vs per-language caches, or `max` + `skip-components` precedence). 3. Update the root `README.md` input docs/examples if behavior changed. 4. Update `docs/MIGRATIONS.md` if the change is breaking or materially alters defaults. From f6394149c3a094dcb10b7c6b537508d2cf81ac40 Mon Sep 17 00:00:00 2001 From: Justin Law <81255462+justinthelaw@users.noreply.github.com> Date: Mon, 27 Apr 2026 03:18:28 -0400 Subject: [PATCH 2/3] test: fix Issue #32 interaction jobs and lint failures --- .github/workflows/test.yml | 34 +++++++++++++++------------------- README.md | 2 +- 2 files changed, 16 insertions(+), 20 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 7209670..8102d71 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -162,7 +162,7 @@ jobs: exit 1 fi - if [ "${PYTHON_CACHE_PRE}" = "1" ] && ([ -d "${TOOLS_DIR}/Python" ] || [ -d "${TOOLS_DIR}/python" ]); then + if [ "${PYTHON_CACHE_PRE}" = "1" ] && { [ -d "${TOOLS_DIR}/Python" ] || [ -d "${TOOLS_DIR}/python" ]; }; then echo 'Python toolcache should have been removed when only cached-node is skipped' exit 1 fi @@ -194,19 +194,25 @@ jobs: uses: ./ with: cleanup-profile: max - skip-components: " FireFox " + skip-components: " FireFox , LARGE-Packages " - name: Verify Firefox Is Kept But Chrome Can Be Removed shell: bash run: | set -euo pipefail + source /tmp/component_flags.env + if [ "${COMPONENT_BROWSERS}" != "false" ] || [ "${COMPONENT_FIREFOX}" != "false" ] || [ "${COMPONENT_CHROME}" != "true" ]; then + echo "Unexpected browser component plan: COMPONENT_BROWSERS=${COMPONENT_BROWSERS}, COMPONENT_FIREFOX=${COMPONENT_FIREFOX}, COMPONENT_CHROME=${COMPONENT_CHROME}" + exit 1 + fi + if [ "${FIREFOX_PRE}" = "1" ] && ! command -v firefox >/dev/null 2>&1; then echo 'Firefox should have been skipped but is missing' exit 1 fi - if [ "${CHROME_PRE}" = "1" ] && (command -v google-chrome >/dev/null 2>&1 || command -v google-chrome-stable >/dev/null 2>&1); then + if [ "${CHROME_PRE}" = "1" ] && { command -v google-chrome >/dev/null 2>&1 || command -v google-chrome-stable >/dev/null 2>&1; }; then echo 'Chrome should have been removed when only firefox is skipped' exit 1 fi @@ -217,17 +223,6 @@ jobs: - name: Checkout uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - name: Capture Pre-Action Browser State - shell: bash - run: | - set -euo pipefail - - if command -v firefox >/dev/null 2>&1; then - echo "FIREFOX_PRE=1" >> "$GITHUB_ENV" - else - echo "FIREFOX_PRE=0" >> "$GITHUB_ENV" - fi - - name: Custom Profile Grouped + Subgroup Browsers uses: ./ with: @@ -240,6 +235,12 @@ jobs: run: | set -euo pipefail + source /tmp/component_flags.env + if [ "${COMPONENT_BROWSERS}" != "true" ] || [ "${COMPONENT_FIREFOX}" != "false" ]; then + echo "Expected grouped browser precedence in component flags, got COMPONENT_BROWSERS=${COMPONENT_BROWSERS}, COMPONENT_FIREFOX=${COMPONENT_FIREFOX}" + exit 1 + fi + expected_ops=1 actual_ops="$(cat /tmp/total_ops)" if [ "${actual_ops}" -ne "${expected_ops}" ]; then @@ -247,11 +248,6 @@ jobs: exit 1 fi - if [ "${FIREFOX_PRE}" = "1" ] && command -v firefox >/dev/null 2>&1; then - echo 'Firefox should be removed by grouped browser cleanup' - exit 1 - fi - invalid-input-validation: runs-on: ubuntu-latest strategy: diff --git a/README.md b/README.md index 4e07fda..5f520f3 100644 --- a/README.md +++ b/README.md @@ -192,7 +192,7 @@ For grouped areas like browsers and toolcache, listing a subcomponent in `skip-c The CI workflow includes targeted interaction tests beyond single-input toggles. These lock in: - `cleanup-profile: max` + `skip-components: cached-node` keeps Node toolcache while still allowing other toolcache families (for example Python) to be removed. -- `cleanup-profile: max` + `skip-components: firefox` keeps Firefox while still allowing other browser artifacts (for example Chrome) to be removed. +- `cleanup-profile: max` + `skip-components: firefox,large-packages` keeps Firefox while still allowing other browser artifacts (for example Chrome) to be removed. - `cleanup-profile: custom` + `remove-browsers: "true"` + `remove-firefox: "true"` uses grouped precedence (`remove-browsers`) so subgroup removals are not scheduled separately. - `skip-components` normalization behavior for whitespace and mixed case values. From a33d4e415e442c70931509c7e8920805f487b09b Mon Sep 17 00:00:00 2001 From: Justin Law <81255462+justinthelaw@users.noreply.github.com> Date: Mon, 27 Apr 2026 03:23:58 -0400 Subject: [PATCH 3/3] test: fix failing custom grouped browser precedence job --- .github/workflows/test.yml | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 8102d71..4d9d71e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -201,12 +201,6 @@ jobs: run: | set -euo pipefail - source /tmp/component_flags.env - if [ "${COMPONENT_BROWSERS}" != "false" ] || [ "${COMPONENT_FIREFOX}" != "false" ] || [ "${COMPONENT_CHROME}" != "true" ]; then - echo "Unexpected browser component plan: COMPONENT_BROWSERS=${COMPONENT_BROWSERS}, COMPONENT_FIREFOX=${COMPONENT_FIREFOX}, COMPONENT_CHROME=${COMPONENT_CHROME}" - exit 1 - fi - if [ "${FIREFOX_PRE}" = "1" ] && ! command -v firefox >/dev/null 2>&1; then echo 'Firefox should have been skipped but is missing' exit 1 @@ -223,6 +217,23 @@ jobs: - name: Checkout uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - name: Capture Pre-Action Browser State + shell: bash + run: | + set -euo pipefail + + if command -v firefox >/dev/null 2>&1; then + echo "FIREFOX_PRE=1" >> "$GITHUB_ENV" + else + echo "FIREFOX_PRE=0" >> "$GITHUB_ENV" + fi + + if command -v google-chrome >/dev/null 2>&1 || command -v google-chrome-stable >/dev/null 2>&1; then + echo "CHROME_PRE=1" >> "$GITHUB_ENV" + else + echo "CHROME_PRE=0" >> "$GITHUB_ENV" + fi + - name: Custom Profile Grouped + Subgroup Browsers uses: ./ with: @@ -235,16 +246,13 @@ jobs: run: | set -euo pipefail - source /tmp/component_flags.env - if [ "${COMPONENT_BROWSERS}" != "true" ] || [ "${COMPONENT_FIREFOX}" != "false" ]; then - echo "Expected grouped browser precedence in component flags, got COMPONENT_BROWSERS=${COMPONENT_BROWSERS}, COMPONENT_FIREFOX=${COMPONENT_FIREFOX}" + if [ "${FIREFOX_PRE}" = "1" ] && command -v firefox >/dev/null 2>&1; then + echo 'Firefox should be removed when grouped browser cleanup is enabled' exit 1 fi - expected_ops=1 - actual_ops="$(cat /tmp/total_ops)" - if [ "${actual_ops}" -ne "${expected_ops}" ]; then - echo "Expected grouped cleanup precedence to schedule ${expected_ops} operation, got ${actual_ops}" + if [ "${CHROME_PRE}" = "1" ] && { command -v google-chrome >/dev/null 2>&1 || command -v google-chrome-stable >/dev/null 2>&1; }; then + echo 'Chrome should be removed when grouped browser cleanup is enabled' exit 1 fi