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.

Code

392 commit(s) on main

Merge change request 01M70WES5ZZDJ6RP226WB11BBZ: Let people rename and remove their own passkeys keenan · 24m ago 4b8c9e1d
history blame raw 1.8 KiB
1package server
2
3import (
4 "io"
5 "log/slog"
6 "path/filepath"
7 "testing"
8 "time"
9
10 "rodent.software/vole/ci/runs"
11 "rodent.software/vole/core/git"
12 "rodent.software/vole/forge/access"
13 "rodent.software/vole/forge/repo"
14)
15
16func TestRunSchedulesQueuesOncePerSlot(t *testing.T) {
17 t.Parallel()
18 dir := t.TempDir()
19 acls, err := access.Open(filepath.Join(dir, "users.db"))
20 if err != nil {
21 t.Fatal(err)
22 }
23 acls.AuditPath = filepath.Join(dir, "audit.log")
24 repos := repo.New(filepath.Join(dir, "repos"), "", acls)
25 m, err := repos.Create("demo", "owner", "")
26 if err != nil {
27 t.Fatal(err)
28 }
29 workflow := `version: 1
30on:
31 schedule:
32 - cron: "* * * * *"
33jobs:
34 tick:
35 image: alpine:3.22
36 steps:
37 - run: echo tick
38`
39 if _, err := git.CommitFiles(m.Git(), "refs/heads/main", func(files map[string][]byte) error {
40 files[".vole/workflows/tick.yaml"] = []byte(workflow)
41 return nil
42 }, "add the schedule", "owner"); err != nil {
43 t.Fatal(err)
44 }
45 store, err := runs.Open(filepath.Join(dir, "runs.db"))
46 if err != nil {
47 t.Fatal(err)
48 }
49 t.Cleanup(func() { store.Close() })
50 s := &Server{Repos: repos, Runs: store,
51 Log: slog.New(slog.NewTextHandler(io.Discard, nil))}
52
53 slot := time.Date(2026, 11, 2, 3, 17, 0, 0, time.UTC)
54 s.runSchedules(slot)
55 list, err := store.Recent("demo", 10)
56 if err != nil {
57 t.Fatal(err)
58 }
59 if len(list) != 1 || list[0].Trigger != "schedule" || list[0].TriggerAction != "scheduled" {
60 t.Fatalf("schedule runs = %+v", list)
61 }
62 if list[0].Occurrence != "schedule:"+slot.Format(time.RFC3339) {
63 t.Fatalf("occurrence = %q", list[0].Occurrence)
64 }
65 // A second look inside the same minute is the same slot, not a second run.
66 s.runSchedules(slot.Add(20 * time.Second))
67 list, err = store.Recent("demo", 10)
68 if err != nil {
69 t.Fatal(err)
70 }
71 if len(list) != 1 {
72 t.Fatalf("a second check duplicated the slot: %+v", list)
73 }
74}
75