Skip to content

Commit b6d4dad

Browse files
committed
feat: add pristine-homebrew and setup-homebrew actions
feat: add prepare-pristine-homebrew job to test workflow refactor: use actions for setup-homebrew and pristine-homebrew test: add pytest marks for destructive tests test: group destructive tests and add pytest-group matrix fix: update clean_homebrew.sh to use zap when uninstalling chore: add filterwarnings to pyproject.toml style: improve readability in test.yml workflow file
1 parent 9a92c0c commit b6d4dad

File tree

6 files changed

+191
-25
lines changed

6 files changed

+191
-25
lines changed
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
name: pristine-homebrew
2+
description: Setup pristine Homebrew and cache it
3+
4+
inputs:
5+
os:
6+
description: Runner OS (used in the cache key)
7+
required: true
8+
restore:
9+
description: Restore a cached pristine Homebrew
10+
required: false
11+
default: "true"
12+
13+
runs:
14+
using: composite
15+
steps:
16+
- name: Build path list
17+
id: brew_paths
18+
shell: bash
19+
run: |
20+
P="${{ steps.brew_env.outputs.prefix }}"
21+
{
22+
echo 'list<<EOF'
23+
printf '%s\n' \
24+
"$P/bin" "$P/etc" "$P/include" "$P/lib" "$P/opt" \
25+
"$P/sbin" "$P/share" "$P/var" "$P/Library/Taps"
26+
echo 'EOF'
27+
} >>"$GITHUB_OUTPUT"
28+
- name: Cache lookup
29+
id: cache_lookup
30+
uses: actions/cache/restore@v4
31+
with:
32+
lookup-only: true
33+
path: ${{ steps.brew_paths.outputs.list }}
34+
key: brew-pristine-${{ inputs.os }}-${{ steps.brew_env.outputs.version }}
35+
- name: Remove current Homebrew directories
36+
if: inputs.restore == 'true' && steps.cache_lookup.outputs.cache-hit == 'true'
37+
shell: bash
38+
run: |
39+
while read -r d; do
40+
rm -rf "$d"
41+
done <<<"${{ steps.brew_paths.outputs.list }}"
42+
- name: Restore pristine Homebrew
43+
id: cache_restore
44+
if: inputs.restore == 'true' && steps.cache_lookup.outputs.cache-hit == 'true'
45+
uses: actions/cache/restore@v4
46+
with:
47+
path: ${{ steps.brew_paths.outputs.list }}
48+
key: ${{ steps.cache_lookup.outputs.cache-primary-key }}
49+
- name: Make Homebrew pristine
50+
if: steps.cache_lookup.outputs.cache-hit != 'true'
51+
shell: bash
52+
run: |
53+
set -euo pipefail
54+
mapfile -t formulae < <(brew list --formula)
55+
if [ "${#formulae[@]}" -gt 0 ]; then
56+
brew uninstall --zap --force "${formulae[@]}"
57+
fi
58+
mapfile -t casks < <(brew list --cask)
59+
if [ "${#casks[@]}" -gt 0 ]; then
60+
brew uninstall --cask --zap --force "${casks[@]}"
61+
fi
62+
mapfile -t taps < <(brew tap)
63+
if [ "${#taps[@]}" -gt 0 ]; then
64+
brew untap "${taps[@]}"
65+
fi
66+
- name: Save pristine Homebrew
67+
if: steps.cache_lookup.outputs.cache-hit != 'true'
68+
uses: actions/cache/save@v4
69+
with:
70+
path: ${{ steps.brew_paths.outputs.list }}
71+
key: brew-pristine-${{ inputs.os }}-${{ steps.brew_env.outputs.version }}
72+
- name: Remove brew download cache
73+
if: inputs.restore == 'true'
74+
shell: bash
75+
run: |
76+
rm -rf "$(brew --cache)" || true
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
name: setup Homebrew
2+
description: Setup Homebrew
3+
4+
runs:
5+
using: composite
6+
steps:
7+
- name: Detect Homebrew
8+
id: brew_env
9+
shell: bash
10+
run: |
11+
set -euo pipefail
12+
13+
ORIGINAL_PATH="$PATH"
14+
15+
# Linuxbrew
16+
if [ -x /home/linuxbrew/.linuxbrew/bin/brew ]; then
17+
eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"
18+
fi
19+
# macOS Apple Silicon
20+
if [ -x /opt/homebrew/bin/brew ]; then
21+
eval "$(/opt/homebrew/bin/brew shellenv)"
22+
fi
23+
# macOS Intel
24+
if [ -x /usr/local/bin/brew ]; then
25+
eval "$(/usr/local/bin/brew shellenv)"
26+
fi
27+
28+
if ! command -v brew >/dev/null; then
29+
echo "::error::brew not found"
30+
exit 1
31+
fi
32+
33+
# Persist any new PATH entries for later steps
34+
IFS=':' read -ra NEW_PARTS <<<"$PATH"
35+
for p in "${NEW_PARTS[@]}"; do
36+
case ":$ORIGINAL_PATH:" in
37+
*":$p:"*) ;; # already present
38+
*) echo "$p" >>"$GITHUB_PATH" ;;
39+
esac
40+
done
41+
42+
# Keep HOMEBREW variables
43+
echo "HOMEBREW_PREFIX=$(brew --prefix)" >> "$GITHUB_ENV"
44+
echo "HOMEBREW_CELLAR=$(brew --cellar)" >> "$GITHUB_ENV"
45+
echo "HOMEBREW_REPOSITORY=$(brew --repository)" >> "$GITHUB_ENV"

.github/workflows/test.yml

Lines changed: 46 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,14 @@ on:
4040

