Skip to content

Commit 5259317

Browse files
committed
init: initialize bundle maintenance
Interface through 'crontab' to update the daily maintenance schedule for all routes. This can be modified in the future to allow both a --daily and --hourly schedule.
1 parent 897b77a commit 5259317

File tree

4 files changed

+124
-0
lines changed

4 files changed

+124
-0
lines changed

cmd/git-bundle-server/cron.go

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"os"
6+
"strings"
7+
8+
"github.com/github/git-bundle-server/internal/core"
9+
)
10+
11+
func SetCronSchedule() error {
12+
pathToExec, err := os.Executable()
13+
if err != nil {
14+
return fmt.Errorf("failed to get executable: %w", err)
15+
}
16+
17+
dailySchedule := "0 0 * * * \"" + pathToExec + "\" update-all\n"
18+
19+
scheduleBytes, err := core.LoadExistingSchedule()
20+
if err != nil {
21+
return fmt.Errorf("failed to get existing cron schedule: %w", err)
22+
}
23+
24+
scheduleStr := string(scheduleBytes)
25+
26+
// TODO: Use comments to indicate a "region" where our schedule
27+
// is set, so we can remove the entire region even if we update
28+
// the schedule in the future.
29+
if strings.Contains(scheduleStr, dailySchedule) {
30+
// We already have this schedule, so skip modifying
31+
// the crontab schedule.
32+
return nil
33+
}
34+
35+
scheduleBytes = append(scheduleBytes, []byte(dailySchedule)...)
36+
scheduleFile := core.CrontabFile()
37+
38+
err = os.WriteFile(scheduleFile, scheduleBytes, 0o600)
39+
if err != nil {
40+
return fmt.Errorf("failed to write new cron schedule to temp file: %w", err)
41+
}
42+
43+
err = core.CommitCronSchedule(scheduleFile)
44+
if err != nil {
45+
return fmt.Errorf("failed to commit new cron schedule: %w", err)
46+
}
47+
48+
err = os.Remove(scheduleFile)
49+
if err != nil {
50+
return fmt.Errorf("failed to clear schedule file: %w", err)
51+
}
52+
53+
return nil
54+
}

cmd/git-bundle-server/init.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,5 +63,7 @@ func (Init) run(args []string) error {
6363
return fmt.Errorf("failed to write bundle list: %w", listErr)
6464
}
6565

66+
SetCronSchedule()
67+
6668
return nil
6769
}

internal/core/cron.go

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package core
2+
3+
import (
4+
"bytes"
5+
"fmt"
6+
"os/exec"
7+
)
8+
9+
func GetCrontabCommand(args ...string) (*exec.Cmd, error) {
10+
crontab, err := exec.LookPath("crontab")
11+
if err != nil {
12+
return nil, fmt.Errorf("failed to find 'crontab' on the path: %w", err)
13+
}
14+
15+
cmd := exec.Command(crontab, args...)
16+
return cmd, nil
17+
}
18+
19+
func LoadExistingSchedule() ([]byte, error) {
20+
cmd, err := GetCrontabCommand("-l")
21+
if err != nil {
22+
return nil, err
23+
}
24+
25+
buffer := bytes.Buffer{}
26+
cmd.Stdout = &buffer
27+
28+
errorBuffer := bytes.Buffer{}
29+
cmd.Stderr = &errorBuffer
30+
31+
err = cmd.Start()
32+
if err != nil {
33+
return nil, fmt.Errorf("crontab failed to start: %w", err)
34+
}
35+
36+
err = cmd.Wait()
37+
if err != nil {
38+
return nil, fmt.Errorf("crontab returned a failure: %w\nstderr: %s", err, errorBuffer.String())
39+
}
40+
41+
return buffer.Bytes(), nil
42+
}
43+
44+
func CommitCronSchedule(filename string) error {
45+
cmd, err := GetCrontabCommand(filename)
46+
if err != nil {
47+
return err
48+
}
49+
50+
errorBuffer := bytes.Buffer{}
51+
cmd.Stderr = &errorBuffer
52+
53+
err = cmd.Start()
54+
if err != nil {
55+
return fmt.Errorf("crontab failed to start: %w", err)
56+
}
57+
58+
err = cmd.Wait()
59+
if err != nil {
60+
return fmt.Errorf("crontab returned a failure: %w\nstderr: %s", err, errorBuffer.String())
61+
}
62+
63+
return nil
64+
}

internal/core/paths.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,7 @@ func webroot() string {
1919
func reporoot() string {
2020
return bundleroot() + "git/"
2121
}
22+
23+
func CrontabFile() string {
24+
return bundleroot() + "cron-schedule"
25+
}

0 commit comments

Comments
 (0)