diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index f5d599a06..c5d1f1337 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -31,7 +31,7 @@ jobs: uses: actions/setup-go@v3 with: go-version: ${{ matrix.go-version }} - - name: install dependencies + - name: Install dependencies run: | sudo apt-get update sudo apt-get install -yy lxc-utils lxc-dev libacl1-dev jq libcap-dev libseccomp-dev libpam-dev bats parallel libzstd-dev diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 3ade24199..7986fe444 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -18,3 +18,12 @@ jobs: ["1.20.x"] privilege-level: >- ["unpriv", "priv"] + coverage: + uses: ./.github/workflows/coverage.yaml + with: + # note >-, args needs to be strings to be used as inputs + # for the reusable build.yaml workflow + go-version: >- + ["1.20.x"] + privilege-level: >- + ["unpriv", "priv"] diff --git a/.github/workflows/coverage.yaml b/.github/workflows/coverage.yaml new file mode 100644 index 000000000..564fbab56 --- /dev/null +++ b/.github/workflows/coverage.yaml @@ -0,0 +1,58 @@ +name: Reusable stacker build for coverage +on: + workflow_call: + inputs: + go-version: + required: true + type: string + description: 'Stringified JSON object listing go versions' + privilege-level: + required: true + type: string + description: 'Stringified JSON object listing stacker privilege-level' +jobs: + build: + runs-on: ubuntu-22.04 + services: + registry: + image: registry:2 + ports: + - 5000:5000 + strategy: + matrix: + go-version: ${{fromJson(inputs.go-version)}} + privilege-level: ${{fromJson(inputs.privilege-level)}} + name: "golang ${{ matrix.go-version }} privilege ${{ matrix.privilege-level }}" + steps: + - uses: actions/checkout@v3 + - uses: benjlevesque/short-sha@v2.1 + id: short-sha + - name: Set up golang ${{ matrix.go-version }} + uses: actions/setup-go@v3 + with: + go-version: ${{ matrix.go-version }} + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -yy lxc-utils lxc-dev libacl1-dev jq libcap-dev libseccomp-dev libpam-dev bats parallel libzstd-dev + GO111MODULE=off go get github.com/opencontainers/umoci/cmd/umoci + sudo cp ~/go/bin/umoci /usr/bin + curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin + sudo apt-get install -yy autoconf automake make autogen autoconf libtool binutils git squashfs-tools libcryptsetup-dev libdevmapper-dev cryptsetup-bin squashfuse + (cd /tmp && git clone https://github.com/AgentD/squashfs-tools-ng && cd squashfs-tools-ng && ./autogen.sh && ./configure --prefix=/usr && make -j2 && sudo make -j2 install && sudo ldconfig -v) + (cd /tmp && git clone https://github.com/anuvu/squashfs && cd squashfs && make && sudo cp squashtool/squashtool /usr/bin) + - if: github.event_name != 'release' || github.event.action != 'published' + name: Build and test + run: | + export GOCOVERDIR=. + make check-cov GCOVERDIR=. PRIVILEGE_LEVEL=${{ matrix.privilege-level }} + ls -altr + go tool covdata textfmt -i $GOCOVERDIR -o coverage-${{ matrix.privilege-level }}.txt + go tool covdata percent -i $GOCOVERDIR + ls -altr + env: + REGISTRY_URL: localhost:5000 + - name: Upload code coverage + uses: codecov/codecov-action@v3 + with: + files: coverage-${{ matrix.privilege-level}}.txt diff --git a/Makefile b/Makefile index 66fa3dfea..43ce60e44 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ BUILD_TAGS = exclude_graphdriver_btrfs exclude_graphdriver_devicemapper containe STACKER_OPTS=--oci-dir=.build/oci --roots-dir=.build/roots --stacker-dir=.build/stacker --storage-type=overlay -build_stacker = go build -tags "$(BUILD_TAGS) $1" -ldflags "-X main.version=$(VERSION_FULL) -X main.lxc_version=$(LXC_VERSION) $2" -o $3 ./cmd/stacker +build_stacker = go build $1 -tags "$(BUILD_TAGS) $2" -ldflags "-X main.version=$(VERSION_FULL) -X main.lxc_version=$(LXC_VERSION) $3" -o $4 ./cmd/stacker STACKER_DOCKER_BASE?=docker:// STACKER_BUILD_BASE_IMAGE?=$(STACKER_DOCKER_BASE)alpine:edge @@ -23,15 +23,30 @@ stacker: stacker-dynamic --substitute STACKER_BUILD_BASE_IMAGE=$(STACKER_BUILD_BASE_IMAGE) \ --substitute LXC_CLONE_URL=$(LXC_CLONE_URL) \ --substitute LXC_BRANCH=$(LXC_BRANCH) \ - --substitute VERSION_FULL=$(VERSION_FULL) + --substitute VERSION_FULL=$(VERSION_FULL) \ + --substitute WITH_COV=no + +stacker-cov: stacker-dynamic + ./stacker-dynamic --debug $(STACKER_OPTS) build \ + -f build.yaml --shell-fail \ + --substitute STACKER_BUILD_BASE_IMAGE=$(STACKER_BUILD_BASE_IMAGE) \ + --substitute LXC_CLONE_URL=$(LXC_CLONE_URL) \ + --substitute LXC_BRANCH=$(LXC_BRANCH) \ + --substitute VERSION_FULL=$(VERSION_FULL) \ + --substitute WITH_COV=yes stacker-static: $(GO_SRC) go.mod go.sum cmd/stacker/lxc-wrapper/lxc-wrapper - $(call build_stacker,static_build,-extldflags '-static',stacker) + $(call build_stacker,,static_build,-extldflags '-static',stacker) + +# can't use a comma in func call args, so do this instead +, := , +stacker-static-cov: $(GO_SRC) go.mod go.sum cmd/stacker/lxc-wrapper/lxc-wrapper + $(call build_stacker,-cover -coverpkg="./pkg/...$(,)./cmd/...",static_build,-extldflags '-static',stacker) # TODO: because we clean lxc-wrapper in the nested build, this always rebuilds. # Could find a better way to do this. stacker-dynamic: $(GO_SRC) go.mod go.sum cmd/stacker/lxc-wrapper/lxc-wrapper - $(call build_stacker,,,stacker-dynamic) + $(call build_stacker,,,,stacker-dynamic) cmd/stacker/lxc-wrapper/lxc-wrapper: cmd/stacker/lxc-wrapper/lxc-wrapper.c make -C cmd/stacker/lxc-wrapper LDFLAGS=-static LDLIBS="$(shell pkg-config --static --libs lxc) -lpthread -ldl" lxc-wrapper @@ -61,6 +76,18 @@ check: stacker lint $(shell [ -z $(PRIVILEGE_LEVEL) ] || echo --privilege-level=$(PRIVILEGE_LEVEL)) \ $(patsubst %,test/%.bats,$(TEST)) +check-cov: stacker-cov lint + sudo -E PATH="$$PATH" \ + LXC_BRANCH=$(LXC_BRANCH) \ + LXC_CLONE_URL=$(LXC_CLONE_URL) \ + STACKER_BUILD_BASE_IMAGE=$(STACKER_BUILD_BASE_IMAGE) \ + STACKER_BUILD_CENTOS_IMAGE=$(STACKER_BUILD_CENTOS_IMAGE) \ + STACKER_BUILD_UBUNTU_IMAGE=$(STACKER_BUILD_UBUNTU_IMAGE) \ + GOCOVERDIR=. \ + ./test/main.py \ + $(shell [ -z $(PRIVILEGE_LEVEL) ] || echo --privilege-level=$(PRIVILEGE_LEVEL)) \ + $(patsubst %,test/%.bats,$(TEST)) + .PHONY: vendorup vendorup: go get -u diff --git a/build.yaml b/build.yaml index ee75c9c14..506006c6a 100644 --- a/build.yaml +++ b/build.yaml @@ -89,4 +89,8 @@ build: export VERSION_FULL=${{VERSION_FULL}} make -C /stacker-tree/cmd/stacker/lxc-wrapper clean - make -C /stacker-tree stacker-static + if [ x${{WITH_COV}} = x"yes" ]; then + make -C /stacker-tree stacker-static-cov + else + make -C /stacker-tree stacker-static + fi diff --git a/pkg/container/userns.go b/pkg/container/userns.go index 25c4ce76d..151175441 100644 --- a/pkg/container/userns.go +++ b/pkg/container/userns.go @@ -26,7 +26,7 @@ func MaybeRunInNamespace(config types.StackerConfig, userCmd []string) error { cmd.Stdin = os.Stdin cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr - cmd.Env = env + cmd.Env = append(env, "GOCOVERDIR=.") return errors.WithStack(cmd.Run()) } diff --git a/pkg/stacker/build.go b/pkg/stacker/build.go index 3429effd2..1f732f885 100644 --- a/pkg/stacker/build.go +++ b/pkg/stacker/build.go @@ -609,6 +609,9 @@ func runInternalGoSubcommand(config types.StackerConfig, args []string) error { c.Stdin = os.Stdin c.Stdout = os.Stdout c.Stderr = os.Stderr + // FIXME: add coverage flag + env := []string{"GOCOVERDIR=."} + c.Env = env return errors.WithStack(c.Run()) } diff --git a/test/helpers.bash b/test/helpers.bash index 9f82473fd..286621aeb 100644 --- a/test/helpers.bash +++ b/test/helpers.bash @@ -42,6 +42,7 @@ function image_copy { STACKER_DOCKER_BASE=${STACKER_DOCKER_BASE:-docker://} STACKER_BUILD_CENTOS_IMAGE=${STACKER_BUILD_CENTOS_IMAGE:-${STACKER_DOCKER_BASE}centos:latest} STACKER_BUILD_UBUNTU_IMAGE=${STACKER_BUILD_UBUNTU_IMAGE:-${STACKER_DOCKER_BASE}ubuntu:latest} +GOCOVERDIR=${GOCOVERDIR:-.} ( flock 9 [ -f "$ROOT_DIR/test/centos/index.json" ] || (image_copy "${STACKER_BUILD_CENTOS_IMAGE}" "oci:$ROOT_DIR/test/centos:latest" && chmod -R 777 "$ROOT_DIR/test/centos") @@ -49,6 +50,7 @@ STACKER_BUILD_UBUNTU_IMAGE=${STACKER_BUILD_UBUNTU_IMAGE:-${STACKER_DOCKER_BASE}u ) 9<$ROOT_DIR/test/main.py export CENTOS_OCI="$ROOT_DIR/test/centos:latest" export UBUNTU_OCI="$ROOT_DIR/test/ubuntu:latest" +export GOCOVERDIR="." function sha() { echo $(sha256sum $1 | cut -f1 -d" ") diff --git a/test/main.py b/test/main.py index c13d28106..a03719231 100755 --- a/test/main.py +++ b/test/main.py @@ -27,6 +27,7 @@ env = os.environ.copy() env["PRIVILEGE_LEVEL"] = priv + env["GOCOVERDIR"] = "." print("running tests in modes:", priv) try: