Skip to content
Merged
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
5 changes: 5 additions & 0 deletions .custom-gcl.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
version: v2.13.1
plugins:
- module: "go.uber.org/nilaway"
import: "go.uber.org/nilaway/cmd/gclplugin"
version: "v0.0.0-20260808063849-8649a03c818a"
3 changes: 3 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ jobs:
go mod tidy
git diff --exit-code -- go.mod go.sum

- name: Run golangci-lint
run: make lint

test:
name: Go tests (${{ matrix.os }})
runs-on: ${{ matrix.os }}
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
.kata.local.toml
# roborev snapshots
/.roborev/
/custom-gcl
19 changes: 19 additions & 0 deletions .golangci.nilaway.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
version: "2"
run:
tests: false
linters:
default: none
enable:
- nilaway
settings:
custom:
nilaway:
type: "module"
description: Static analysis tool to detect potential nil panics in Go code.
settings:
include-pkgs: "go.kenn.io/kit"
exclusions:
rules:
- path: "_test\\.go"
linters:
- nilaway
9 changes: 9 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
version: "2"
run:
tests: true
go: "1.27"
linters:
default: none
enable:
Expand Down Expand Up @@ -33,6 +34,10 @@ linters:
alias: gittest
- pkg: go.kenn.io/kit/git/worktree
alias: gitworktree
testifylint:
disable:
- float-compare
- require-error
exclusions:
generated: lax
presets:
Expand All @@ -47,6 +52,10 @@ linters:
- linters:
- modernize
text: "omitzero:"
- linters:
- staticcheck
path: ^(agenthook/|git/managed/untrusted_tree\.go$)
text: "ST1005:"
paths:
- third_party$
- builtin$
Expand Down
16 changes: 16 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
GOLANGCI_LINT_VERSION ?= v2.13.1
CUSTOM_GCL_DIR ?= .
CUSTOM_GCL := $(CUSTOM_GCL_DIR)/custom-gcl

.PHONY: lint lint-golangci nilaway nilaway-golangci-build
lint: lint-golangci nilaway

lint-golangci:
go run github.com/golangci/golangci-lint/v2/cmd/golangci-lint@$(GOLANGCI_LINT_VERSION) run ./...

nilaway-golangci-build:
go run github.com/golangci/golangci-lint/v2/cmd/golangci-lint@$(GOLANGCI_LINT_VERSION) custom \
--destination $(CUSTOM_GCL_DIR) --name custom-gcl --version $(GOLANGCI_LINT_VERSION)

