4343 make test_unit &&
4444 [[ ! $(jq -s -c 'map(select(.Action == "fail")) | .[]' test/unit/gotest.json) ]]
4545 - name : Upload coverage to Codecov
46- uses : codecov/codecov-action@671740ac38dd9b0130fbe1cec585b89eea48d3de # v5.5.2
46+ uses : codecov/codecov-action@57e3a136b779b570ffcdbf80b3bdc90e7fab3de2 # v6.0.0
4747 if : failure() || success()
4848 with :
4949 name : unittests
5757 output : test/unit/gotest.junit.xml
5858 if : failure() || success()
5959 - name : Archive the JUnit XML report
60- uses : actions/upload-artifact@v6
60+ uses : actions/upload-artifact@v7
6161 with :
6262 name : unit-tests-junit
6363 path : test/unit/gotest.junit.xml
7070 output : test/unit/gotest.html
7171 if : failure() || success()
7272 - name : Archive the HTML report
73- uses : actions/upload-artifact@v6
73+ uses : actions/upload-artifact@v7
7474 with :
7575 name : unit-tests-html
7676 path : test/unit/gotest.html
@@ -120,7 +120,7 @@ jobs:
120120 output : test/cli/cli-tests.junit.xml
121121 if : failure() || success()
122122 - name : Archive JUnit XML report
123- uses : actions/upload-artifact@v6
123+ uses : actions/upload-artifact@v7
124124 with :
125125 name : cli-tests-junit
126126 path : test/cli/cli-tests.junit.xml
@@ -133,7 +133,7 @@ jobs:
133133 output : test/cli/cli-tests.html
134134 if : failure() || success()
135135 - name : Archive HTML report
136- uses : actions/upload-artifact@v6
136+ uses : actions/upload-artifact@v7
137137 with :
138138 name : cli-tests-html
139139 path : test/cli/cli-tests.html
@@ -149,6 +149,59 @@ jobs:
149149 run : cat test/cli/cli-tests.md >> $GITHUB_STEP_SUMMARY
150150 if : failure() || success()
151151
152+ # FUSE filesystem tests (require /dev/fuse and fusermount)
153+ # Runs both FUSE unit tests (./fuse/...) and CLI integration tests (./test/cli/fuse/...)
154+ fuse-tests :
155+ if : github.repository == 'ipfs/kubo' || github.event_name == 'workflow_dispatch'
156+ runs-on : ${{ fromJSON(github.repository == 'ipfs/kubo' && '["self-hosted", "linux", "x64", "2xlarge"]' || '"ubuntu-latest"') }}
157+ concurrency :
158+ group : fuse-tests-${{ github.repository }}
159+ cancel-in-progress : false
160+ # A normal run takes ~3min. 6min gives roughly 2x and lets Go's 4min
161+ # test timeout fire first (printing a stack trace) on a hang, instead
162+ # of GitHub silently cancelling the job.
163+ timeout-minutes : 6
164+ env :
165+ # Dump all goroutines on a test panic, not just the panicking one,
166+ # so we can see which test is actually hung.
167+ GOTRACEBACK : all
168+ TEST_FUSE : 1
169+ defaults :
170+ run :
171+ shell : bash
172+ steps :
173+ - name : Check out Kubo
174+ uses : actions/checkout@v6
175+ - name : Set up Go
176+ uses : actions/setup-go@v6
177+ with :
178+ go-version-file : ' go.mod'
179+ - name : Install FUSE
180+ run : |
181+ if ! command -v fusermount3 &>/dev/null && ! command -v fusermount &>/dev/null; then
182+ sudo apt-get update
183+ sudo apt-get install -y fuse3
184+ fi
185+ - name : Clean up stale FUSE mounts
186+ run : |
187+ # On shared self-hosted runners, leftover mounts from previous
188+ # runs can exhaust the kernel FUSE mount limit (mount_max).
189+ # Unit tests mount with FsName "kubo-test"; CLI tests mount
190+ # under the harness temp dir (ipfs/ipns/mfs subdirectories).
191+ awk '$1 == "kubo-test" || $2 ~ /\/tmp\/.*\/(ipfs|ipns|mfs)$/ { print $2 }' /proc/mounts 2>/dev/null \
192+ | while read -r mp; do
193+ fusermount3 -uz "$mp" 2>/dev/null || fusermount -uz "$mp" 2>/dev/null || true
194+ done
195+ - name : Run FUSE tests
196+ run : make test_fuse
197+ - name : Clean up FUSE mounts
198+ if : always()
199+ run : |
200+ awk '$1 == "kubo-test" || $2 ~ /\/tmp\/.*\/(ipfs|ipns|mfs)$/ { print $2 }' /proc/mounts 2>/dev/null \
201+ | while read -r mp; do
202+ fusermount3 -uz "$mp" 2>/dev/null || fusermount -uz "$mp" 2>/dev/null || true
203+ done
204+
152205 # Example tests (kubo-as-a-library)
153206 example-tests :
154207 if : github.repository == 'ipfs/kubo' || github.event_name == 'workflow_dispatch'
0 commit comments