diff --git a/.github/workflows/tag.yaml b/.github/workflows/tag.yaml index 38c0d0d1..eb84220f 100644 --- a/.github/workflows/tag.yaml +++ b/.github/workflows/tag.yaml @@ -54,6 +54,7 @@ jobs: nix-update gocov-merger nix-update cunicu + nix-update cunicu-scripts git diff --quiet || echo "changed=true" >> "$GITHUB_OUTPUT" diff --git a/Makefile b/Makefile index f7e3492a..3c888cff 100644 --- a/Makefile +++ b/Makefile @@ -80,7 +80,7 @@ docs-website: docs redirects: cd scripts && \ - go run ./generate_vanity_redirects.go -static-dir ../website/static + go run ./vanity_redirects -static-dir ../website/static completions: completions/cunicu.bash completions/cunicu.zsh completions/cunicu.fish diff --git a/flake.nix b/flake.nix index 6c430790..f62df5c3 100644 --- a/flake.nix +++ b/flake.nix @@ -26,6 +26,7 @@ overlays = { default = final: prev: { cunicu = final.callPackage ./nix/cunicu.nix { }; + cunicu-scripts = final.callPackage ./nix/scripts.nix { }; gocov-merger = final.callPackage ./nix/gocov-merger.nix { }; }; }; @@ -66,6 +67,7 @@ inherit (pkgs) cunicu gocov-merger; default = pkgs.cunicu; + scripts = pkgs.cunicu-scripts; }; }; }; diff --git a/nix/scripts.nix b/nix/scripts.nix new file mode 100644 index 00000000..1c601079 --- /dev/null +++ b/nix/scripts.nix @@ -0,0 +1,17 @@ +# SPDX-FileCopyrightText: 2025 Steffen Vogel +# SPDX-License-Identifier: Apache-2.0 +{ buildGoModule, cunicu }: +buildGoModule { + pname = "scripts"; + inherit (cunicu) version; + + src = ../scripts; + + subPackages = [ "vanity_redirects" ]; + + vendorHash = "sha256-AGepsQRIFVGTWRUQPnSuLEJb/Oxp2G+V0QxBOgb2L1U="; + + meta = { + mainProgram = "vanity_redirects"; + }; +} diff --git a/nix/shell.nix b/nix/shell.nix index 7106cd2b..6dcead2b 100644 --- a/nix/shell.nix +++ b/nix/shell.nix @@ -19,6 +19,8 @@ reuse, svu, + cunicu-scripts, + ... }: mkShell { @@ -35,6 +37,8 @@ mkShell { nix-update reuse svu + + cunicu-scripts ]; inputsFrom = [ diff --git a/scripts/generate_vanity_redirects.go b/scripts/vanity_redirects/main.go similarity index 63% rename from scripts/generate_vanity_redirects.go rename to scripts/vanity_redirects/main.go index 36d7b6c1..157304f1 100755 --- a/scripts/generate_vanity_redirects.go +++ b/scripts/vanity_redirects/main.go @@ -5,6 +5,7 @@ package main import ( "context" + "encoding/json" "flag" "fmt" "html/template" @@ -81,7 +82,7 @@ func getModsFromGitHub(ctx context.Context, owner string) (map[string]string, er client = client.WithAuthToken(token) } - repos, _, err := client.Repositories.ListByUser(context.Background(), owner, nil) //nolint:contextcheck + repos, _, err := client.Repositories.ListByUser(ctx, owner, nil) if err != nil { return nil, fmt.Errorf("failed to list repos: %w", err) } @@ -127,33 +128,65 @@ func getModBase(pkg string) string { func main() { prefix := flag.String("prefix", "cunicu.li", "Prefix") owner := flag.String("owner", "cunicu", "GitHub user/org") - staticDir := flag.String("static-dir", "./website/static", "Directory in which the generated files should be placed") + modsFile := flag.String("modules-file", "", "JSON file containing a map of modules") + modsFetch := flag.Bool("modules-fetch", false, "Only fetch modules from GitHub") + staticDir := flag.String("static-dir", "", "Directory in which the generated files should be placed") flag.Parse() ctx := context.Background() - mods, err := getModsFromGitHub(ctx, *owner) - if err != nil { - log.Fatalf("Failed to list packages: %v", err) + var mods map[string]string + + if *modsFile == "" || *modsFetch { + var err error + if mods, err = getModsFromGitHub(ctx, *owner); err != nil { + log.Fatalf("Failed to list packages: %v", err) + } } - for mod, repo := range mods { - modBase := getModBase(mod) - - if !strings.HasPrefix(mod, *prefix) { - continue + if *modsFetch { + if *modsFile == "" { + log.Fatal("-modules-fetch requires -modules-file") } - if err := generate(mod, repo, *staticDir, *prefix); err != nil { - log.Fatalf("Failed to generate HTML file: %v", err) + modsJSON, err := json.MarshalIndent(mods, "", " ") + if err != nil { + log.Fatalf("Failed to encode modules: %s", err) } - if mod == modBase { - continue + if err := os.WriteFile(*modsFile, modsJSON, 0o755); err != nil { //nolint:gosec + log.Fatalf("Failed to write modules to file: %s", err) + } + } else if *modsFile != "" { + modsJSON, err := os.ReadFile(*modsFile) + if err != nil { + log.Fatalf("Failed to read modules from file: %s", err) } - if err := generate(modBase, repo, *staticDir, *prefix); err != nil { - log.Fatalf("Failed to generate HTML file: %v", err) + if err := json.Unmarshal(modsJSON, &mods); err != nil { + log.Fatalf("Failed to decode modules: %s", err) + } + } + + if *staticDir != "" { + for mod, repo := range mods { + modBase := getModBase(mod) + + if !strings.HasPrefix(mod, *prefix) { + continue + } + + if err := generate(mod, repo, *staticDir, *prefix); err != nil { + log.Fatalf("Failed to generate HTML file: %v", err) + } + + if mod == modBase { + continue + } + + if err := generate(modBase, repo, *staticDir, *prefix); err != nil { + log.Fatalf("Failed to generate HTML file: %v", err) + } } } }