Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,26 @@
# See the License for the specific language governing permissions and
# limitations under the License.

name: Gitleaks Pull Request Scan
name: Gitleaks

# Gitleaks runs only on pull requests. The upstream action's diff mode checks
# out refs/pull/<N>/merge and scans just the PR range; it relies on
# github.event.number, which exists only for pull_request events. (A push-event
# run produces an empty refspec — `+refs/pull//merge:...` — and `git fetch`
# fails, so we deliberately do not trigger on push.)
on:
pull_request:
types: [opened, synchronize, reopened]

permissions:
contents: read
pull-requests: read

# Cancel superseded runs on the same PR ref so rapid-fire pushes don't pile up.
concurrency:
group: gitleaks-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
gitleaks_scan:
name: Gitleaks scan
Expand Down
106 changes: 106 additions & 0 deletions .github/workflows/unit-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
# Copyright 2026 Flant JSC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

name: Unit Tests

# Triggers:
# push: every push to any branch — gives feature branches a green/red
# signal without needing an open PR.
# pull_request: PRs targeting main — required so the check is also evaluated
# for fork PRs (whose push events do not run in the upstream repo).
on:
push: {}
pull_request:
branches: [main]
types: [opened, synchronize, reopened]

permissions:
contents: read
# Required by actions/upload-code-coverage to publish the coverage report.
code-quality: write
# On push events the action resolves any open PR for the ref via `gh pr list`,
# which needs read access to pull requests.
pull-requests: read

# Cancel in-flight runs for the same ref when a new commit lands. Each push
# trigger then evaluates only the latest SHA, which keeps CI minutes bounded
# on rapid-fire force-pushes.
concurrency:
group: unit-tests-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
unit-tests:
name: Build, vet & unit test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: actions/setup-go@v5
with:
go-version-file: go.mod
cache: true

- name: Download modules
run: go mod download

# Compile everything (including the e2e suites under ./tests/...) to catch
# refactor breakage in code that the unit-tests package set deliberately
# does not execute.
- name: Build
run: go build ./...

- name: Vet
run: go vet ./...

# Unit tests run with -race (catches data races in retry.Do and module
# configuration goroutines) and -shuffle=on (surfaces ordering bugs in
# tests that touch package-level env vars in internal/config).
# We restrict the set to ./internal/... ./pkg/... so the e2e suites in
# ./tests/... do not execute (they require real VMs/clusters/SSH).
- name: Unit tests (race + coverage)
run: |
go test -race -shuffle=on -covermode=atomic \
-coverprofile=coverage.out \
./internal/... ./pkg/...
echo "Total coverage:"
go tool cover -func=coverage.out | tail -1

# actions/upload-code-coverage consumes Cobertura XML, so convert the Go
# coverage profile produced above into that format.
- name: Convert coverage to Cobertura XML
run: |
go run github.com/boumenot/gocover-cobertura@latest \
< coverage.out > coverage.xml

# Publishes the report via GitHub's native code-coverage feature. On push
# to the default branch it sets the baseline; on push to a branch with an
# open PR the github-code-quality[bot] posts the comparison on that PR.
- name: Upload code coverage
uses: actions/upload-code-coverage@v1
with:
file: coverage.xml
language: Go
label: code-coverage/go
fail-on-error: false

- name: Upload coverage artifact
if: always()
uses: actions/upload-artifact@v4
with:
name: coverage
path: |
coverage.out
coverage.xml
if-no-files-found: warn
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Coverage artifacts emitted by `make cover` / unit-tests CI job.
coverage.out
coverage.html
9 changes: 9 additions & 0 deletions .gitleaksignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# gitleaks finding fingerprints to ignore (format: commit:file:rule:startline).
#
# False positive: base64("user:token") == "dXNlcjp0b2tlbg==" is a table-driven
# unit-test fixture in TestBase64Encode, not a real credential. The finding is
# anchored to commit 5f1edc2, which first introduced the line *before* the
# inline `gitleaks:allow` comment was added (in a later commit). A diff scan
# walks the whole PR commit range, so the later inline suppression cannot hide
# the earlier commit — we ignore it here by fingerprint instead.
5f1edc2ea49b6f107c55faeaa630bae63fe749f0:internal/kubernetes/commander/client_test.go:generic-api-key:75
88 changes: 88 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# CLAUDE.md

Guidance for working in this repository. Read the linked docs in `docs/` before making
non-trivial changes.

## What this is

`github.com/deckhouse/storage-e2e` — an end-to-end test framework for Deckhouse storage
components. It provisions/manages test clusters (VMs via virtualization, existing clusters,
or Deckhouse Commander), wires up storage modules, and runs Ginkgo-based e2e suites.

**It is imported as a library by other repos** (e.g. `csi-ceph`), so the `pkg/` public API
must stay backward compatible.

- Module path: `github.com/deckhouse/storage-e2e`, Go `1.26`.
- Layers (top → bottom): `tests/` → `pkg/testkit` → `internal/` domain logic →
`internal/infrastructure` → `k8s client-go`. See ARCHITECTURE for the full tree.

## Documentation map (`docs/`)