nilaway: nilaway-golangci-build
$(CUSTOM_GCL) run --config .golangci.nilaway.yml ./...
2 changes: 1 addition & 1 deletion agenthook/hermes.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ func removeOwnedHermesHookNodes(
event := hooks.Content[i]
entries := hooks.Content[i+1]
resolvedEntries := resolveYAMLAlias(entries)
if resolvedEntries.Kind != yaml.SequenceNode {
if resolvedEntries == nil || resolvedEntries.Kind != yaml.SequenceNode {
if isHermesEventName(event.Value) {
return fmt.Errorf(
"Hermes config %s event %q must be an array", path, event.Value,
Expand Down
3 changes: 3 additions & 0 deletions agenthook/json.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ func planNestedJSONConfig(
}
}
if !uninstall {
if hooksObject == nil {
return nil, false, fmt.Errorf("agent hook config %s has no hooks object", path)
}
for _, hook := range hooks {
entry := map[string]any{}
if hook.matcher != "" {
Expand Down
3 changes: 3 additions & 0 deletions agenthook/json_direct.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ func planDirectJSONConfig(
}
}
if !uninstall {
if hooksObject == nil {
return nil, false, fmt.Errorf("agent hook config %s has no hooks object", path)
}
if spec.requireVersion {
if _, exists := root["version"]; !exists {
root["version"] = 1
Expand Down
3 changes: 3 additions & 0 deletions backup/auxiliary.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,9 @@ func captureAuxiliaryArtifacts(
}
return nil, fmt.Errorf("backup: preparing auxiliary artifact %q: %w", artifact.Name, err)
}
if prepared == nil {
return nil, fmt.Errorf("backup: preparing auxiliary artifact %q returned no result", artifact.Name)
}
id := prepared.ID()
if _, err := appender.AddPrepared(ctx, prepared); err != nil {
return nil, err
Expand Down
19 changes: 10 additions & 9 deletions backup/auxiliary_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import (
"strings"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
Assert "github.com/stretchr/testify/assert"
Require "github.com/stretchr/testify/require"
"go.kenn.io/kit/pack"
)

Expand Down Expand Up @@ -48,7 +48,7 @@ func TestValidateAuxiliaryArtifactsRejectsAmbiguousAuthority(t *testing.T) {
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
t.Parallel()
assert.ErrorContains(t, validateAuxiliaryArtifacts(test.artifacts), test.want)
Assert.ErrorContains(t, validateAuxiliaryArtifacts(test.artifacts), test.want)
})
}
}
Expand Down Expand Up @@ -90,11 +90,11 @@ func TestValidateManifestAuxiliaryRequiresSortedBoundedIdentity(t *testing.T) {
want: "invalid size",
},
}
require.NoError(t, validateManifestAuxiliary([]ManifestAuxiliary{valid}))
Require.NoError(t, validateManifestAuxiliary([]ManifestAuxiliary{valid}))
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
t.Parallel()
assert.ErrorContains(t, validateManifestAuxiliary(test.artifacts), test.want)
Assert.ErrorContains(t, validateManifestAuxiliary(test.artifacts), test.want)
})
}
}
Expand All @@ -106,14 +106,15 @@ func TestRestoreAuxiliaryRejectsOversizedFooterBeforePayloadRead(t *testing.T) {
name = "unreadable payload"
}
t.Run(name, func(t *testing.T) {
require := Require.New(t)
repo := initTestRepo(t)
known := map[pack.BlobID]IndexEntry{}
appender := NewPackAppender(repo, known, pack.DefaultZstdLevel, nil, testPackExt)
content := bytes.Repeat([]byte("oversized auxiliary payload"), 4096)
id, _, err := appender.Add(content)
require.NoError(t, err)
require.NoError(err)
_, _, err = appender.Finish()
require.NoError(t, err)
require.NoError(err)
if corruptPayload {
corruptStoredBlob(t, repo, known, id)
}
Expand All @@ -125,8 +126,8 @@ func TestRestoreAuxiliaryRejectsOversizedFooterBeforePayloadRead(t *testing.T) {

restored, err := state.restoreAuxiliary(context.Background(), manifest)

require.ErrorContains(t, err, "is 110592 bytes but manifest records 1")
assert.Nil(t, restored)
require.ErrorContains(err, "is 110592 bytes but manifest records 1")
Assert.Nil(t, restored)
})
}
}
3 changes: 3 additions & 0 deletions backup/create_shared.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,9 @@ func preparePortableMetadata(
}
return pack.BlobID{}, 0, fmt.Errorf("backup: preparing portable metadata: %w", err)
}
if prepared == nil {
return pack.BlobID{}, 0, fmt.Errorf("backup: preparing portable metadata returned no result")
}
metadataID := prepared.ID()
if _, err := appender.AddPrepared(ctx, prepared); err != nil {
return pack.BlobID{}, 0, err
Expand Down
5 changes: 4 additions & 1 deletion backup/pagehash.go
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ func MaterializeHashMap(
fetch func(pack.BlobID) ([]byte, error),
chain []pack.BlobID,
) (*PageHashMap, error) {
var deltas []*PageHashDelta
deltas := make([]*PageHashDelta, 0)
for i, id := range chain {
data, err := fetch(id)
if err != nil {
Expand Down Expand Up @@ -258,6 +258,9 @@ func MaterializeHashMap(
err,
)
}
if d == nil {
return nil, fmt.Errorf("backup: hash-map chain blob %d (%s) decoded to no delta", i, id)
}
deltas = append(deltas, d)
}
return nil, fmt.Errorf("backup: hash-map chain of %d blobs has no keyframe", len(chain))
Expand Down
5 changes: 4 additions & 1 deletion backup/pagemap.go
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ func ApplyPageMapDelta(base, delta *PageMap) (*PageMap, error) {
// MaterializePageMap walks a newest-to-oldest blob chain to a keyframe and
// replays the deltas oldest-first.
func MaterializePageMap(fetch func(pack.BlobID) ([]byte, error), chain []pack.BlobID) (*PageMap, error) {
var deltas []*PageMap
deltas := make([]*PageMap, 0)
for i, id := range chain {
data, err := fetch(id)
if err != nil {
Expand All @@ -260,6 +260,9 @@ func MaterializePageMap(fetch func(pack.BlobID) ([]byte, error), chain []pack.Bl
}
return m, nil
}
if m == nil {
return nil, fmt.Errorf("backup: page-map chain blob %d (%s) decoded to no delta", i, id)
}
deltas = append(deltas, m)
}
return nil, fmt.Errorf("backup: page-map chain of %d blobs has no keyframe", len(chain))
Expand Down
3 changes: 3 additions & 0 deletions backup/restore.go
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,9 @@ func Restore(ctx context.Context, r *Repo, app App, opts RestoreOptions) (res *R
// publishRestoredDB touches an Overwrite target's existing database.
var tmpRel string
if m.Metadata == nil {
if pm == nil {
return nil, fmt.Errorf("backup: snapshot has no page map")
}
tmpRel, err = st.restoreDB(ctx, app.DBFileName(), pm, hm)
} else {
tmpRel, res.DBBytes, err = st.restorePortableMetadata(
Expand Down
Loading
Loading