Run tests in parallel and output github formats on workflow (#543)

* Run tests in parallel and output github formats on workflow

Signed-off-by: Itxaka <itxaka@kairos.io>

* Fix broken parallel tests

We were using a fixed file for the tests which several tests could be
accessing at the same time.

This fixes it by setting a temp random file at the test start

Signed-off-by: Itxaka <itxaka@kairos.io>

* Fix the tests logging to stdout

Signed-off-by: Itxaka <itxaka@kairos.io>

* Drop the verbose

Signed-off-by: Itxaka <itxaka@kairos.io>

* Fix agent test

Signed-off-by: Itxaka <itxaka@kairos.io>

* Let the event consumer create the logfile or whatever

Signed-off-by: Itxaka <itxaka@kairos.io>

* Drop Focus

Signed-off-by: Itxaka <itxaka@kairos.io>

---------

Signed-off-by: Itxaka <itxaka@kairos.io>
This commit is contained in:
Itxaka 2024-09-17 17:51:11 +02:00 committed by GitHub
parent 3e99d75331
commit fbb64f2a82
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 41 additions and 45 deletions

View File

@ -13,21 +13,20 @@ jobs:
unit-tests: unit-tests:
strategy: strategy:
matrix: matrix:
go-version: [ "1.23-bookworm" ] go-version: [ "1.23" ]
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout code - name: Checkout code
uses: actions/checkout@v4 uses: actions/checkout@v4
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Install earthly - name: Setup Go environment
uses: Luet-lab/luet-install-action@v1 uses: actions/setup-go@v5.0.2
with: with:
repository: quay.io/kairos/packages go-version: '${{ matrix.go-version }}'
packages: utils/earthly
- name: Run tests - name: Run tests
run: | run: |
earthly -P +test --GO_VERSION=${{ matrix.go-version }} go run github.com/onsi/ginkgo/v2/ginkgo run -p --github-output --covermode=atomic --coverprofile=coverage.out --race -r ./...
- name: Codecov - name: Codecov
uses: codecov/codecov-action@v4 uses: codecov/codecov-action@v4
env: env:

View File

@ -23,7 +23,7 @@ test:
ARG TEST_PATHS=./... ARG TEST_PATHS=./...
ARG LABEL_FILTER= ARG LABEL_FILTER=
ENV CGO_ENABLED=1 ENV CGO_ENABLED=1
RUN go run github.com/onsi/ginkgo/v2/ginkgo run --label-filter "$LABEL_FILTER" --covermode=atomic --coverprofile=coverage.out -v --race -r $TEST_PATHS RUN go run github.com/onsi/ginkgo/v2/ginkgo run -p --label-filter "$LABEL_FILTER" --covermode=atomic --coverprofile=coverage.out --race -r $TEST_PATHS
SAVE ARTIFACT coverage.out AS LOCAL coverage.out SAVE ARTIFACT coverage.out AS LOCAL coverage.out
version: version:

View File

@ -2,17 +2,15 @@ package agent
import ( import (
"fmt" "fmt"
v1 "github.com/kairos-io/kairos-agent/v2/pkg/types/v1"
"os"
"path/filepath"
hook "github.com/kairos-io/kairos-agent/v2/internal/agent/hooks" hook "github.com/kairos-io/kairos-agent/v2/internal/agent/hooks"
"github.com/kairos-io/kairos-agent/v2/internal/bus" "github.com/kairos-io/kairos-agent/v2/internal/bus"
config "github.com/kairos-io/kairos-agent/v2/pkg/config" config "github.com/kairos-io/kairos-agent/v2/pkg/config"
v1 "github.com/kairos-io/kairos-agent/v2/pkg/types/v1"
events "github.com/kairos-io/kairos-sdk/bus" events "github.com/kairos-io/kairos-sdk/bus"
"github.com/kairos-io/kairos-sdk/collector" "github.com/kairos-io/kairos-sdk/collector"
"github.com/kairos-io/kairos-sdk/machine" "github.com/kairos-io/kairos-sdk/machine"
"github.com/kairos-io/kairos-sdk/utils" "github.com/kairos-io/kairos-sdk/utils"
"os"
) )
// Run starts the agent provider emitting the bootstrap event. // Run starts the agent provider emitting the bootstrap event.
@ -38,17 +36,7 @@ func Run(opts ...Option) error {
return nil return nil
} }
os.MkdirAll("/var/log/kairos", 0600) //nolint:errcheck fileName := "/var/log/kairos/agent-provider.log"
fileName := filepath.Join("/var/log/kairos", "agent-provider.log")
// Create if not exist
if _, err := os.Stat(fileName); err != nil {
err = os.WriteFile(fileName, []byte{}, os.ModePerm)
if err != nil {
return err
}
}
if !machine.SentinelExist("firstboot") { if !machine.SentinelExist("firstboot") {
spec := v1.EmptySpec{} spec := v1.EmptySpec{}

View File

@ -28,7 +28,7 @@ var _ = Describe("Bootstrap provider", func() {
defer os.RemoveAll(f) defer os.RemoveAll(f)
wd, _ := os.Getwd() wd, _ := os.Getwd()
os.WriteFile(filepath.Join(wd, "agent-provider-test"), []byte(testProvider), 0655) os.WriteFile(filepath.Join(wd, "agent-provider-test"), []byte(testProvider), 0777)
defer os.RemoveAll(filepath.Join(wd, "agent-provider-test")) defer os.RemoveAll(filepath.Join(wd, "agent-provider-test"))

View File

@ -94,13 +94,15 @@ var _ = Describe("Install action tests", func() {
}) })
Describe("Install Action", Label("install"), func() { Describe("Install Action", Label("install"), func() {
var device, cmdFail string var device, cmdFail, tmpdir string
var err error var err error
var spec *v1.InstallSpec var spec *v1.InstallSpec
var installer *action.InstallAction var installer *action.InstallAction
BeforeEach(func() { BeforeEach(func() {
device = "/tmp/test.img" tmpdir, err = os.MkdirTemp("", "install-*")
Expect(err).Should(BeNil())
device = filepath.Join(tmpdir, "test.img")
Expect(os.RemoveAll(device)).Should(Succeed()) Expect(os.RemoveAll(device)).Should(Succeed())
// at least 2Gb in size as state is set to 1G // at least 2Gb in size as state is set to 1G
_, err = diskfs.Create(device, 2*1024*1024*1024, diskfs.Raw, 512) _, err = diskfs.Create(device, 2*1024*1024*1024, diskfs.Raw, 512)
@ -201,6 +203,7 @@ var _ = Describe("Install action tests", func() {
} }
Expect(os.RemoveAll(device)).ToNot(HaveOccurred()) Expect(os.RemoveAll(device)).ToNot(HaveOccurred())
ghwTest.Clean() ghwTest.Clean()
Expect(os.RemoveAll(tmpdir)).ToNot(HaveOccurred())
}) })
It("Successfully installs", func() { It("Successfully installs", func() {

View File

@ -49,14 +49,19 @@ var _ = Describe("Types", Label("types", "config"), func() {
var logger sdkTypes.KairosLogger var logger sdkTypes.KairosLogger
var ci *v1mock.FakeCloudInitRunner var ci *v1mock.FakeCloudInitRunner
var c *config.Config var c *config.Config
var memLog bytes.Buffer
BeforeEach(func() { BeforeEach(func() {
memLog = bytes.Buffer{}
logger = sdkTypes.NewBufferLogger(&memLog)
logger.SetLevel("debug")
fs, cleanup, err = vfst.NewTestFS(nil) fs, cleanup, err = vfst.NewTestFS(nil)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
mounter = v1mock.NewErrorMounter() mounter = v1mock.NewErrorMounter()
runner = v1mock.NewFakeRunner() runner = v1mock.NewFakeRunner()
client = &v1mock.FakeHTTPClient{} client = &v1mock.FakeHTTPClient{}
sysc = &v1mock.FakeSyscall{} sysc = &v1mock.FakeSyscall{}
logger = sdkTypes.NewNullLogger()
ci = &v1mock.FakeCloudInitRunner{} ci = &v1mock.FakeCloudInitRunner{}
c = config.NewConfig( c = config.NewConfig(
config.WithFs(fs), config.WithFs(fs),
@ -535,10 +540,11 @@ cloud-init-paths:
ghwTest.Clean() ghwTest.Clean()
}) })
It("Reads properly the cloud config for install", func() { It("Reads properly the cloud config for install", func() {
cfg, err := config.Scan(collector.Directories([]string{dir}...), cfg, err := config.ScanNoLogs(collector.Directories([]string{dir}...),
collector.NoLogs, collector.NoLogs,
) )
cfg.Fs = fs cfg.Fs = fs
cfg.Logger = logger
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
// Once we got the cfg override the fs to our test fs // Once we got the cfg override the fs to our test fs
@ -559,13 +565,14 @@ cloud-init-paths:
}) })
It("Reads properly the cloud config for reset", func() { It("Reads properly the cloud config for reset", func() {
bootedFrom = constants.SystemLabel bootedFrom = constants.SystemLabel
cfg, err := config.Scan(collector.Directories([]string{dir}...), collector.NoLogs) cfg, err := config.ScanNoLogs(collector.Directories([]string{dir}...), collector.NoLogs)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
// Override the config with our test params // Override the config with our test params
cfg.Runner = runner cfg.Runner = runner
cfg.Fs = fs cfg.Fs = fs
cfg.Mounter = mounter cfg.Mounter = mounter
cfg.CloudInitRunner = ci cfg.CloudInitRunner = ci
cfg.Logger = logger
spec, err := config.ReadSpecFromCloudConfig(cfg, "reset") spec, err := config.ReadSpecFromCloudConfig(cfg, "reset")
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
resetSpec := spec.(*v1.ResetSpec) resetSpec := spec.(*v1.ResetSpec)
@ -574,37 +581,33 @@ cloud-init-paths:
Expect(resetSpec.Passive.Label).To(Equal("MY_LABEL")) Expect(resetSpec.Passive.Label).To(Equal("MY_LABEL"))
}) })
It("Reads properly the cloud config for upgrade", func() { It("Reads properly the cloud config for upgrade", func() {
cfg, err := config.Scan(collector.Directories([]string{dir}...), collector.NoLogs) cfg, err := config.ScanNoLogs(collector.Directories([]string{dir}...), collector.NoLogs)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
// Override the config with our test params // Override the config with our test params
cfg.Runner = runner cfg.Runner = runner
cfg.Fs = fs cfg.Fs = fs
cfg.Mounter = mounter cfg.Mounter = mounter
cfg.CloudInitRunner = ci cfg.CloudInitRunner = ci
cfg.Logger = logger
spec, err := config.ReadSpecFromCloudConfig(cfg, "upgrade") spec, err := config.ReadSpecFromCloudConfig(cfg, "upgrade")
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
upgradeSpec := spec.(*v1.UpgradeSpec) upgradeSpec := spec.(*v1.UpgradeSpec)
Expect(upgradeSpec.RecoveryUpgrade()).To(BeTrue()) Expect(upgradeSpec.RecoveryUpgrade()).To(BeTrue())
}) })
It("Fails when a wrong action is read", func() { It("Fails when a wrong action is read", func() {
cfg, err := config.Scan(collector.Directories([]string{dir}...), collector.NoLogs) cfg, err := config.ScanNoLogs(collector.Directories([]string{dir}...), collector.NoLogs)
cfg.Logger = logger
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
_, err = config.ReadSpecFromCloudConfig(cfg, "nope") _, err = config.ReadSpecFromCloudConfig(cfg, "nope")
Expect(err).To(HaveOccurred()) Expect(err).To(HaveOccurred())
}) })
It("Sets info level if its not on the cloud-config", func() {
// Now again but with no config
cfg, err := config.Scan(collector.Directories([]string{""}...), collector.NoLogs)
Expect(err).ToNot(HaveOccurred())
Expect(cfg.Logger.GetLevel()).To(Equal(zerolog.InfoLevel))
})
It("Sets debug level if its on the cloud-config", func() { It("Sets debug level if its on the cloud-config", func() {
ccdata := []byte(`#cloud-config ccdata := []byte(`#cloud-config
debug: true debug: true
`) `)
err = os.WriteFile(filepath.Join(dir, "cc.yaml"), ccdata, os.ModePerm) err = os.WriteFile(filepath.Join(dir, "cc.yaml"), ccdata, os.ModePerm)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
cfg, err := config.Scan(collector.Directories([]string{dir}...), collector.NoLogs) cfg, err := config.ScanNoLogs(collector.Directories([]string{dir}...), collector.NoLogs)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
Expect(cfg.Logger.GetLevel()).To(Equal(zerolog.DebugLevel)) Expect(cfg.Logger.GetLevel()).To(Equal(zerolog.DebugLevel))

View File

@ -355,23 +355,26 @@ var _ = Describe("Elemental", Label("elemental"), func() {
var install *v1.InstallSpec var install *v1.InstallSpec
var err error var err error
var el *elemental.Elemental var el *elemental.Elemental
var tmpDir string
BeforeEach(func() { BeforeEach(func() {
cInit = &v1mock.FakeCloudInitRunner{ExecStages: []string{}, Error: false} cInit = &v1mock.FakeCloudInitRunner{ExecStages: []string{}, Error: false}
config.CloudInitRunner = cInit config.CloudInitRunner = cInit
Expect(os.RemoveAll("/tmp/test.img")).ToNot(HaveOccurred()) tmpDir, err = os.MkdirTemp("", "elements-*")
Expect(err).To(BeNil())
Expect(os.RemoveAll(filepath.Join(tmpDir, "/test.img"))).ToNot(HaveOccurred())
// at least 2Gb in size as state is set to 1G // at least 2Gb in size as state is set to 1G
_, err = diskfs.Create("/tmp/test.img", 2*1024*1024*1024, diskfs.Raw, 512) _, err = diskfs.Create(filepath.Join(tmpDir, "/test.img"), 2*1024*1024*1024, diskfs.Raw, 512)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
config.Install.Device = "/tmp/test.img" config.Install.Device = filepath.Join(tmpDir, "/test.img")
install, err = agentConfig.NewInstallSpec(config) install, err = agentConfig.NewInstallSpec(config)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
install.Target = "/tmp/test.img" install.Target = filepath.Join(tmpDir, "/test.img")
el = elemental.NewElemental(config) el = elemental.NewElemental(config)
}) })
AfterEach(func() { AfterEach(func() {
Expect(os.RemoveAll("/tmp/test.img")).ToNot(HaveOccurred()) Expect(os.RemoveAll(tmpDir)).ToNot(HaveOccurred())
}) })
It("Successfully creates partitions and formats them, EFI boot", func() { It("Successfully creates partitions and formats them, EFI boot", func() {
@ -379,7 +382,7 @@ var _ = Describe("Elemental", Label("elemental"), func() {
install.Firmware = v1.EFI install.Firmware = v1.EFI
Expect(install.Partitions.SetFirmwarePartitions(v1.EFI, v1.GPT)).To(BeNil()) Expect(install.Partitions.SetFirmwarePartitions(v1.EFI, v1.GPT)).To(BeNil())
Expect(el.PartitionAndFormatDevice(install)).To(BeNil()) Expect(el.PartitionAndFormatDevice(install)).To(BeNil())
disk, err := diskfs.Open("/tmp/test.img", diskfs.WithOpenMode(diskfs.ReadOnly)) disk, err := diskfs.Open(filepath.Join(tmpDir, "/test.img"), diskfs.WithOpenMode(diskfs.ReadOnly))
defer disk.Close() defer disk.Close()
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
// check that its type GPT // check that its type GPT
@ -412,7 +415,7 @@ var _ = Describe("Elemental", Label("elemental"), func() {
install.Firmware = v1.BIOS install.Firmware = v1.BIOS
Expect(install.Partitions.SetFirmwarePartitions(v1.BIOS, v1.GPT)).To(BeNil()) Expect(install.Partitions.SetFirmwarePartitions(v1.BIOS, v1.GPT)).To(BeNil())
Expect(el.PartitionAndFormatDevice(install)).To(BeNil()) Expect(el.PartitionAndFormatDevice(install)).To(BeNil())
disk, err := diskfs.Open("/tmp/test.img", diskfs.WithOpenMode(diskfs.ReadOnly)) disk, err := diskfs.Open(filepath.Join(tmpDir, "/test.img"), diskfs.WithOpenMode(diskfs.ReadOnly))
defer disk.Close() defer disk.Close()
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
// check that its type GPT // check that its type GPT