diff --git a/.github/workflows/goreleaser.yaml b/.github/workflows/goreleaser.yaml index 68277cd..cca3de6 100644 --- a/.github/workflows/goreleaser.yaml +++ b/.github/workflows/goreleaser.yaml @@ -11,7 +11,32 @@ permissions: id-token: write jobs: + lint-test: + runs-on: ubuntu-24.04 + permissions: + contents: read + steps: + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + + - name: Set up Go + uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6 + with: + go-version: ">=1.26.1" + + - name: golangci-lint + uses: golangci/golangci-lint-action@82606bf257cbaff209d206a39f5134f0cfbfd2ee # v9 + with: + version: latest + install-only: true + + - name: lint + run: make lint + + - name: unit test + run: make test + goreleaser: + needs: lint-test uses: libops/.github/.github/workflows/sitectl-plugin-goreleaser.yaml@main permissions: contents: write diff --git a/.github/workflows/integration-test.yaml b/.github/workflows/integration-test.yaml new file mode 100644 index 0000000..2bc7159 --- /dev/null +++ b/.github/workflows/integration-test.yaml @@ -0,0 +1,43 @@ +name: integration-test + +on: + pull_request: + workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: integration-test-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +jobs: + create-ojs: + name: sitectl create ojs ${{ matrix.create_definition }} + runs-on: ubuntu-24.04 + strategy: + fail-fast: false + matrix: + include: + - create_definition: default + create_args: "" + steps: + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 + + - name: Set up Go + uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c + with: + go-version: ">=1.26.1" + + - name: Install sitectl + uses: libops/.github/.github/actions/install-sitectl@main + + - name: setup git identity + run: | + git config --global user.email "actions@github.com" + git config --global user.name "GitHub Actions" + + - name: Run create integration test + run: make integration-test CREATE_DEFINITION=${{ matrix.create_definition }} CREATE_ARGS="${{ matrix.create_args }}" + env: + TERM: xterm-256color diff --git a/.github/workflows/lint-test.yaml b/.github/workflows/lint-test.yaml new file mode 100644 index 0000000..60456ec --- /dev/null +++ b/.github/workflows/lint-test.yaml @@ -0,0 +1,28 @@ +name: lint-test +on: [push] +permissions: + contents: read + packages: write + +jobs: + lint-test: + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + + - name: Set up Go + uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6 + with: + go-version: ">=1.26.1" + + - name: golangci-lint + uses: golangci/golangci-lint-action@82606bf257cbaff209d206a39f5134f0cfbfd2ee # v9 + with: + version: latest + install-only: true + + - name: lint + run: make lint + + - name: unit test + run: make test diff --git a/.gitignore b/.gitignore index 4369e43..dbcd14a 100644 --- a/.gitignore +++ b/.gitignore @@ -5,8 +5,8 @@ bin/ *.dll *.so *.dylib -sitectl-isle -sitectl-isle-* +sitectl-ojs +sitectl-ojs-* # Test binary, built with `go test -c` *.test @@ -39,5 +39,4 @@ temp/ # Build artifacts dist/ release/ -sitectl-ojs .cache diff --git a/.goreleaser.yaml b/.goreleaser.yaml index aadab83..f786a3d 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -47,6 +47,7 @@ brews: name: homebrew dependencies: - name: "libops/homebrew/sitectl" + - name: "libops/homebrew/sitectl-triplet" nfpms: - id: sitectl-ojs package_name: sitectl-ojs diff --git a/Makefile b/Makefile index 58880f6..579bc81 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,9 @@ -.PHONY: build deps test work install +.PHONY: build deps lint test work install integration-test BINARY_NAME=sitectl-ojs +CREATE_DEFINITION?=default +CREATE_ARGS?= +SITECTL_CONTEXT?=integration-test deps: work go mod tidy @@ -11,8 +14,15 @@ build: install: build mv $(BINARY_NAME) /usr/local/bin +lint: + go fmt ./... + golangci-lint run + test: build - go test ./... + go test -v -race ./... work: ./scripts/use-go-work.sh + +integration-test: + SITECTL_CONTEXT="$(SITECTL_CONTEXT)" CREATE_DEFINITION="$(CREATE_DEFINITION)" CREATE_ARGS="$(CREATE_ARGS)" ./scripts/test-create.sh diff --git a/cmd/dependencies.go b/cmd/dependencies.go new file mode 100644 index 0000000..9e474ae --- /dev/null +++ b/cmd/dependencies.go @@ -0,0 +1,6 @@ +package cmd + +// IncludedPlugins returns application plugins accepted by OJS contexts. +func IncludedPlugins() []string { + return []string{} +} diff --git a/cmd/dependencies_test.go b/cmd/dependencies_test.go new file mode 100644 index 0000000..1ad971b --- /dev/null +++ b/cmd/dependencies_test.go @@ -0,0 +1,15 @@ +package cmd + +import ( + "reflect" + "testing" +) + +func TestIncludedPlugins(t *testing.T) { + t.Parallel() + + want := []string{} + if got := IncludedPlugins(); !reflect.DeepEqual(got, want) { + t.Fatalf("IncludedPlugins() = %v, want %v", got, want) + } +} diff --git a/cmd/healthcheck.go b/cmd/healthcheck.go new file mode 100644 index 0000000..3938b51 --- /dev/null +++ b/cmd/healthcheck.go @@ -0,0 +1,30 @@ +package cmd + +import ( + "github.com/libops/sitectl/pkg/config" + "github.com/libops/sitectl/pkg/healthcheck" + "github.com/libops/sitectl/pkg/plugin" + sitevalidate "github.com/libops/sitectl/pkg/validate" + "github.com/spf13/cobra" +) + +type ojsHealthcheckRunner struct{} + +func (ojsHealthcheckRunner) BindFlags(cmd *cobra.Command) {} + +func (ojsHealthcheckRunner) Run(cmd *cobra.Command, ctx *config.Context) ([]sitevalidate.Result, error) { + results := []sitevalidate.Result{ + healthcheck.CheckHTTP(cmd.Context(), "http:ojs", healthcheck.PublicURLFromEnv(ctx, "http", "localhost")), + } + + checker, err := healthcheck.NewDockerChecker(ctx) + if err != nil { + return nil, err + } + defer func() { _ = checker.Close() }() + + results = append(results, checker.CheckMariaDB(cmd.Context(), "mariadb")) + return results, nil +} + +var _ plugin.HealthcheckRunner = ojsHealthcheckRunner{} diff --git a/cmd/root.go b/cmd/root.go index caa2be0..23269d6 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -7,7 +7,6 @@ const ( createBranch = "main" pluginName = "ojs" defaultPath = "./ojs" - displayName = "OJS" ) func createDefinition() plugin.CreateSpec { @@ -34,12 +33,11 @@ func RegisterCommands(s *plugin.SDK) { RequiredServices: []string{"ojs"}, Reason: "ojs service", }) - s.AddCommand(s.GetDiscoveryMetadataCommand()) - plugin.RegisterStandardComposeTemplate(s, createDefinition(), plugin.StandardComposeTemplateOptions{ + s.RegisterComposeTemplateCreateRunner(createDefinition(), plugin.ComposeTemplateCreateOptions{ DefaultPath: defaultPath, DefaultPlugin: pluginName, ReadyMessage: "OJS is ready for use through sitectl.", - DisplayName: displayName, }) + s.RegisterHealthcheckRunner(ojsHealthcheckRunner{}) registerOJSCommands(s) } diff --git a/go.mod b/go.mod index 2ab04e1..94bb66c 100644 --- a/go.mod +++ b/go.mod @@ -3,24 +3,29 @@ module github.com/libops/sitectl-ojs go 1.26.1 require ( - github.com/libops/sitectl v0.17.1 + github.com/libops/sitectl v0.19.2 github.com/spf13/cobra v1.10.2 ) require ( charm.land/bubbles/v2 v2.1.0 // indirect - charm.land/bubbletea/v2 v2.0.6 // indirect + charm.land/bubbletea/v2 v2.0.7 // indirect charm.land/fang/v2 v2.0.1 // indirect + charm.land/glamour/v2 v2.0.0 // indirect charm.land/lipgloss/v2 v2.0.3 // indirect github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect github.com/Microsoft/go-winio v0.6.2 // indirect + github.com/NimbleMarkets/ntcharts/v2 v2.2.0 // indirect + github.com/alecthomas/chroma/v2 v2.26.1 // indirect github.com/atotto/clipboard v0.1.4 // indirect + github.com/aymerick/douceur v0.2.0 // indirect github.com/cenkalti/backoff/v5 v5.0.3 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/charmbracelet/colorprofile v0.4.3 // indirect - github.com/charmbracelet/ultraviolet v0.0.0-20260525132238-948f4557a654 // indirect + github.com/charmbracelet/ultraviolet v0.0.0-20260601155805-6cf7526a1b3f // indirect github.com/charmbracelet/x/ansi v0.11.7 // indirect - github.com/charmbracelet/x/exp/charmtone v0.0.0-20260525135217-abeec2b8bf0b // indirect + github.com/charmbracelet/x/exp/charmtone v0.0.0-20260602025833-85a30b5e440a // indirect + github.com/charmbracelet/x/exp/slice v0.0.0-20260602025833-85a30b5e440a // indirect github.com/charmbracelet/x/term v0.2.2 // indirect github.com/charmbracelet/x/termios v0.1.1 // indirect github.com/charmbracelet/x/windows v0.2.2 // indirect @@ -29,18 +34,22 @@ require ( github.com/containerd/errdefs v1.0.0 // indirect github.com/containerd/errdefs/pkg v0.3.0 // indirect github.com/distribution/reference v0.6.0 // indirect + github.com/dlclark/regexp2/v2 v2.1.2 // indirect github.com/docker/docker v28.5.2+incompatible // indirect github.com/docker/go-connections v0.7.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/go-logr/logr v1.4.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect + github.com/gorilla/css v1.0.1 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/joho/godotenv v1.5.1 // indirect github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect github.com/kr/fs v0.1.0 // indirect + github.com/lrstanley/bubblezone/v2 v2.0.0 // indirect github.com/lucasb-eyer/go-colorful v1.4.0 // indirect - github.com/mattn/go-runewidth v0.0.23 // indirect + github.com/mattn/go-runewidth v0.0.24 // indirect + github.com/microcosm-cc/bluemonday v1.0.27 // indirect github.com/moby/docker-image-spec v1.3.1 // indirect github.com/moby/sys/sequential v0.6.0 // indirect github.com/muesli/cancelreader v0.2.2 // indirect @@ -56,14 +65,17 @@ require ( github.com/sahilm/fuzzy v0.1.2 // indirect github.com/spf13/pflag v1.0.10 // indirect github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect + github.com/yuin/goldmark v1.8.2 // indirect + github.com/yuin/goldmark-emoji v1.0.6 // indirect go.opentelemetry.io/auto/sdk v1.2.1 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0 // indirect - go.opentelemetry.io/otel v1.43.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.69.0 // indirect + go.opentelemetry.io/otel v1.44.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.43.0 // indirect - go.opentelemetry.io/otel/metric v1.43.0 // indirect - go.opentelemetry.io/otel/trace v1.43.0 // indirect + go.opentelemetry.io/otel/metric v1.44.0 // indirect + go.opentelemetry.io/otel/trace v1.44.0 // indirect go.opentelemetry.io/proto/otlp v1.10.0 // indirect golang.org/x/crypto v0.52.0 // indirect + golang.org/x/net v0.55.0 // indirect golang.org/x/sync v0.20.0 // indirect golang.org/x/sys v0.45.0 // indirect golang.org/x/term v0.43.0 // indirect diff --git a/go.sum b/go.sum index eebbfe3..5d7fecc 100644 --- a/go.sum +++ b/go.sum @@ -1,33 +1,43 @@ charm.land/bubbles/v2 v2.1.0 h1:YSnNh5cPYlYjPxRrzs5VEn3vwhtEn3jVGRBT3M7/I0g= charm.land/bubbles/v2 v2.1.0/go.mod h1:l97h4hym2hvWBVfmJDtrEHHCtkIKeTEb3TTJ4ZOB3wY= -charm.land/bubbletea/v2 v2.0.6 h1:UHN/91OyuhaOFGSrBXQ/hMZD8IO1Uc4BvHlgHXL2WJo= -charm.land/bubbletea/v2 v2.0.6/go.mod h1:MH/D8ZLlN3op37vQvijKuU29g3rqTp+aQapURFonF9g= +charm.land/bubbletea/v2 v2.0.7 h1:7qw2tTAVar7m7klOPBYfTB0mniv/RuexsYwMRNxSeL0= +charm.land/bubbletea/v2 v2.0.7/go.mod h1:DGW2q8gvzHnOpMpZTORs0aySVHCox5C+2Svk0fci1qs= charm.land/fang/v2 v2.0.1 h1:zQCM8JQJ1JnQX/66B5jlCYBUxL2as5JXQZ2KJ6EL0mY= charm.land/fang/v2 v2.0.1/go.mod h1:S1GmkpcvK+OB5w9caywUnJcsMew45Ot8FXqoz8ALrII= +charm.land/glamour/v2 v2.0.0 h1:IDBoqLEy7Hdpb9VOXN+khLP/XSxtJy1VsHuW/yF87+U= +charm.land/glamour/v2 v2.0.0/go.mod h1:kjq9WB0s8vuUYZNYey2jp4Lgd9f4cKdzAw88FZtpj/w= charm.land/lipgloss/v2 v2.0.3 h1:yM2zJ4Cf5Y51b7RHIwioil4ApI/aypFXXVHSwlM6RzU= charm.land/lipgloss/v2 v2.0.3/go.mod h1:7myLU9iG/3xluAWzpY/fSxYYHCgoKTie7laxk6ATwXA= github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg= github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= +github.com/NimbleMarkets/ntcharts/v2 v2.2.0 h1:c173B0dc2eaJMJGEzlGEn8AVpuupIot5BkqLawJrVVo= +github.com/NimbleMarkets/ntcharts/v2 v2.2.0/go.mod h1:/REzF4aM+P5xGMUHtYczoTtQNL9E65mxOTyQPgiXkUQ= +github.com/alecthomas/chroma/v2 v2.26.1 h1:2X21EdxGZNv5GF9mG5u+uzc02GCFyGxbcBm3Grd9A78= +github.com/alecthomas/chroma/v2 v2.26.1/go.mod h1:lxhRRa9H4hPmRLOOdYga4zkQIQjq3dtrrdwQeCfu78Y= github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4= github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI= github.com/aymanbagabas/go-udiff v0.4.1 h1:OEIrQ8maEeDBXQDoGCbbTTXYJMYRCRO1fnodZ12Gv5o= github.com/aymanbagabas/go-udiff v0.4.1/go.mod h1:0L9PGwj20lrtmEMeyw4WKJ/TMyDtvAoK9bf2u/mNo3w= +github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= +github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM= github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/charmbracelet/colorprofile v0.4.3 h1:QPa1IWkYI+AOB+fE+mg/5/4HRMZcaXex9t5KX76i20Q= github.com/charmbracelet/colorprofile v0.4.3/go.mod h1:/zT4BhpD5aGFpqQQqw7a+VtHCzu+zrQtt1zhMt9mR4Q= -github.com/charmbracelet/ultraviolet v0.0.0-20260525132238-948f4557a654 h1:FpSYhY28ucg9ZRr+2wj67FAQ0Ey5yiK0072PmRDJNek= -github.com/charmbracelet/ultraviolet v0.0.0-20260525132238-948f4557a654/go.mod h1:hFpumms29Smx3LStRfku8vcCTBe1Kq8aCXtHUJa3mjY= +github.com/charmbracelet/ultraviolet v0.0.0-20260601155805-6cf7526a1b3f h1:vKsPSlO4g4jKfJ9enESgNZ45BkbHngTIq3UxNOzic74= +github.com/charmbracelet/ultraviolet v0.0.0-20260601155805-6cf7526a1b3f/go.mod h1:hFpumms29Smx3LStRfku8vcCTBe1Kq8aCXtHUJa3mjY= github.com/charmbracelet/x/ansi v0.11.7 h1:kzv1kJvjg2S3r9KHo8hDdHFQLEqn4RBCb39dAYC84jI= github.com/charmbracelet/x/ansi v0.11.7/go.mod h1:9qGpnAVYz+8ACONkZBUWPtL7lulP9No6p1epAihUZwQ= -github.com/charmbracelet/x/exp/charmtone v0.0.0-20260525135217-abeec2b8bf0b h1:8eaOsqj4avmPlTVXAQE9Z/SWqKc5imsBXdcdkaZb1QE= -github.com/charmbracelet/x/exp/charmtone v0.0.0-20260525135217-abeec2b8bf0b/go.mod h1:nsExn0DGyX0lh9LwLHTn2Gg+hafdzfSXnC+QmEJTZFY= +github.com/charmbracelet/x/exp/charmtone v0.0.0-20260602025833-85a30b5e440a h1:aVvnksCVgxB2igk7jERL9ARIkbDXccp1gXCFqhGlamQ= +github.com/charmbracelet/x/exp/charmtone v0.0.0-20260602025833-85a30b5e440a/go.mod h1:nsExn0DGyX0lh9LwLHTn2Gg+hafdzfSXnC+QmEJTZFY= github.com/charmbracelet/x/exp/golden v0.0.0-20250806222409-83e3a29d542f h1:pk6gmGpCE7F3FcjaOEKYriCvpmIN4+6OS/RD0vm4uIA= github.com/charmbracelet/x/exp/golden v0.0.0-20250806222409-83e3a29d542f/go.mod h1:IfZAMTHB6XkZSeXUqriemErjAWCCzT0LwjKFYCZyw0I= +github.com/charmbracelet/x/exp/slice v0.0.0-20260602025833-85a30b5e440a h1:wjp4RGuKcbK244BiURmgle3N9HMT1ParMh96omH6Lj4= +github.com/charmbracelet/x/exp/slice v0.0.0-20260602025833-85a30b5e440a/go.mod h1:vqEfX6xzqW1pKKZUUiFOKg0OQ7bCh54Q2vR/tserrRA= github.com/charmbracelet/x/term v0.2.2 h1:xVRT/S2ZcKdhhOuSP4t5cLi5o+JxklsoEObBSgfgZRk= github.com/charmbracelet/x/term v0.2.2/go.mod h1:kF8CY5RddLWrsgVwpw4kAa6TESp6EB5y3uxGLeCqzAI= github.com/charmbracelet/x/termios v0.1.1 h1:o3Q2bT8eqzGnGPOYheoYS8eEleT5ZVNYNy8JawjaNZY= @@ -49,6 +59,8 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= +github.com/dlclark/regexp2/v2 v2.1.2 h1:RJjAeD/h91npDhTG4rMD4+gzGVnLT32qQy/q/ECbyUs= +github.com/dlclark/regexp2/v2 v2.1.2/go.mod h1:avUrQvPaLz2DrFNHJF0taWAFFX2C1GMSSoeiqFjcBmU= github.com/docker/docker v28.5.2+incompatible h1:DBX0Y0zAjZbSrm1uzOkdr1onVghKaftjlSWt4AFexzM= github.com/docker/docker v28.5.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.7.0 h1:6SsRfJddP22WMrCkj19x9WKjEDTB+ahsdiGYf0mN39c= @@ -66,6 +78,8 @@ github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/css v1.0.1 h1:ntNaBIghp6JmvWnxbZKANoLyuXTPZ4cAMlo6RyhlbO8= +github.com/gorilla/css v1.0.1/go.mod h1:BvnYkspnSzMmwRK+b8/xgNPLiIuNZr6vbZBTPQ2A3b0= github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0 h1:HWRh5R2+9EifMyIHV7ZV+MIZqgz+PMpZ14Jynv3O2Zs= github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0/go.mod h1:JfhWUomR1baixubs02l85lZYYOm7LV6om4ceouMv45c= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= @@ -82,12 +96,20 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/libops/sitectl v0.17.1 h1:+cCHh1xYW0Rz8J98G2o7Px9snkTaoxeOYbDybIUcDcw= -github.com/libops/sitectl v0.17.1/go.mod h1:HAKa1E20tpogWyFaz5RYvYGHxpWH+4V1OBw/ulAglm8= +github.com/libops/sitectl v0.18.1 h1:Z7iSuEv8cZ67SOa9p2AtI39P+ZqVKLvTqUTBlvqhsjU= +github.com/libops/sitectl v0.18.1/go.mod h1:3sK7qEeV6MHAUZ81USMd8EQbX3XfvEmbZt/S6lZtAw0= +github.com/libops/sitectl v0.19.0 h1:+6UDuhUwWk0agEGeSvIf/JAtuegWI0C4ZuoxdlbUwtE= +github.com/libops/sitectl v0.19.0/go.mod h1:3sK7qEeV6MHAUZ81USMd8EQbX3XfvEmbZt/S6lZtAw0= +github.com/libops/sitectl v0.19.2 h1:XUIoU8st3uJWSbzkKlYCzNcJQouv9pys61/Cg/T588E= +github.com/libops/sitectl v0.19.2/go.mod h1:3sK7qEeV6MHAUZ81USMd8EQbX3XfvEmbZt/S6lZtAw0= +github.com/lrstanley/bubblezone/v2 v2.0.0 h1:pMb9fHKs0slJF6OrzQ2hEgWusqyl9VU/S0UZ5hyh7ZA= +github.com/lrstanley/bubblezone/v2 v2.0.0/go.mod h1:yV/QTjcm4Zu5cqvGvdHi7xVUfnB36w/SafOuDp57dgY= github.com/lucasb-eyer/go-colorful v1.4.0 h1:UtrWVfLdarDgc44HcS7pYloGHJUjHV/4FwW4TvVgFr4= github.com/lucasb-eyer/go-colorful v1.4.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= -github.com/mattn/go-runewidth v0.0.23 h1:7ykA0T0jkPpzSvMS5i9uoNn2Xy3R383f9HDx3RybWcw= -github.com/mattn/go-runewidth v0.0.23/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs= +github.com/mattn/go-runewidth v0.0.24 h1:cpokDiIn0MGnhdHwuWnJBITySJ20QyNGnY2kR/ay2DU= +github.com/mattn/go-runewidth v0.0.24/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs= +github.com/microcosm-cc/bluemonday v1.0.27 h1:MpEUotklkwCSLeH+Qdx1VJgNqLlpY2KXwXFM08ygZfk= +github.com/microcosm-cc/bluemonday v1.0.27/go.mod h1:jFi9vgW+H7c3V0lb6nR74Ib/DIB5OBs92Dimizgw2cA= github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= github.com/moby/sys/atomicwriter v0.1.0 h1:kw5D/EqkBwsBFi0ss9v1VG3wIkVhzGvLklJ+w3A14Sw= @@ -136,24 +158,28 @@ github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no= github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM= +github.com/yuin/goldmark v1.8.2 h1:kEGpgqJXdgbkhcOgBxkC0X0PmoPG1ZyoZ117rDVp4zE= +github.com/yuin/goldmark v1.8.2/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg= +github.com/yuin/goldmark-emoji v1.0.6 h1:QWfF2FYaXwL74tfGOW5izeiZepUDroDJfWubQI9HTHs= +github.com/yuin/goldmark-emoji v1.0.6/go.mod h1:ukxJDKFpdFb5x0a5HqbdlcKtebh086iJpI31LTKmWuA= go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0 h1:CqXxU8VOmDefoh0+ztfGaymYbhdB/tT3zs79QaZTNGY= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0/go.mod h1:BuhAPThV8PBHBvg8ZzZ/Ok3idOdhWIodywz2xEcRbJo= -go.opentelemetry.io/otel v1.43.0 h1:mYIM03dnh5zfN7HautFE4ieIig9amkNANT+xcVxAj9I= -go.opentelemetry.io/otel v1.43.0/go.mod h1:JuG+u74mvjvcm8vj8pI5XiHy1zDeoCS2LB1spIq7Ay0= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.69.0 h1:8tvICD4vSTOOsNrsI4Ljf6C+6UKvpTEH5XY3JMoyPoo= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.69.0/go.mod h1:z9+yiacE0IHRqM4qFfkbt/JYlmYXgss8GY/jXoNuPJI= +go.opentelemetry.io/otel v1.44.0 h1:JjwHmHpA4iZ3wBxluu2fbbE7j4kqlE8jXyAyPXH7HqU= +go.opentelemetry.io/otel v1.44.0/go.mod h1:BMgjTHL9WPRlRjL2oZCBTL4whCGtXch2H4BhOPIAyYc= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.43.0 h1:88Y4s2C8oTui1LGM6bTWkw0ICGcOLCAI5l6zsD1j20k= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.43.0/go.mod h1:Vl1/iaggsuRlrHf/hfPJPvVag77kKyvrLeD10kpMl+A= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.43.0 h1:3iZJKlCZufyRzPzlQhUIWVmfltrXuGyfjREgGP3UUjc= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.43.0/go.mod h1:/G+nUPfhq2e+qiXMGxMwumDrP5jtzU+mWN7/sjT2rak= -go.opentelemetry.io/otel/metric v1.43.0 h1:d7638QeInOnuwOONPp4JAOGfbCEpYb+K6DVWvdxGzgM= -go.opentelemetry.io/otel/metric v1.43.0/go.mod h1:RDnPtIxvqlgO8GRW18W6Z/4P462ldprJtfxHxyKd2PY= -go.opentelemetry.io/otel/sdk v1.43.0 h1:pi5mE86i5rTeLXqoF/hhiBtUNcrAGHLKQdhg4h4V9Dg= -go.opentelemetry.io/otel/sdk v1.43.0/go.mod h1:P+IkVU3iWukmiit/Yf9AWvpyRDlUeBaRg6Y+C58QHzg= -go.opentelemetry.io/otel/sdk/metric v1.43.0 h1:S88dyqXjJkuBNLeMcVPRFXpRw2fuwdvfCGLEo89fDkw= -go.opentelemetry.io/otel/sdk/metric v1.43.0/go.mod h1:C/RJtwSEJ5hzTiUz5pXF1kILHStzb9zFlIEe85bhj6A= -go.opentelemetry.io/otel/trace v1.43.0 h1:BkNrHpup+4k4w+ZZ86CZoHHEkohws8AY+WTX09nk+3A= -go.opentelemetry.io/otel/trace v1.43.0/go.mod h1:/QJhyVBUUswCphDVxq+8mld+AvhXZLhe+8WVFxiFff0= +go.opentelemetry.io/otel/metric v1.44.0 h1:1w0gILTcHdr3YI+ixLyjemwrVnsMURbTZFrSYCdDdmc= +go.opentelemetry.io/otel/metric v1.44.0/go.mod h1:8O7hanEPBNgEMmybD3s2VBKcgWOCsA6tzHBPODAiquo= +go.opentelemetry.io/otel/sdk v1.44.0 h1:nHYwb9lK+fJPU/dnT6s7W7Z8itMWyqrnVfbheVYrZ58= +go.opentelemetry.io/otel/sdk v1.44.0/go.mod h1:Osuydd3Se74nqjAKxid74N5eC+jfEqfTegHRnq58oK0= +go.opentelemetry.io/otel/sdk/metric v1.44.0 h1:3LlKgI+VjbVsjNRFZJZAJ30WjXC5VkNRks6si09iEfI= +go.opentelemetry.io/otel/sdk/metric v1.44.0/go.mod h1:5B5pMARnXxKhltooO4xUuCBorl65a4EpnTalObqOigA= +go.opentelemetry.io/otel/trace v1.44.0 h1:jxF5CsGYCe74MCRx2X4g7WsY/VBKRqqpNvXlX/6gtIk= +go.opentelemetry.io/otel/trace v1.44.0/go.mod h1:oLl1jrMQAVo6v3GAggN+1VH9VIz9iUSvW53sW1Q8PIE= go.opentelemetry.io/proto/otlp v1.10.0 h1:IQRWgT5srOCYfiWnpqUYz9CVmbO8bFmKcwYxpuCSL2g= go.opentelemetry.io/proto/otlp v1.10.0/go.mod h1:/CV4QoCR/S9yaPj8utp3lvQPoqMtxXdzn7ozvvozVqk= go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= diff --git a/main.go b/main.go index e38d390..13eb326 100644 --- a/main.go +++ b/main.go @@ -20,6 +20,7 @@ func main() { Description: "Open Journal Systems helpers", Author: "libops", TemplateRepo: "https://github.com/libops/ojs", + Includes: cmd.IncludedPlugins(), }) cmd.RegisterCommands(sdk) diff --git a/scripts/test-create.sh b/scripts/test-create.sh new file mode 100755 index 0000000..68b0370 --- /dev/null +++ b/scripts/test-create.sh @@ -0,0 +1,132 @@ +#!/usr/bin/env bash + +set -euo pipefail +set -x + +export TERM="${TERM:-dumb}" + +PLUGIN_NAME="ojs" +PLUGIN_BINARY="sitectl-ojs" +SITE_DIR_NAME="ojs" +CREATE_DEFINITION="${CREATE_DEFINITION:-default}" +CREATE_ARGS="${CREATE_ARGS:-}" +SITECTL_CONTEXT="${SITECTL_CONTEXT:-integration-test}" + +REPO_ROOT="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." &>/dev/null && pwd)" + +if [ -n "${SITECTL_TMP_PARENT:-}" ]; then + TMP_PARENT="${SITECTL_TMP_PARENT}" +elif [ -n "${GITHUB_WORKSPACE:-}" ]; then + TMP_PARENT="${GITHUB_WORKSPACE}" +else + TMP_PARENT="${HOME}/.tmp" +fi +mkdir -p "${TMP_PARENT}" +TMP_DIR="$(mktemp -d "${TMP_PARENT%/}/${PLUGIN_BINARY}-test.XXXXXX")" +SITECTL_HOME="${TMP_DIR}/home" +BIN_DIR="${TMP_DIR}/bin" +SITE_DIR="${TMP_DIR}/${SITE_DIR_NAME}" +PATH="${BIN_DIR}:${PATH}" +export PATH +mkdir -p "${SITECTL_HOME}" + +dump_compose_debug() { + ( + cd "${SITE_DIR}" || exit 0 + docker compose logs --no-color --tail=200 || true + docker compose ps -a || true + ) +} + +remove_tmp_dir() { + if [ ! -d "${TMP_DIR}" ]; then + return + fi + chmod -R u+rwX "${TMP_DIR}" 2>/dev/null || true + if rm -rf "${TMP_DIR}" 2>/dev/null; then + return + fi + if command -v sudo >/dev/null 2>&1; then + sudo chown -R "$(id -u):$(id -g)" "${TMP_DIR}" 2>/dev/null || true + sudo chmod -R u+rwX "${TMP_DIR}" 2>/dev/null || true + fi + rm -rf "${TMP_DIR}" +} + +cleanup() { + if [ -d "${SITE_DIR}" ] && command -v sitectl >/dev/null 2>&1; then + HOME="${SITECTL_HOME}" sitectl compose down -v --remove-orphans >/dev/null 2>&1 || true + fi + remove_tmp_dir +} +trap cleanup EXIT + +build_plugin() { + mkdir -p "${BIN_DIR}" + ( + cd "${REPO_ROOT}" && + go build -o "${BIN_DIR}/${PLUGIN_BINARY}" . + ) + command -v sitectl >/dev/null + command -v "${PLUGIN_BINARY}" >/dev/null +} + +create_site() { + local target="${PLUGIN_NAME}/${CREATE_DEFINITION}" + local extra_args=() + if [ -n "${CREATE_ARGS}" ]; then + read -r -a extra_args <<< "${CREATE_ARGS}" + fi + + HOME="${SITECTL_HOME}" sitectl create "${target}" \ + --path "${SITE_DIR}" \ + --type local \ + --checkout-source template \ + --default-context \ + --setup-only \ + "${extra_args[@]}" +} + +run_make_target() { + local target="$1" + if ! ( + cd "${SITE_DIR}" && + make "${target}" + ); then + dump_compose_debug + exit 1 + fi +} + +run_healthcheck() { + local timeout="${SITECTL_HEALTHCHECK_TIMEOUT:-300}" + local interval="${SITECTL_HEALTHCHECK_INTERVAL:-10}" + local start="${SECONDS}" + local attempt=0 + + while true; do + attempt=$((attempt + 1)) + echo "Healthcheck attempt ${attempt}..." + if HOME="${SITECTL_HOME}" sitectl healthcheck; then + return 0 + fi + + if [ $((SECONDS - start)) -ge "${timeout}" ]; then + echo "sitectl healthcheck did not pass within ${timeout}s" >&2 + dump_compose_debug + return 1 + fi + + sleep "${interval}" + done +} + +main() { + build_plugin + create_site + run_make_target init + run_make_target up + run_healthcheck +} + +main "$@" diff --git a/scripts/use-go-work.sh b/scripts/use-go-work.sh index 586e87c..8888774 100755 --- a/scripts/use-go-work.sh +++ b/scripts/use-go-work.sh @@ -11,14 +11,18 @@ if [[ ! -f "${SITECTL_GOMOD}" ]]; then exit 0 fi -cat > go.work < go.work echo "Wrote go.work using local sitectl checkout at ${SITECTL_PATH}" -