diff options
| author | Ophestra <cat@gensokyo.uk> | 2026-09-28 17:37:30 +0900 |
|---|---|---|
| committer | Ophestra <cat@gensokyo.uk> | 2026-09-28 19:57:13 +0900 |
| commit | 75bf6b0f0a1ce00a4ce1d710bbd84d5ff20e058a (patch) | |
| tree | 13f66c45250143a0eac246185a3eb4e9bd3e85fd | |
| parent | aae629a16bdce3931c508f498db7055b2301d156 (diff) | |
cmd/workflows: migrate workflowswip-ci-json
This represents the workflow documents via compound literals, and
removes the ugly and footgun-heavy yaml documents.
Signed-off-by: Ophestra <cat@gensokyo.uk>
| -rw-r--r-- | .gitea/workflows/test.yml | 130 | ||||
| -rw-r--r-- | cmd/workflows/doc.go | 10 | ||||
| -rw-r--r-- | cmd/workflows/main.go | 149 | ||||
| -rw-r--r-- | cmd/workflows/test.go | 227 |
4 files changed, 387 insertions, 129 deletions
diff --git a/.gitea/workflows/test.yml b/.gitea/workflows/test.yml index d1fc7ef8..0c29eb9e 100644 --- a/.gitea/workflows/test.yml +++ b/.gitea/workflows/test.yml @@ -1,129 +1 @@ -name: Test - -on: - - push - -jobs: - hakurei: - name: Hakurei - runs-on: nix - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Run NixOS test - run: nix build --out-link "result" --print-out-paths --print-build-logs ./test#checks.x86_64-linux.hakurei - - - name: Upload test output - uses: actions/upload-artifact@v3 - with: - name: "hakurei-vm-output" - path: result/* - retention-days: 1 - - race: - name: Hakurei (race detector) - runs-on: nix - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Run NixOS test - run: nix build --out-link "result" --print-out-paths --print-build-logs ./test#checks.x86_64-linux.race - - - name: Upload test output - uses: actions/upload-artifact@v3 - with: - name: "hakurei-race-vm-output" - path: result/* - retention-days: 1 - - sandbox: - name: Sandbox - runs-on: nix - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Run NixOS test - run: nix build --out-link "result" --print-out-paths --print-build-logs ./test#checks.x86_64-linux.sandbox - - - name: Upload test output - uses: actions/upload-artifact@v3 - with: - name: "sandbox-vm-output" - path: result/* - retention-days: 1 - - sandbox-race: - name: Sandbox (race detector) - runs-on: nix - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Run NixOS test - run: nix build --out-link "result" --print-out-paths --print-build-logs ./test#checks.x86_64-linux.sandbox-race - - - name: Upload test output - uses: actions/upload-artifact@v3 - with: - name: "sandbox-race-vm-output" - path: result/* - retention-days: 1 - - sharefs: - name: ShareFS - runs-on: nix - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Run NixOS test - run: nix build --out-link "result" --print-out-paths --print-build-logs ./test#checks.x86_64-linux.sharefs - - - name: Upload test output - uses: actions/upload-artifact@v3 - with: - name: "sharefs-vm-output" - path: result/* - retention-days: 1 - - check: - name: Flake checks - needs: - - hakurei - - race - - sandbox - - sandbox-race - - sharefs - runs-on: nix - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Run checks - run: nix --print-build-logs --experimental-features 'nix-command flakes' flake check ./test - - dist: - name: Create distribution - runs-on: nix - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Build for test - id: build-test - run: >- - export HAKUREI_REV="$(git rev-parse --short HEAD)" && - sed -i.old 's/version = /version = "0.0.0-'$HAKUREI_REV'"; # version = /' test/package.nix && - nix build --print-out-paths --print-build-logs ./test#dist && - mv test/{package.nix.old,package.nix} && - echo "rev=$HAKUREI_REV" >> $GITHUB_OUTPUT - - - name: Upload test build - uses: actions/upload-artifact@v3 - with: - name: "hakurei-${{ steps.build-test.outputs.rev }}" - path: result/* - retention-days: 1 +{"name":"Test","on":["push"],"jobs":{"hakurei":{"name":"Hakurei","runs-on":"nix","steps":[{"name":"Checkout","uses":"actions/checkout@v4"},{"name":"Run NixOS test","run":"nix build --out-link result --print-out-paths --print-build-logs ./test#checks.x86_64-linux.hakurei"},{"name":"Upload test output","uses":"actions/upload-artifact@v3","with":{"name":"hakurei-vm-output","path":"result/*","retention-days":1}}]},"race":{"name":"Hakurei (race detector)","runs-on":"nix","steps":[{"name":"Checkout","uses":"actions/checkout@v4"},{"name":"Run NixOS test","run":"nix build --out-link result --print-out-paths --print-build-logs ./test#checks.x86_64-linux.race"},{"name":"Upload test output","uses":"actions/upload-artifact@v3","with":{"name":"hakurei-race-vm-output","path":"result/*","retention-days":1}}]},"sandbox":{"name":"Sandbox","runs-on":"nix","steps":[{"name":"Checkout","uses":"actions/checkout@v4"},{"name":"Run NixOS test","run":"nix build --out-link result --print-out-paths --print-build-logs ./test#checks.x86_64-linux.sandbox"},{"name":"Upload test output","uses":"actions/upload-artifact@v3","with":{"name":"sandbox-vm-output","path":"result/*","retention-days":1}}]},"sandbox-race":{"name":"Sandbox (race detector)","runs-on":"nix","steps":[{"name":"Checkout","uses":"actions/checkout@v4"},{"name":"Run NixOS test","run":"nix build --out-link result --print-out-paths --print-build-logs ./test#checks.x86_64-linux.sandbox-race"},{"name":"Upload test output","uses":"actions/upload-artifact@v3","with":{"name":"sandbox-race-vm-output","path":"result/*","retention-days":1}}]},"sharefs":{"name":"ShareFS","runs-on":"nix","steps":[{"name":"Checkout","uses":"actions/checkout@v4"},{"name":"Run NixOS test","run":"nix build --out-link result --print-out-paths --print-build-logs ./test#checks.x86_64-linux.sharefs"},{"name":"Upload test output","uses":"actions/upload-artifact@v3","with":{"name":"sharefs-vm-output","path":"result/*","retention-days":1}}]},"check":{"name":"Flake checks","needs":["hakurei","race","sandbox","sandbox-race","sharefs"],"runs-on":"nix","steps":[{"name":"Checkout","uses":"actions/checkout@v4"},{"name":"Run checks","run":"nix --print-build-logs --experimental-features 'nix-command flakes' flake check ./test"}]},"dist":{"name":"Create distribution","runs-on":"nix","steps":[{"name":"Checkout","uses":"actions/checkout@v4"},{"name":"Build for test","id":"build-test","run":"export HAKUREI_REV=\"$(git rev-parse --short HEAD)\" \u0026\u0026 sed -i.old 's/version = /version = \"0.0.0-'$HAKUREI_REV'\"; # version = /' test/package.nix \u0026\u0026 nix build --print-out-paths --print-build-logs ./test#dist \u0026\u0026 mv test/{package.nix.old,package.nix} \u0026\u0026 echo \"rev=$HAKUREI_REV\" \u003e\u003e $GITHUB_OUTPUT"},{"name":"Upload test build","uses":"actions/upload-artifact@v3","with":{"name":"hakurei-${{ steps.build-test.outputs.rev }}","path":"result/*","retention-days":1}}]}}} diff --git a/cmd/workflows/doc.go b/cmd/workflows/doc.go new file mode 100644 index 00000000..110d635a --- /dev/null +++ b/cmd/workflows/doc.go @@ -0,0 +1,10 @@ +//go:build !workflows + +// The workflows program manages the .gitea directory to avoid having to write +// yaml. It is never invoked directly or built for the distribution tarball. +// +// This program is an internal detail of the hakurei project and is not usable +// on its own. It is not covered by the compatibility promise. +package main + +//go:generate go run -tags=workflows . diff --git a/cmd/workflows/main.go b/cmd/workflows/main.go new file mode 100644 index 00000000..46f7e054 --- /dev/null +++ b/cmd/workflows/main.go @@ -0,0 +1,149 @@ +//go:build workflows + +package main + +import ( + "bytes" + "encoding/json" + "fmt" + "os" + "path/filepath" + "sync" +) + +// KV represents a string to value pair. +type KV[T any] struct { + K string + V T +} + +// A Map represents an ordered set of key-value pairs. +type Map[T any] []KV[T] + +// MarshalJSON encodes m as a key-value pair in JSON. +func (m *Map[T]) MarshalJSON() ([]byte, error) { + if m == nil || len(*m) == 0 { + return []byte("{}"), nil + } + + buf := bytes.NewBuffer(make([]byte, 0, len(*m)<<5)) + buf.WriteByte('{') + + last := len(*m) - 1 + for i, pair := range *m { + p, err := json.Marshal(pair.K) + if err != nil { + return nil, fmt.Errorf("key %q: %w", pair.K, err) + } + buf.Write(p) + buf.WriteByte(':') + + p, err = json.Marshal(pair.V) + if err != nil { + return nil, fmt.Errorf("value of key %q: %w", pair.K, err) + } + buf.Write(p) + + if i < last { + buf.WriteByte(',') + } + } + + buf.WriteByte('}') + return buf.Bytes(), nil +} + +// A Step is a task ran as part of a [Job]. +type Step struct { + // A name for the step. + Name string `json:"name,omitempty"` + // Selects an action to run as part of a step in the job. + Uses string `json:"uses,omitempty"` + // A unique identifier for the step. + ID string `json:"id,omitempty"` + // Prevent a step from running unless a condition is met. + If string `json:"if,omitempty"` + // Runs command-line programs that do not exceed 21,000 characters using the + // operating system's shell. + Run string `json:"run,omitempty"` + // Key-value pairs of input parameters defined by the action. + With Map[any] `json:"with,omitempty"` +} + +// A Job is an entry in a [Workflow] document. +type Job struct { + // Set a name for the job. + Name string `json:"name,omitempty"` + // Identifies any jobs that must complete successfully before this job will + // run. + Needs []string `json:"needs,omitempty"` + // Define the type of machine to run the job on. + On string `json:"runs-on,omitempty"` + // A sequence of tasks. + Steps []Step `json:"steps,omitempty"` +} + +// Workflow describes a workflow document. +type Workflow struct { + // The name of the workflow. + Name string `json:"name,omitempty"` + // The name for workflow runs generated from the workflow. + RunName string `json:"run-name,omitempty"` + // Define which events can cause the workflow to run. + On any `json:"on"` + + // Named jobs part of the workflow run. + Jobs Map[Job] `json:"jobs,omitempty"` +} + +// workflowsDir is the relative pathname of the workflows directory. +const workflowsDir = "../../.gitea/workflows" + +// writeFile writes the action to the .gitea directory. +func (w *Workflow) writeFile(name string) error { + f, err := os.OpenFile( + filepath.Join(workflowsDir, name+".yml"), + os.O_CREATE|os.O_EXCL|os.O_WRONLY, + 0444, + ) + if err != nil { + return err + } + + err = json.NewEncoder(f).Encode(w) + if closeErr := f.Close(); err == nil { + err = closeErr + } + return err +} + +// removeOnce synchronises removal of stale workflow files. +var removeOnce sync.Once + +// removeWorkflows removes existing workflow files once. +func removeWorkflows() { + removeOnce.Do(func() { + if err := os.RemoveAll(workflowsDir); err != nil { + fmt.Println(err) + os.Exit(1) + } + if err := os.Mkdir(workflowsDir, 0755); err != nil { + fmt.Println(err) + os.Exit(1) + } + }) +} + +// mustWriteFile is like writeFile, but terminates the program if a non-nil +// error is returned. +func (w *Workflow) mustWriteFile(name string) (_ struct{}) { + removeWorkflows() + + if err := w.writeFile(name); err != nil { + fmt.Println(err) + os.Exit(1) + } + return +} + +func main() {} diff --git a/cmd/workflows/test.go b/cmd/workflows/test.go new file mode 100644 index 00000000..1bbb04f9 --- /dev/null +++ b/cmd/workflows/test.go @@ -0,0 +1,227 @@ +//go:build workflows + +package main + +var _ = (&Workflow{ + Name: "Test", + On: []any{"push"}, + + Jobs: Map[Job]{ + {K: "hakurei", V: Job{ + Name: "Hakurei", + On: "nix", + + Steps: []Step{ + { + Name: "Checkout", + Uses: "actions/checkout@v4", + }, + + { + Name: "Run NixOS test", + Run: "nix build " + + "--out-link result " + + "--print-out-paths " + + "--print-build-logs " + + "./test#checks.x86_64-linux.hakurei", + }, + + { + Name: "Upload test output", + Uses: "actions/upload-artifact@v3", + + With: Map[any]{ + {K: "name", V: "hakurei-vm-output"}, + {K: "path", V: "result/*"}, + + {K: "retention-days", V: 1}, + }, + }, + }, + }}, + + {K: "race", V: Job{ + Name: "Hakurei (race detector)", + On: "nix", + + Steps: []Step{ + {Name: "Checkout", Uses: "actions/checkout@v4"}, + + { + Name: "Run NixOS test", + Run: "nix build " + + "--out-link result " + + "--print-out-paths " + + "--print-build-logs " + + "./test#checks.x86_64-linux.race", + }, + + { + Name: "Upload test output", + Uses: "actions/upload-artifact@v3", + + With: Map[any]{ + {K: "name", V: "hakurei-race-vm-output"}, + {K: "path", V: "result/*"}, + + {K: "retention-days", V: 1}, + }, + }, + }, + }}, + + {K: "sandbox", V: Job{ + Name: "Sandbox", + On: "nix", + + Steps: []Step{ + {Name: "Checkout", Uses: "actions/checkout@v4"}, + + { + Name: "Run NixOS test", + Run: "nix build " + + "--out-link result " + + "--print-out-paths " + + "--print-build-logs " + + "./test#checks.x86_64-linux.sandbox", + }, + + { + Name: "Upload test output", + Uses: "actions/upload-artifact@v3", + + With: Map[any]{ + {K: "name", V: "sandbox-vm-output"}, + {K: "path", V: "result/*"}, + + {K: "retention-days", V: 1}, + }, + }, + }, + }}, + + {K: "sandbox-race", V: Job{ + Name: "Sandbox (race detector)", + On: "nix", + + Steps: []Step{ + {Name: "Checkout", Uses: "actions/checkout@v4"}, + + { + Name: "Run NixOS test", + Run: "nix build " + + "--out-link result " + + "--print-out-paths " + + "--print-build-logs " + + "./test#checks.x86_64-linux.sandbox-race", + }, + + { + Name: "Upload test output", + Uses: "actions/upload-artifact@v3", + + With: Map[any]{ + {K: "name", V: "sandbox-race-vm-output"}, + {K: "path", V: "result/*"}, + + {K: "retention-days", V: 1}, + }, + }, + }, + }}, + + {K: "sharefs", V: Job{ + Name: "ShareFS", + On: "nix", + + Steps: []Step{ + {Name: "Checkout", Uses: "actions/checkout@v4"}, + + { + Name: "Run NixOS test", + Run: "nix build " + + "--out-link result " + + "--print-out-paths " + + "--print-build-logs " + + "./test#checks.x86_64-linux.sharefs", + }, + + { + Name: "Upload test output", + Uses: "actions/upload-artifact@v3", + + With: Map[any]{ + {K: "name", V: "sharefs-vm-output"}, + {K: "path", V: "result/*"}, + + {K: "retention-days", V: 1}, + }, + }, + }, + }}, + + {K: "check", V: Job{ + Name: "Flake checks", + On: "nix", + + Needs: []string{ + "hakurei", + "race", + "sandbox", + "sandbox-race", + "sharefs", + }, + + Steps: []Step{ + { + Name: "Checkout", + Uses: "actions/checkout@v4", + }, + + { + Name: "Run checks", + Run: "nix " + + "--print-build-logs " + + "--experimental-features 'nix-command flakes' " + + "flake check ./test", + }, + }, + }}, + + {K: "dist", V: Job{ + Name: "Create distribution", + On: "nix", + + Steps: []Step{ + { + Name: "Checkout", + Uses: "actions/checkout@v4", + }, + + { + Name: "Build for test", + ID: "build-test", + Run: "export HAKUREI_REV=\"$(git rev-parse --short HEAD)\" && " + + "sed -i.old " + + "'s/version = /version = \"0.0.0-'$HAKUREI_REV'\"; # version = /' " + + "test/package.nix && " + + "nix build --print-out-paths --print-build-logs ./test#dist && " + + "mv test/{package.nix.old,package.nix} && " + + "echo \"rev=$HAKUREI_REV\" >> $GITHUB_OUTPUT", + }, + + { + Name: "Upload test build", + Uses: "actions/upload-artifact@v3", + + With: Map[any]{ + {K: "name", V: "hakurei-${{ steps.build-test.outputs.rev }}"}, + {K: "path", V: "result/*"}, + + {K: "retention-days", V: 1}, + }, + }, + }, + }}, + }, +}).mustWriteFile("test") |
