diff --git a/.github/kernel-matrix.conf b/.github/kernel-matrix.conf index bb875c2f3..4c9d00ec7 100644 --- a/.github/kernel-matrix.conf +++ b/.github/kernel-matrix.conf @@ -23,8 +23,6 @@ GITHUB_REGRESSION_KERNEL_SELECTORS="\ 6.1 \ 5.15 \ 5.10 \ -5.9 \ -5.8 \ 5.4 \ 4.19 \ 4.14 \ diff --git a/.github/workflows/ginkgo.yml b/.github/workflows/ginkgo.yml index a237bba15..669b1b4d7 100644 --- a/.github/workflows/ginkgo.yml +++ b/.github/workflows/ginkgo.yml @@ -66,63 +66,3 @@ jobs: ${{ runner.temp }}/ginkgo-image/*.json ${{ runner.temp }}/ginkgo-image/*.txt ${{ runner.temp }}/ginkgo-results/ - - user-kernels: - # Run the local scst_user specs on both sides of the Linux 5.9 boundary of - # dev_user_map_buf(). Named like the regression jobs; the build step checks - # each name against its scripts/ci/.env. - name: ${{ matrix.name }} - runs-on: ubuntu-24.04 - timeout-minutes: 120 - strategy: - fail-fast: false - matrix: - include: - - pin: kernel-5.8 - name: 5.8.18-300.fc33^Fedora^33 - - pin: kernel-5.9 - name: 5.9.16-200.fc33^Fedora^33 - steps: - - uses: actions/checkout@v4 - with: - persist-credentials: false - fetch-depth: 0 - - name: Select Ginkgo checks - id: changes - env: - BASE_SHA: ${{ github.event.pull_request.base.sha }} - HEAD_SHA: ${{ github.event.pull_request.head.sha }} - run: | - python3 scripts/ci/select_checks.py --check ginkgo --event "$GITHUB_EVENT_NAME" \ - --base "$BASE_SHA" --head "$HEAD_SHA" - - name: Install build and VM tools - if: steps.changes.outputs.run == 'true' - run: | - sudo apt-get update - sudo apt-get install -y qemu-system-x86 qemu-utils openssh-client e2fsprogs fakeroot - - name: Build SCST image with the kernel from scripts/ci/${{ matrix.pin }}.env - if: steps.changes.outputs.run == 'true' - timeout-minutes: 60 - env: - PIN: ${{ matrix.pin }} - NAME: ${{ matrix.name }} - run: | - source "scripts/ci/$PIN.env" - [[ $NAME == "$KERNEL_BUILD^"* ]] || { echo "::error::$NAME does not match $PIN.env"; exit 1; } - bash scripts/ci/build-image ginkgo "$RUNNER_TEMP/ginkgo-image" "$PIN" - - name: Run local scst_user tests against the compiled SCST - if: steps.changes.outputs.run == 'true' - run: | - python3 scripts/ci/vm.py ginkgo "$RUNNER_TEMP/ginkgo-image" \ - "$RUNNER_TEMP/ginkgo-results" --timeout 3000 --local-only --ginkgo-label user - - name: Save build logs, reports and serial console - if: always() && steps.changes.outputs.run == 'true' - uses: actions/upload-artifact@v4 - with: - name: ginkgo-${{ matrix.pin }}-results - retention-days: 7 - path: | - ${{ runner.temp }}/ginkgo-image/*.log - ${{ runner.temp }}/ginkgo-image/*.json - ${{ runner.temp }}/ginkgo-image/*.txt - ${{ runner.temp }}/ginkgo-results/ diff --git a/doc/CI.md b/doc/CI.md index 674756a46..464d5b45b 100644 --- a/doc/CI.md +++ b/doc/CI.md @@ -32,14 +32,18 @@ Kernel matrices are maintained through `.github/kernel-matrix.conf` and `nightly/conf/nightly.conf`; VM kernel pins are in `scripts/ci/kernel.env` and `kernel.SHA256SUMS` and must be updated together. -Further Ginkgo jobs run the local `user` specs on Fedora 33's Linux 5.8.18 and -5.9.16, pinned in `scripts/ci/kernel-5.8.env` and `kernel-5.9.env` with their -`SHA256SUMS`. Linux 5.9 is the first release where `fork()` copies pinned +Manual Ginkgo runs can use Fedora 33's Linux 5.8.18 and 5.9.16, pinned in +`scripts/ci/kernel-5.8.env` and `kernel-5.9.env` with their `SHA256SUMS`. +These kernels have no dedicated Ginkgo jobs or entries in the GitHub +regression matrix; the nightly support list is unchanged. +Linux 5.9 is the first release where `fork()` copies pinned ordinary anonymous pages, which scst_user relies on. The 5.8 fork fixture uses the documented `MADV_DONTFORK` protection; the 5.9 fixture exercises pinning without it. Both require correct geometry and data after the fork. The invalid-capacity specs check the exact SCSI rejection on both kernels. -The images are otherwise built the same way; these jobs have no iSCSI initiator. +The images are otherwise built the same way; `--local-only` runs have no +iSCSI initiator. The fork spec has the `manual` label and is excluded from +both automatic Ginkgo selections. ## Results @@ -75,8 +79,16 @@ python3 scripts/ci/vm.py ginkgo /tmp/scst-ginkgo-image /tmp/scst-ginkgo-results ``` Use `--ginkgo-label ci-push` for the master selection; omit it for all specs. -For the scst_user kernel jobs, add the pin name, such as `kernel-5.9`, to -`build-image` and run `vm.py` with `--local-only --ginkgo-label user`. +To run the fork spec manually on Linux 5.9: + +```sh +bash scripts/ci/build-image ginkgo /tmp/scst-ginkgo-5.9-image kernel-5.9 +python3 scripts/ci/vm.py ginkgo /tmp/scst-ginkgo-5.9-image /tmp/scst-ginkgo-5.9-results \ + --timeout 3000 --local-only --ginkgo-label 'user && manual' +``` + +Use `kernel-5.8` and new output directories for Linux 5.8. Use +`--ginkgo-label user` to include the invalid-capacity specs as well. `--local-only` intersects the resolved label expression with `local`; without `--ginkgo-label`, it selects all local specs. QEMU tries KVM then TCG; `--accel tcg` forces emulation. To check the VM diff --git a/scripts/ci/test_vm.py b/scripts/ci/test_vm.py index 68ba22954..57f557e1c 100644 --- a/scripts/ci/test_vm.py +++ b/scripts/ci/test_vm.py @@ -277,7 +277,8 @@ class ConsoleTests(unittest.TestCase): def test_ginkgo_label_sets_reach_both_suites_and_are_reported(self): for label, expression in (('basic || smoke', 'basic || smoke'), - ('ci-pr', 'basic || smoke'), ('ci-push', '!race')): + ('ci-pr', '(basic || smoke) && !manual'), + ('ci-push', '!race && !manual')): with self.subTest(label=label): self.output = self.root / label result, output = self.run_guest('ginkgo', ginkgo_label=label) @@ -298,7 +299,7 @@ class ConsoleTests(unittest.TestCase): def test_local_only_restricts_the_label_filter_to_local_specs(self): for label, expression in (('', 'local'), ('user', 'local && (user)'), ('basic || smoke', 'local && (basic || smoke)'), - ('ci-pr', 'local && (basic || smoke)')): + ('ci-pr', 'local && ((basic || smoke) && !manual)')): with self.subTest(label=label): self.output = self.root / f'filter-{label or "all"}' result, output = self.run_guest('ginkgo', ginkgo_label=label, local_only=True) diff --git a/tests/ginkgo/README.md b/tests/ginkgo/README.md index 426f07a8e..918e53d0c 100644 --- a/tests/ginkgo/README.md +++ b/tests/ginkgo/README.md @@ -57,13 +57,14 @@ by the local runner and VM supervisor: | Label set | Ginkgo expression | | --- | --- | -| `ci-pr` | `basic || smoke` | -| `ci-push` | `!race` | +| `ci-pr` | `(basic || smoke) && !manual` | +| `ci-push` | `!race && !manual` | Each set aliases a whole filter; its definition combines ordinary Ginkgo labels. Pass either a set name or a Ginkgo expression as `GINKGO_LABEL`. Manual workflow -runs use an empty filter and select all specs, including timing-dependent -`race` scenarios. Other stress tests remain in `ci-push`. +runs use an empty filter and select all specs, including `manual` and +timing-dependent `race` scenarios. The `manual` label excludes a spec from +both automatic CI sets. Other stress tests remain in `ci-push`. ```sh # List the pull-request selection: @@ -142,6 +143,15 @@ particular cached buffer to produce an error. The invalid-capacity cases require CHECK CONDITION with sense `0b/44/00` on every kernel. The specs need a C compiler on the target to build the hook; `ginkgo-test-build` also builds `usr`, and the local suite loads `scst_user`. +The fork spec is labelled `manual`; the invalid-capacity specs remain in +`smoke`. To select only the fork spec on a disposable local target: + +```sh +make ginkgo-list GINKGO_LABEL='user && manual' +make ginkgo-test-build GINKGO_CONFIG=tests/ginkgo/config.local.json GINKGO_LABEL='user && manual' +``` + +For manual VM runs on Linux 5.8 or 5.9, see [CI reproduction](../../doc/CI.md#local-reproduction). The `unmap` specs exercise temporary thin-provisioned fileio exports over `scst_local` and TCP iSCSI. They require util-linux `fallocate` on the target diff --git a/tests/ginkgo/internal/testrun/labels.json b/tests/ginkgo/internal/testrun/labels.json index 810906318..6c6349e03 100644 --- a/tests/ginkgo/internal/testrun/labels.json +++ b/tests/ginkgo/internal/testrun/labels.json @@ -1,4 +1,4 @@ { - "ci-pr": "basic || smoke", - "ci-push": "!race" + "ci-pr": "(basic || smoke) && !manual", + "ci-push": "!race && !manual" } diff --git a/tests/ginkgo/internal/testrun/labels_test.go b/tests/ginkgo/internal/testrun/labels_test.go index 29721989e..3627ab867 100644 --- a/tests/ginkgo/internal/testrun/labels_test.go +++ b/tests/ginkgo/internal/testrun/labels_test.go @@ -17,10 +17,17 @@ func TestLabelSetSelection(t *testing.T) { {"ci-pr", []string{"iscsi", "scsi", "smoke"}, true}, {"ci-pr", []string{"iscsi", "stress", "race", "issue-367"}, false}, {"ci-pr", []string{"local", "stress"}, false}, + {"ci-pr", []string{"local", "user", "manual"}, false}, + {"ci-pr", []string{"local", "basic", "manual"}, false}, + {"ci-pr", []string{"local", "smoke", "manual"}, false}, {"ci-push", []string{"local", "stress"}, true}, {" ci-push ", []string{"iscsi", "scsi"}, true}, {"ci-push", []string{"iscsi", "stress", "race", "issue-367"}, false}, + {"ci-push", []string{"local", "user", "manual"}, false}, {"", []string{"iscsi", "race"}, true}, + {"", []string{"local", "user", "manual"}, true}, + {"user && manual", []string{"local", "user", "manual"}, true}, + {"user && manual", []string{"local", "user", "negative", "smoke"}, false}, {"iscsi && race", []string{"iscsi", "race"}, true}, {"iscsi && race", []string{"local", "stress"}, false}, } { diff --git a/tests/ginkgo/suite/user_test.go b/tests/ginkgo/suite/user_test.go index b4ff04e09..b9159a587 100644 --- a/tests/ginkgo/suite/user_test.go +++ b/tests/ginkgo/suite/user_test.go @@ -116,7 +116,7 @@ func (f *fixture) stopUserDevice(ctx SpecContext, p *testhost.Process, name stri } } -var _ = Describe("User-space handler devices", Label("scsi", "user", "smoke"), func() { +var _ = Describe("User-space handler devices", Label("scsi", "user"), func() { DescribeTable("keep replies, geometry and data intact across a handler fault", func(ctx SpecContext, action string, capacityCDB []byte) { timeout := testcfg.Duration(cfg.CommandTimeout) @@ -169,9 +169,9 @@ var _ = Describe("User-space handler devices", Label("scsi", "user", "smoke"), f } Expect(err).To(Succeed()) }, - Entry("handler forks", "fork", nil), - Entry("handler returns an invalid READ CAPACITY(10) block length", Label("negative"), + Entry("handler forks", Label("manual"), "fork", nil), + Entry("handler returns an invalid READ CAPACITY(10) block length", Label("negative", "smoke"), "capacity", dataio.ReadCapacity10), - Entry("handler returns an invalid READ CAPACITY(16) block length", Label("negative"), + Entry("handler returns an invalid READ CAPACITY(16) block length", Label("negative", "smoke"), "capacity", dataio.ReadCapacity16)) })