4141
env:
4242
MAIN_BRANCH: ${{ inputs.main_branch || 'main' }}
43-
MAIN_OS: ${{ inputs.main_os || 'macos-latest' }}
43+
MAIN_OS: ${{ inputs.main_os || 'macos-latest' }}
4444
MAIN_PY_VER: ${{ inputs.main_py_ver || '3.10' }}
45-
TMATE: ${{ inputs.tmate || 'false' }}
46-
45+
TMATE: ${{ inputs.tmate || 'false' }}
4746
concurrency:
48-
group: ${{ github.workflow }}-${{ github.ref }}
47+
group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}
4948
cancel-in-progress: true
50-
49+
defaults:
50+
run: {shell: bash -Eeuo pipefail}
5151
jobs:
5252
install:
5353
strategy:
@@ -86,8 +86,6 @@ jobs:
8686
matrix:
8787
os: [macos-latest, ubuntu-latest]
8888
python-version: ['3.13', '3.12', '3.11', '3.10', '3.9']
89-
permissions:
90-
contents: write
9189
runs-on: ${{ matrix.os }}
9290
steps:
9391
- name: Check is main
@@ -110,13 +108,7 @@ jobs:
110108
echo "DEBUG=0" >> "$GITHUB_ENV"
111109
fi
112110
- name: Setup Homebrew
113-
run: |
114-
if ! which brew &>/dev/null;then
115-
echo "/home/linuxbrew/.linuxbrew/bin:/opt/homebrew/bin:$PATH" >> "$GITHUB_PATH"
116-
echo "HOMEBREW_PREFIX=$(brew --prefix)" >> "$GITHUB_ENV"
117-
echo "HOMEBREW_CELLAR=$(brew --cellar)" >> "$GITHUB_ENV"
118-
echo "HOMEBREW_REPOSITORY=$(brew --repository)" >> "$GITHUB_ENV"
119-
fi
111+
uses: ./.github/actions/setup-homebrew
120112
- name: Set pseudo git user
121113
run: |
122114
git config --global user.name "runner"
@@ -138,15 +130,50 @@ jobs:
138130
github_token: "${{github.token}}"
139131
pre-commit: "${{ env.IS_MAIN }}"
140132
tmate: "${{ env.DEBUG }}"
133+
prepare-pristine-homebrew:
134+
strategy:
135+
fail-fast: false
136+
matrix:
137+
#os: [macos-latest, ubuntu-latest]
138+
os: [macos-latest]
139+
runs-on: ${{ matrix.os }}
140+
steps:
141+
- uses: ./.github/actions/setup-homebrew
142+
- uses: ./.github/actions/pristine-homebrew
143+
with:
144+
os: ${{ runnner.os }}
145+
restore: false
141146
test-destructive:
142147
strategy:
143148
fail-fast: false
144149
matrix:
145150
python-version: ['3.9']
146-
test-path:
147-
- 'tests/test_destructive.py'
148-
runs-on: macos-latest
151+
pytest-group:
152+
- destructive_init
153+
- destructive_install_clean_default
154+
- destructive_install_clean_on_request
155+
- destructive_install_clean_leaves
156+
- destructive_install_clean_top_packages
157+
- destructive_cursor
158+
- destructive_brew_command
159+
- destructive_main_file_inheritance
160+
- destructive_get_tap_packs
161+
- destructive_get_leaves
162+
- destructive_update
163+
- destructive_dry_run
164+
- destructive_get_full_name
165+
- destructive_format_options
166+
- destructive_others
167+
#os: [macos-latest, ubuntu-latest]
168+
os: [macos-latest]
169+
needs: [prepare-pristine-homebrew]
170+
runs-on: ${{ matrix.os }}
149171
steps:
172+
- uses: ./.github/actions/setup-homebrew
173+
- uses: ./.github/actions/pristine-homebrew
174+
with:
175+
os: ${{ runnner.os }}
176+
restore: true
150177
- name: Set pseudo git user
151178
run: |
152179
git config --global user.name "runner"
@@ -158,12 +185,12 @@ jobs:
158185
python-version: "${{ matrix.python-version }}"
159186
setup-type: 'uv'
160187
pytest: 1
161-
pytest-tests-path: "${{ matrix.test-path }}"
188+
pytest-tests-path: "tests/test_destructive.py"
162189
pytest-ignore: ''
163190
pytest-separate-benchmark: 0
164191
coverage: 0
165192
pytest-cov-path: ""
166-
pytest-opt: "-n0 -m destructive"
193+
pytest-opt: "-n0 -m destructive and ${{ matrix.pytest-group }}"
167194
coverage-push: 0
168195
github_token: ""
169196
pre-commit: 0

pyproject.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ markers = [
2828
"destructive: tests only for destructive run.",
2929
]
3030
addopts = "-n auto -m 'not destructive'"
31+
filterwarnings = [
32+
"ignore::_pytest.warning_types.PytestUnknownMarkWarning",
33+
]
3134
testpaths = ["tests",]
3235

3336
[tool.ruff]

tests/scripts/clean_homebrew.sh

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,7 @@
11
#!/usr/bin/env bash
22

3-
brew list | xargs brew uninstall --force
4-
brew list --cask | xargs brew uninstall --cask --force
3+
brew list | xargs brew uninstall --zap --force
4+
brew list --cask | xargs brew uninstall --cask --zap --force
55
brew tap | xargs brew untap
66

77
rm -rf "$(brew --cache)"
8-
rm -rf "$(brew --prefix)/Caskroom/*"
9-
rm -rf ~/Library/Caches/Homebrew
10-
rm -rf ~/Library/Logs/Homebrew
11-
rm -rf ~/Library/Preferences/Homebrew

0 commit comments

Comments
 (0)