home

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit fd5e7ad395d749eaf07d0b345fd563c251eefad9
parent da55f31755481c16a92f5f0ff6271c66f828aa09
Author: Vincent Demeester <vincent@sbr.pm>
Date:   Sun, 10 May 2020 13:54:39 +0200

bus: add a small tool to schedule builds.sr.ht builds…

… used in sakhalin to schedule nightly builds.

Signed-off-by: Vincent Demeester <vincent@sbr.pm>

Diffstat:
Mmachines/sakhalin.nixos.nix | 7++-----
Mpkgs/default.nix | 1+
Atools/bus/default.nix | 19+++++++++++++++++++
Atools/bus/main.go | 94+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 116 insertions(+), 5 deletions(-)

diff --git a/machines/sakhalin.nixos.nix b/machines/sakhalin.nixos.nix @@ -104,6 +104,7 @@ with import ../assets/machines.nix; { OnFailure = "status-email-root@%n.service"; }; }; + environment.etc."secrets/srht-token".text = "${tokten_srht}"; # builds.sr.ht: daily builds systemd.services.builds-srht = { description = "Daily builds.sr.ht"; @@ -119,11 +120,7 @@ with import ../assets/machines.nix; { OnFailure = "status-email-root@%n.service"; }; - path = with pkgs; [ httpie ]; - script = '' - manifest=$(cat /etc/nixos/.builds/nixos.yml) - http POST https://builds.sr.ht/api/jobs manifest="${manifest}" Authorization:"token ${token_srht}" - ''; + script = "${pkgs.my.bus}/bin/bus"; startAt = "daily"; }; diff --git a/pkgs/default.nix b/pkgs/default.nix @@ -6,6 +6,7 @@ rec { tmux-tpm = pkgs.callPackage ./tmux-tpm { }; vrsync = pkgs.callPackage ./vrsync { }; vde-thinkpad = pkgs.callPackage ./vde-thinkpad { }; + bus = pkgs.callPackage ../tools/bus { }; # Mine ape = pkgs.callPackage ./ape { }; diff --git a/tools/bus/default.nix b/tools/bus/default.nix @@ -0,0 +1,19 @@ +{ stdenv, lib, go }: + +stdenv.mkDerivation rec { + name = "bus"; + src = ./.; + + phases = "buildPhase installPhase"; + buildInputs = [ go ]; + + buildPhase = '' + HOME=$(pwd) + cp $src/main.go . + go build -o bus main.go + ''; + installPhase = '' + mkdir $out + install -D bus $out/bin/bus + ''; +} diff --git a/tools/bus/main.go b/tools/bus/main.go @@ -0,0 +1,94 @@ +// bus is a smal CLI tool that triggers home builds on build.sr.ht. +// It is designed to be run in a cron or systemd timer. +package main + +import ( + "bytes" + "encoding/json" + "flag" + "fmt" + "io/ioutil" + "net/http" + "os" + "path/filepath" + "strings" +) + +var ( + branch = flag.String("branch", "master", "branch to schedule") + secret = flag.String("secret", "/etc/secrets/srht-token", "path to find sr.ht secret") + builds = flag.String("builds", "/etc/nixos/.builds", "path to find builds manifests") +) + +// Represents a builds.sr.ht build object as described on +// https://man.sr.ht/builds.sr.ht/api.md +type Build struct { + Manifest string `json:"manifest"` + Note string `json:"note"` + Tags []string `json:"tags"` +} + +func triggerBuild(token, name, manifest, branch string) { + build := Build{ + Manifest: manifest, + Note: fmt.Sprintf("Nightly build of '%s' on '%s'", name, branch), + Tags: []string{ + // my branch names tend to contain slashes, which are not valid + // identifiers in sourcehut. + "home", "nightly", strings.ReplaceAll(branch, "/", "_"), name, + }, + } + + body, _ := json.Marshal(build) + reader := ioutil.NopCloser(bytes.NewReader(body)) + + req, err := http.NewRequest("POST", "https://builds.sr.ht/api/jobs", reader) + if err != nil { + fmt.Fprintf(os.Stderr, "failed to create an HTTP request: %s", err) + os.Exit(1) + } + + req.Header.Add("Authorization", "token "+token) + req.Header.Add("Content-Type", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + // This might indicate a temporary error on the sourcehut side, do + // not fail the whole program. + fmt.Fprintf(os.Stderr, "failed to send build.sr.ht request: %s", err) + return + } + defer resp.Body.Close() + + if resp.StatusCode != 200 { + respBody, _ := ioutil.ReadAll(resp.Body) + fmt.Fprintf(os.Stderr, "received non-success response from builds.sr.ht: %s (%v)", respBody, resp.Status) + os.Exit(1) + } else { + fmt.Fprintf(os.Stdout, "triggered builds.sr.ht job for branch '%s'\n", branch) + } +} + +func main() { + flag.Parse() + token, err := ioutil.ReadFile(*secret) + if err != nil { + fmt.Fprint(os.Stderr, "sourcehut token could not be read.") + os.Exit(1) + } + files, err := ioutil.ReadDir(*builds) + if err != nil { + fmt.Fprintf(os.Stderr, "cannot list builds manifest from %s.", *builds) + os.Exit(1) + } + fmt.Fprintf(os.Stdout, "triggering builds for %v\n", *branch) + for _, f := range files { + path := filepath.Join(*builds, f.Name()) + manifest, err := ioutil.ReadFile(path) + if err != nil { + fmt.Fprintf(os.Stderr, "cannot read manifest %s.", path) + os.Exit(1) + } + triggerBuild(string(token), f.Name(), string(manifest), *branch) + } +}