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: 4 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ MAGE_RUN = go run github.com/magefile/mage@$(MAGE_VERSION)
DOCKER_IMAGE ?= skeeper
DOCKER_TAG ?= dev

.PHONY: deps fmt lint modernize test test-integration cover build verify tools \
.PHONY: deps fmt lint modernize test test-integration cover build install verify tools \
bun-lint bun-fmt bun-fmt-check hooks-install release-snapshot docker-build help

deps:
Expand All @@ -31,6 +31,9 @@ cover:
build:
@$(MAGE_RUN) build

install: build
@$(MAGE_RUN) install

verify:
@$(MAGE_RUN) verify

Expand Down
17 changes: 9 additions & 8 deletions internal/sidecar/reconcile.go
Original file line number Diff line number Diff line change
Expand Up @@ -464,7 +464,7 @@ func (s *Service) sidecarSnapshot(
}
files := map[string]reconcile.SnapshotFile{}
objects := make([]string, 0)
objectPaths := map[string]string{}
objectPaths := map[string][]string{}
prefix := namespace + "/"
for raw := range strings.SplitSeq(out.Stdout, "\x00") {
if raw == "" {
Expand All @@ -489,7 +489,7 @@ func (s *Service) sidecarSnapshot(
object := fields[2]
files[rel] = reconcile.SnapshotFile{Path: rel, Size: size, Blob: object}
objects = append(objects, object)
objectPaths[object] = rel
objectPaths[object] = append(objectPaths[object], rel)
}
if len(objects) == 0 {
return files, nil
Expand All @@ -499,12 +499,13 @@ func (s *Service) sidecarSnapshot(
return nil, err
}
for object, content := range contents {
rel := objectPaths[object]
file := files[rel]
file.Content = content
file.Size = int64(len(content))
file.SHA256 = sha256String(content)
files[rel] = file
for _, rel := range objectPaths[object] {
file := files[rel]
file.Content = content
file.Size = int64(len(content))
file.SHA256 = sha256String(content)
files[rel] = file
}
}
return files, nil
}
Expand Down
46 changes: 46 additions & 0 deletions internal/sidecar/service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,52 @@ func TestServiceVerifyAndFSCKUseLockfile(t *testing.T) {
}
}

func TestServiceFSCKHandlesDuplicateSidecarBlobs(t *testing.T) {
t.Run("Should handle duplicate sidecar blobs", func(t *testing.T) {
setGitIdentity(t)

ctx := context.Background()
root := newMainRepo(t)
remote := newBareRepo(t)
cfg := singleNamespaceConfig(remote, "project", []string{"**/SPEC.md"})
bootstrapRepo(t, root, cfg)
writeFile(t, root, "src/auth/SPEC.md", "# Shared\n")
writeFile(t, root, "src/billing/SPEC.md", "# Shared\n")

service := sidecar.New(&gitexec.ExecRunner{})
if _, err := service.Sync(ctx, root, sidecar.SyncOptions{}); err != nil {
t.Fatalf("sync: %v", err)
}

fsck, err := service.FSCK(ctx, root, sidecar.FSCKOptions{})
if err != nil {
t.Fatalf("fsck: %v", err)
}
if !fsck.OK {
t.Fatalf("expected duplicate-content specs to fsck clean: %#v", fsck)
}

journalPath := filepath.Join(root, ".git", "skeeper", "hydration.json")
data, err := os.ReadFile(journalPath)
if err != nil {
t.Fatalf("read hydration journal: %v", err)
}
var journal state.HydrationJournal
if err := json.Unmarshal(data, &journal); err != nil {
t.Fatalf("decode hydration journal: %v", err)
}
files := journal.Namespaces["project"].Files
auth := files["src/auth/SPEC.md"]
billing := files["src/billing/SPEC.md"]
if auth.SHA256 == "" || billing.SHA256 == "" {
t.Fatalf("expected duplicate blob entries to keep sha256: %#v", files)
}
if auth.SHA256 != billing.SHA256 || auth.SidecarBlob != billing.SidecarBlob {
t.Fatalf("expected duplicate files to share digest and blob: %#v", files)
}
})
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.

func TestServiceHydrateBlocksLocalOnlyByDefaultAndPrunesToRescue(t *testing.T) {
setGitIdentity(t)

Expand Down
45 changes: 45 additions & 0 deletions magefile.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,20 @@ func Build() error {
return sh.RunV("go", "build", "-trimpath", "-ldflags", buildLDFlags(), "-o", out, "./cmd/skeeper")
}

// Install installs the application binary into GOBIN/GOPATH/bin with version ldflags.
func Install() error {
installPath, err := goInstallPath()
if err != nil {
return err
}
fmt.Printf("Installing %s to %s\n", appBinary, installPath)
if err := sh.RunV("go", "install", "-trimpath", "-ldflags", buildLDFlags(), "./cmd/skeeper"); err != nil {
return fmt.Errorf("install %s: %w", appBinary, err)
}
fmt.Printf("Installed %s to %s\n", appBinary, installPath)
return nil
}

// Verify runs the blocking gate: fmt -> lint -> test -> build.
func Verify() {
mg.SerialDeps(Fmt, Lint, Test, Build)
Expand Down Expand Up @@ -239,6 +253,37 @@ func gitOutput(args ...string) string {
return strings.TrimSpace(string(out))
}

func goInstallPath() (string, error) {
gobin, err := goEnv("GOBIN")
if err != nil {
return "", err
}
if gobin != "" {
return filepath.Join(gobin, appBinary), nil
}
gopath, err := goEnv("GOPATH")
if err != nil {
return "", err
}
if gopath == "" {
return "", fmt.Errorf("go env GOPATH returned an empty path")
}
firstGoPath := filepath.SplitList(gopath)[0]
if firstGoPath == "" {
return "", fmt.Errorf("go env GOPATH returned an empty first path")
}
return filepath.Join(firstGoPath, "bin", appBinary), nil
}

func goEnv(key string) (string, error) {
cmd := exec.Command("go", "env", key)
out, err := cmd.Output()
if err != nil {
return "", fmt.Errorf("go env %s: %w", key, err)
}
return strings.TrimSpace(string(out)), nil
}

func runWithEnv(env map[string]string, name string, args ...string) error {
cmd := exec.CommandContext(context.Background(), name, args...)
cmd.Stdout = os.Stdout
Expand Down
Loading