| Doc | Purpose |
|---|---|
| [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) | Package structure, layers, components, env-var reference. **Source of truth for layout.** |
| [docs/FUNCTIONS_GLOSSARY.md](docs/FUNCTIONS_GLOSSARY.md) | All exported `pkg/` functions, grouped by resource. Check before adding new exported functions. |
| [docs/TODO.md](docs/TODO.md) | Global TODO list (managed via the `/todo` convention below). |
| [docs/WORKLOG.md](docs/WORKLOG.md) | Dated change log. Append an entry on every code change. |
| [docs/TESTS_IMPLEMENTATION_PLAN.md](docs/TESTS_IMPLEMENTATION_PLAN.md) | Plan for unit-test coverage and the CI/CD pipeline (build/vet/test, merge-blocking). |
| [docs/TESTING_STRATEGY.md](docs/TESTING_STRATEGY.md) | *(to be created)* Testing conventions, unit-vs-e2e boundaries, fakes/httptest patterns, coverage policy. |

Also useful: [README.md](README.md) (quick start, env vars, running suites),
[internal/README.md](internal/README.md), [internal/logger/README.md](internal/logger/README.md).

## Build, vet & test

```bash
go build ./... # compiles everything (incl. e2e suites)
go vet ./...
go test -race -shuffle=on ./internal/... ./pkg/... # unit tests only — no cluster needed
```

- **Unit tests** live next to sources under `internal/` and `pkg/`; they are hermetic
(no SSH, no cluster, no network — use `httptest` and `client-go` fakes).
- **E2E suites** live under `tests/` and require real VMs/clusters + env vars
(`SSH_HOST`, `DKP_LICENSE_KEY`, `TEST_CLUSTER_CREATE_MODE`, …). **Do not run them in
unit/CI flows.** Run one explicitly, e.g.:
`go test -timeout=240m -v ./tests/<name> -count=1`.
- New tests/CI conventions are described in TESTS_IMPLEMENTATION_PLAN.md (and, once it
exists, TESTING_STRATEGY.md).

## Project conventions (must follow)

These mirror the rules in `.cursor/rules/` — apply them whether or not you use Cursor.

1. **Backward compatibility (`pkg/`).** Removing/renaming an exported symbol, changing a
signature, or changing observed behavior is a breaking change. **Ask the user first**,
prefer adding alongside (deprecate, don't delete), and tag the WORKLOG entry with
`[Possible compatibility break]`.

2. **Functions glossary.** Before adding a new exported `pkg/` function, search
[docs/FUNCTIONS_GLOSSARY.md](docs/FUNCTIONS_GLOSSARY.md) for an existing one. Reuse/extend
if it exists; otherwise add the new function to the glossary in the matching section.

3. **Versatile functions.** `pkg/` functions must be general-purpose: return data not
decisions, no hardcoded names/indices, accept broad inputs (`context`, `rest.Config`)
and return concrete K8s objects, no empty wrappers.

4. **Architecture sync.** On structural changes (add/remove/rename a package or file, move
between layers, new cluster mode, new env var, changed core types), update the affected
sections of [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md). Only touch affected sections.

5. **Work log.** After any change to `*.go`, `*.yml`, `*.yaml`, `*.tpl`, or `*.sh`, append a
one-line entry to [docs/WORKLOG.md](docs/WORKLOG.md) under today's `## YYYY-MM-DD`
heading: `- **Type** description` (Type ∈ Add/Remove/Rename/Refactor/Bugfix/Update/Move).
Append only; never edit previous days' entries.

6. **`/todo` command.** When a message starts with `/todo`, manage items in
[docs/TODO.md](docs/TODO.md) (Add / Remove / Check|List / Done), then record a WORKLOG entry.

7. **Commits/PRs.** Do not add AI co-author trailers (no `Co-Authored-By: Claude` /
"Generated with Claude").

## Creating new e2e tests

Use the template + script (don't hand-roll suites, and don't edit `tests/test-template`):

```bash
cd tests && ./create-test.sh <your-test-name>
```
52 changes: 52 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Copyright 2026 Flant JSC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# Convenience targets for local development. CI runs the same commands so
# `make test` locally is equivalent to the CI unit-test job.
#
# Unit tests deliberately exclude ./tests/... (e2e suites that require real
# VMs/clusters/SSH). Use `make e2e` for hints on running individual suites.

UNIT_PKGS := ./internal/... ./pkg/...

.PHONY: help build vet test cover e2e clean

help: ## Print this help.
@awk 'BEGIN {FS = ":.*##"; printf "Targets:\n"} \
/^[a-zA-Z0-9_-]+:.*##/ {printf " \033[36m%-10s\033[0m %s\n", $$1, $$2}' \
$(MAKEFILE_LIST)

build: ## Compile every package (incl. e2e suites for refactor-breakage check).
go build ./...

vet: ## Run go vet on every package.
go vet ./...

test: ## Unit tests with -race -shuffle=on (no cluster needed).
go test -race -shuffle=on $(UNIT_PKGS)

cover: ## Unit tests + coverage profile + total %.
go test -race -shuffle=on -covermode=atomic \
-coverprofile=coverage.out $(UNIT_PKGS)
@echo "Total coverage:"
@go tool cover -func=coverage.out | tail -1

e2e: ## Hints for running an individual e2e suite (requires VMs/cluster).
@echo "E2E suites require real infra. Examples:"
@echo " go test -timeout=240m -v ./tests/test-template -count=1"
@echo " go test -timeout=240m -v ./tests/csi-all-stress-tests -count=1"
@echo "See README.md for required env vars (SSH_HOST, DKP_LICENSE_KEY, ...)."

clean: ## Remove build / coverage artifacts.
rm -f coverage.out
Loading
Loading