Skip to content

Commit

Permalink
Merge branch 'main' into tools
Browse files Browse the repository at this point in the history
  • Loading branch information
AlekSi authored Aug 20, 2024
2 parents 283f061 + d13dfd7 commit 968d3f3
Show file tree
Hide file tree
Showing 8 changed files with 174 additions and 64 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/dance.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ env:

jobs:
dance:
name: dance
name: ${{ matrix.db }} ${{ matrix.project }}

# https://www.ubicloud.com/docs/github-actions-integration/price-performance#usage-pricing
# https://docs.github.com/en/billing/managing-billing-for-github-actions/about-billing-for-github-actions#per-minute-rates
Expand Down
97 changes: 97 additions & 0 deletions .github/workflows/go.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
---
name: Go
on:
pull_request:
types:
- unlabeled # if GitHub Actions stuck, add and remove "not ready" label to force rebuild
- opened
- reopened
- synchronize
push:
branches:
- main
schedule:
- cron: "12 3 * * *"

env:
GOPATH: /home/runner/go
GOCACHE: /home/runner/go/cache
GOLANGCI_LINT_CACHE: /home/runner/go/cache/lint
GOMODCACHE: /home/runner/go/mod
GOPROXY: https://proxy.golang.org
GOTOOLCHAIN: local

jobs:
tests:
name: Tests
runs-on: ubuntu-22.04
timeout-minutes: 10

# Do not run this job in parallel for any PR change or branch push.
concurrency:
group: ${{ github.workflow }}-tests-${{ github.head_ref || github.ref_name }}
cancel-in-progress: true

if: github.event_name != 'pull_request' || !contains(github.event.pull_request.labels.*.name, 'not ready')

steps:
# TODO https://github.com/FerretDB/github-actions/issues/211
- name: Checkout code
uses: actions/checkout@v4

- name: Setup Go
uses: FerretDB/github-actions/setup-go@main
with:
cache-key: tests

- name: Install Task
run: go generate -x
working-directory: tools

- name: Run init
run: bin/task init

- name: Run tests
run: bin/task test
env:
GOFLAGS: ${{ runner.debug == '1' && '-v' || '' }}

# we don't want them on CI
- name: Clean test and fuzz caches
if: always()
run: go clean -testcache -fuzzcache

- name: Check dirty
run: |
git status
git diff --exit-code
linters:
name: Linters
runs-on: ubuntu-22.04
timeout-minutes: 5

# Do not run this job in parallel for any PR change or branch push.
concurrency:
group: ${{ github.workflow }}-linters-${{ github.head_ref || github.ref_name }}
cancel-in-progress: true

if: github.event_name != 'pull_request' || !contains(github.event.pull_request.labels.*.name, 'not ready')

steps:
# TODO https://github.com/FerretDB/github-actions/issues/211
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0 # for `golangci-lint run --new` to work

- name: Setup Go
uses: FerretDB/github-actions/setup-go@main
with:
cache-key: linters

- name: Run linters
uses: FerretDB/github-actions/linters@main

- name: Format and lint documentation
run: bin/task docs-fmt
52 changes: 0 additions & 52 deletions .github/workflows/linters.yml

This file was deleted.

6 changes: 6 additions & 0 deletions Taskfile.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ version: "3"
vars:
DB: ""
CONFIG: ""
RACE_FLAG: -race={{and (ne OS "windows") (ne ARCH "arm") (ne ARCH "riscv64")}}

tasks:
init-tools:
Expand Down Expand Up @@ -64,6 +65,11 @@ tasks:
cmds:
- go build -v -o bin/ ./cmd/dance/

test:
desc: "Run unit tests (with caching)"
cmds:
- go test {{.RACE_FLAG}} -shuffle=on ./internal/...

