feat(build): expose release workflow generation
This commit is contained in:
parent
20f6f8e538
commit
eeb87e0444
4 changed files with 93 additions and 2 deletions
|
|
@ -105,6 +105,7 @@ func (p *BuildProvider) RegisterRoutes(rg *gin.RouterGroup) {
|
|||
rg.GET("/release/version", p.getVersion)
|
||||
rg.GET("/release/changelog", p.getChangelog)
|
||||
rg.POST("/release", p.triggerRelease)
|
||||
rg.POST("/release/workflow", p.generateReleaseWorkflow)
|
||||
|
||||
// SDK
|
||||
rg.GET("/sdk/diff", p.getSdkDiff)
|
||||
|
|
@ -165,6 +166,13 @@ func (p *BuildProvider) Describe() []api.RouteDescription {
|
|||
Description: "Publishes pre-built artifacts from dist/ to configured targets.",
|
||||
Tags: []string{"release"},
|
||||
},
|
||||
{
|
||||
Method: "POST",
|
||||
Path: "/release/workflow",
|
||||
Summary: "Generate release workflow",
|
||||
Description: "Writes the embedded GitHub Actions release workflow into .github/workflows/release.yml or a custom path.",
|
||||
Tags: []string{"release", "workflow"},
|
||||
},
|
||||
{
|
||||
Method: "GET",
|
||||
Path: "/sdk/diff",
|
||||
|
|
@ -504,6 +512,38 @@ func (p *BuildProvider) triggerRelease(c *gin.Context) {
|
|||
}))
|
||||
}
|
||||
|
||||
type releaseWorkflowRequest struct {
|
||||
Path string `json:"path"`
|
||||
}
|
||||
|
||||
func (p *BuildProvider) generateReleaseWorkflow(c *gin.Context) {
|
||||
dir, err := p.resolveDir()
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, api.Fail("resolve_failed", err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
var req releaseWorkflowRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
req.Path = ""
|
||||
}
|
||||
|
||||
path := req.Path
|
||||
if path == "" {
|
||||
path = build.ReleaseWorkflowPath(dir)
|
||||
}
|
||||
|
||||
if err := build.WriteReleaseWorkflow(p.medium, path); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, api.Fail("workflow_write_failed", err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, api.OK(map[string]any{
|
||||
"generated": true,
|
||||
"path": path,
|
||||
}))
|
||||
}
|
||||
|
||||
// -- SDK Handlers -------------------------------------------------------------
|
||||
|
||||
func (p *BuildProvider) getSdkDiff(c *gin.Context) {
|
||||
|
|
|
|||
|
|
@ -3,9 +3,14 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io/fs"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"dappco.re/go/core/build/internal/ax"
|
||||
"dappco.re/go/core/build/pkg/build"
|
||||
"dappco.re/go/core/io"
|
||||
|
|
@ -45,8 +50,8 @@ func TestProvider_BuildProviderDescribe_Good(t *testing.T) {
|
|||
p := NewProvider(".", nil)
|
||||
routes := p.Describe()
|
||||
|
||||
// Should have 9 endpoint descriptions
|
||||
assert.Len(t, routes, 9)
|
||||
// Should have 10 endpoint descriptions
|
||||
assert.Len(t, routes, 10)
|
||||
|
||||
// Verify key routes exist
|
||||
paths := make(map[string]string)
|
||||
|
|
@ -61,6 +66,7 @@ func TestProvider_BuildProviderDescribe_Good(t *testing.T) {
|
|||
assert.Equal(t, "GET", paths["/release/version"])
|
||||
assert.Equal(t, "GET", paths["/release/changelog"])
|
||||
assert.Equal(t, "POST", paths["/release"])
|
||||
assert.Equal(t, "POST", paths["/release/workflow"])
|
||||
assert.Equal(t, "GET", paths["/sdk/diff"])
|
||||
assert.Equal(t, "POST", paths["/sdk/generate"])
|
||||
}
|
||||
|
|
@ -152,3 +158,27 @@ func TestProvider_ResolveProjectType_Good(t *testing.T) {
|
|||
assert.Equal(t, build.ProjectTypeGo, projectType)
|
||||
})
|
||||
}
|
||||
|
||||
func TestProvider_GenerateReleaseWorkflow_Good(t *testing.T) {
|
||||
gin.SetMode(gin.TestMode)
|
||||
|
||||
projectDir := t.TempDir()
|
||||
p := NewProvider(projectDir, nil)
|
||||
|
||||
recorder := httptest.NewRecorder()
|
||||
request := httptest.NewRequest(http.MethodPost, "/release/workflow", bytes.NewBufferString(`{}`))
|
||||
request.Header.Set("Content-Type", "application/json")
|
||||
|
||||
ctx, _ := gin.CreateTestContext(recorder)
|
||||
ctx.Request = request
|
||||
|
||||
p.generateReleaseWorkflow(ctx)
|
||||
|
||||
assert.Equal(t, http.StatusOK, recorder.Code)
|
||||
|
||||
path := build.ReleaseWorkflowPath(projectDir)
|
||||
content, err := io.Local.Read(path)
|
||||
require.NoError(t, err)
|
||||
assert.Contains(t, content, "workflow_call:")
|
||||
assert.Contains(t, content, "workflow_dispatch:")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,6 +33,10 @@ func WriteReleaseWorkflow(fs io_interface.Medium, path string) error {
|
|||
return coreerr.E("build.WriteReleaseWorkflow", "failed to read embedded workflow template", err)
|
||||
}
|
||||
|
||||
if err := fs.EnsureDir(ax.Dir(path)); err != nil {
|
||||
return coreerr.E("build.WriteReleaseWorkflow", "failed to create release workflow directory", err)
|
||||
}
|
||||
|
||||
if err := fs.Write(path, string(content)); err != nil {
|
||||
return coreerr.E("build.WriteReleaseWorkflow", "failed to write release workflow", err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package build
|
|||
import (
|
||||
"testing"
|
||||
|
||||
"dappco.re/go/core/build/internal/ax"
|
||||
"dappco.re/go/core/io"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
|
@ -37,6 +38,22 @@ func TestWorkflow_WriteReleaseWorkflow_Good(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
assert.NotEmpty(t, content)
|
||||
})
|
||||
|
||||
t.Run("creates parent directories on a real filesystem", func(t *testing.T) {
|
||||
projectDir := t.TempDir()
|
||||
path := ax.Join(projectDir, ".github", "workflows", "release.yml")
|
||||
|
||||
err := WriteReleaseWorkflow(io.Local, path)
|
||||
require.NoError(t, err)
|
||||
|
||||
content, err := io.Local.Read(path)
|
||||
require.NoError(t, err)
|
||||
|
||||
template, err := releaseWorkflowTemplate.ReadFile("templates/release.yml")
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(t, string(template), content)
|
||||
})
|
||||
}
|
||||
|
||||
func TestWorkflow_ReleaseWorkflowPath_Good(t *testing.T) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue