Sign in

Search issue titles and bodies, change requests and comments. Private repositories you cannot read are not included.

vole
Clone

Read only, no credentials:

https://rodent.software/git/vole.git

Write over SSH with a registered key:

git clone ssh://git@0.0.0.0:2222/vole.git

A free and open-source forge that lives in your Git repo.

Drop the legacy run-record import

59badc638dde0655b11d01eebfe3a457735d2501 · Keenan Nemetz · 10d ago · parent b312e166

Drop the legacy run-record import

There is no released instance to stay compatible with, so the file format
under runs/, the branch importer, and the pre-receive allowance for that
directory are gone. The Record value is now only the finish wire format and the
shape stored in run_attempts. metadata.ValidateIssues rejects runs/ like any
other unknown directory, and vole admin index rebuild no longer reads run
history from Git.

An existing instance migrates once with the previous build, then rewrites the
vole branch to remove the old records. Nothing in this build reads them.

server/integration_test.go +12−69

@@ -27,7 +27,6 @@ import (
27 27
28 28 "github.com/rodent-software/vole/ci"
29 29 "github.com/rodent-software/vole/ci/runs"
30 "github.com/rodent-software/vole/core/id"
31 30 "github.com/rodent-software/vole/forge/access"
32 31 "github.com/rodent-software/vole/forge/config"
33 32 "github.com/rodent-software/vole/forge/identity"
@@ -526,68 +525,6 @@ func TestRebuildIndexAfterDelete(t *testing.T) {
526 525 }
527 526 }
528 527
529 // TestIndexRebuildImportsLegacyRunRecords is the upgrade path: records written
530 // before CI history moved into the database are still on the branch, and a rebuild
531 // imports them into runs.db instead of rebuilding the queue from Git forever.
532 func TestIndexRebuildImportsLegacyRunRecords(t *testing.T) {
533 t.Parallel()
534 f := newFixture(t)
535 f.publish(f.repo)
536
537 now := time.Now().UTC()
538 runID, err := id.New(now)
539 if err != nil {
540 t.Fatal(err)
541 }
542 m, err := f.srv.Repos.Open(f.repo)
543 if err != nil {
544 t.Fatal(err)
545 }
546 rec := runs.Record{
547 RunID: runID, Attempt: 1, Repo: f.repo, Ref: "refs/heads/main",
548 SHA: strings.Repeat("ab", 20), Workflow: ".vole/workflows/ci.yaml",
549 WorkflowSHA: strings.Repeat("cd", 20), Job: "build", StepsSHA: "steps-digest",
550 Exit: 0, Finished: now, Signer: "keenan",
551 Steps: []runs.StepResult{{
552 Name: "build", Started: now.Add(-time.Second), Finished: now,
553 }},
554 }
555 if _, err := runs.WriteRecord(m.Git(), metadata.Ref, rec, "keenan", nil); err != nil {
556 t.Fatalf("writing the legacy record: %v", err)
557 }
558
559 // A fresh database, as after restoring the repositories but not runs.db.
560 f.srv.SSH.Close()
561 f.http.Close()
562 f.srv.Close()
563 for _, p := range []string{f.cfg.RunsDB(), f.cfg.RunsDB() + "-wal", f.cfg.RunsDB() + "-shm"} {
564 if err := os.Remove(p); err != nil && !os.IsNotExist(err) {
565 t.Fatal(err)
566 }
567 }
568 cmd := exec.Command(binPath, "index", "rebuild", "--config", f.cfgFile(t))
569 if out, err := cmd.CombinedOutput(); err != nil {
570 t.Fatalf("rebuild: %v\n%s", err, out)
571 }
572
573 store, err := runs.Open(f.cfg.RunsDB())
574 if err != nil {
575 t.Fatal(err)
576 }
577 defer store.Close()
578 got, err := store.Get(runID)
579 if err != nil || got == nil {
580 t.Fatalf("the legacy run was not imported: %v", err)
581 }
582 if got.Status != runs.StatusSuccess || got.Attempts != 1 {
583 t.Fatalf("imported run = %+v", got)
584 }
585 stored, err := store.Attempt(runID, 1)
586 if err != nil || stored == nil || stored.Signer != "keenan" || len(stored.Steps) != 1 {
587 t.Fatalf("imported attempt = %+v, %v", stored, err)
588 }
589 }
590
591 528 // TestRosterIsOneDatabaseFile proves the backup story end to end: the roster is
592 529 // one SQLite file, a consistent copy of it is complete, and no system repository
593 530 // or key directory exists beside it.
@@ -3086,12 +3023,18 @@ jobs:
3086 3023 if err != nil {
3087 3024 t.Fatal(err)
3088 3025 }
3089 onBranch, err := runs.ReadRecord(m.Git(), metadata.Ref, done.ID)
3090 if err != nil {
3091 t.Fatalf("reading the branch: %v", err)
3092 }
3093 if onBranch != nil {
3094 t.Fatalf("the run record is still on %s: %+v", metadata.Ref, onBranch)
3026 if tip, err := m.Git().RevParseRaw(metadata.Ref); err != nil {
3027 t.Fatal(err)
3028 } else if tip != "" {
3029 entries, err := m.Git().LsTreeR(tip)
3030 if err != nil {
3031 t.Fatal(err)
3032 }
3033 for _, e := range entries {
3034 if strings.HasPrefix(e.Name, "runs/") {
3035 t.Fatalf("the run record is still on %s: %s", metadata.Ref, e.Name)
3036 }
3037 }
3095 3038 }
3096 3039
3097 3040 // The page reads the attempt, not a tree walk.