dance:
desc: "Dance!"
deps: [build]
Expand Down
2 changes: 1 addition & 1 deletion cmd/dance/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ func main() {

switch c.Runner {
case config.RunnerTypeCommand:
runner, err = command.New(c.Params.(*config.RunnerParamsCommand), rl)
runner, err = command.New(c.Params.(*config.RunnerParamsCommand), rl, cli.Verbose)
case config.RunnerTypeGoTest:
fallthrough
case config.RunnerTypeJSTest:
Expand Down
35 changes: 26 additions & 9 deletions internal/runner/command/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package command
import (
"context"
"fmt"
"io"
"log/slog"
"os"
"os/exec"
Expand All @@ -29,21 +30,23 @@ import (

// command represents a generic test runner.
type command struct {
p *config.RunnerParamsCommand
l *slog.Logger
p *config.RunnerParamsCommand
l *slog.Logger
verbose bool
}

// New creates a new `command` runner with given parameters.
func New(params *config.RunnerParamsCommand, l *slog.Logger) (runner.Runner, error) {
func New(params *config.RunnerParamsCommand, l *slog.Logger, verbose bool) (runner.Runner, error) {
return &command{
p: params,
l: l,
p: params,
l: l,
verbose: verbose,
}, nil
}

// execScripts stores the given shell script content in dir/file-XXX.sh and executes it.
// It returns the combined output of the script execution.
func execScript(ctx context.Context, dir, file, content string) ([]byte, error) {
func execScript(ctx context.Context, dir, file, content string, verbose bool) ([]byte, error) {
f, err := os.CreateTemp(dir, file+"-*.sh")
if err != nil {
return nil, err
Expand All @@ -70,15 +73,29 @@ func execScript(ctx context.Context, dir, file, content string) ([]byte, error)
cmd := exec.CommandContext(ctx, "./"+filepath.Base(f.Name()))
cmd.Dir = dir

return cmd.CombinedOutput()
var b runner.LockedBuffer

if verbose {
cmd.Stdout = io.MultiWriter(&b, os.Stdout)
cmd.Stderr = io.MultiWriter(&b, os.Stderr)
} else {
cmd.Stdout = &b
cmd.Stderr = &b
}

if err = cmd.Run(); err != nil {
return nil, err
}

return b.Bytes(), nil
}

// Run implements [runner.Runner] interface.
func (c *command) Run(ctx context.Context) (map[string]config.TestResult, error) {
if c.p.Setup != "" {
c.l.InfoContext(ctx, "Running setup")

b, err := execScript(ctx, c.p.Dir, "setup", c.p.Setup)
b, err := execScript(ctx, c.p.Dir, "setup", c.p.Setup, c.verbose)
if err != nil {
return nil, fmt.Errorf("%s\n%w", b, err)
}
Expand All @@ -89,7 +106,7 @@ func (c *command) Run(ctx context.Context) (map[string]config.TestResult, error)
for _, t := range c.p.Tests {
c.l.InfoContext(ctx, "Running test", slog.String("test", t.Name))

b, err := execScript(ctx, c.p.Dir, t.Name, t.Cmd)
b, err := execScript(ctx, c.p.Dir, t.Name, t.Cmd, c.verbose)

tc := config.TestResult{
Status: config.Pass,
Expand Down
2 changes: 1 addition & 1 deletion internal/runner/command/command_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ func TestCommand(t *testing.T) {
p := &config.RunnerParamsCommand{
Setup: "exit 1",
}
c, err := New(p, slog.Default())
c, err := New(p, slog.Default(), true)
require.NoError(t, err)

ctx := context.Background()
Expand Down
42 changes: 42 additions & 0 deletions internal/runner/locked_buffer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Copyright 2021 FerretDB Inc.
//
// 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.

package runner

import (
"bytes"
"sync"
)

// LockedBuffer is a thread-safe [bytes.Buffer].
type LockedBuffer struct {
b bytes.Buffer
m sync.Mutex
}

// Bytes calls [bytes.Buffer.Write] in a thread-safe way.
func (lb *LockedBuffer) Write(p []byte) (int, error) {
lb.m.Lock()
defer lb.m.Unlock()

return lb.b.Write(p)
}

// Bytes calls [bytes.Buffer.Bytes] in a thread-safe way.
func (lb *LockedBuffer) Bytes() []byte {
lb.m.Lock()
defer lb.m.Unlock()

return lb.b.Bytes()
}

0 comments on commit 968d3f3

Please sign in to comment.