Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions pkg/action/chart_ts_init.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@ import (
)

type ChartTSInitOptions struct {
ChartDirPath string
ChartName string
TempDirPath string
ChartDirPath string
ChartName string
RenderContextType string
TempDirPath string
}

func ChartTSInit(ctx context.Context, opts ChartTSInitOptions) error {
Expand Down Expand Up @@ -47,7 +48,9 @@ func ChartTSInit(ctx context.Context, opts ChartTSInitOptions) error {
return fmt.Errorf("init chart structure: %w", err)
}

if err := ts.InitTSBoilerplate(ctx, absPath, chartName); err != nil {
if err := ts.InitTSBoilerplate(ctx, absPath, chartName, ts.InitTSBoilerplateOptions{
RenderContextType: opts.RenderContextType,
}); err != nil {
return fmt.Errorf("init TypeScript boilerplate: %w", err)
}

Expand Down
2 changes: 2 additions & 0 deletions pkg/common/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,8 @@ const (
StageStartSuffix = "start"
StubReleaseName = "stub-release"
StubReleaseNamespace = "stub-namespace"
// WerfRenderContextType is the TypeScript render context type name for werf charts.
WerfRenderContextType = "WerfRenderContext"
)

var (
Expand Down
25 changes: 18 additions & 7 deletions pkg/ts/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,14 @@ import (
"github.com/werf/nelm/pkg/log"
)

const denoBuildScript = "deno bundle --output=dist/bundle.js src/index.ts"
const (
defaultRenderContextType = "RenderContext"
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move it where WerfRenderContextType is defined and name it something like TSGenericRenderContextType and TSWerfRenderContextType. Then add a TSDefaultRenderContextType = TSGenericRenderContextType

denoBuildScript = "deno bundle --output=dist/bundle.js src/index.ts"
)

type InitTSBoilerplateOptions struct {
RenderContextType string
}

// EnsureGitignore adds TypeScript entries to .gitignore, creating if needed.
func EnsureGitignore(chartPath string) error {
Expand Down Expand Up @@ -53,8 +60,7 @@ func InitChartStructure(ctx context.Context, chartPath, chartName string) error
return nil
}

// InitTSBoilerplate creates TypeScript boilerplate files in ts/ directory.
func InitTSBoilerplate(ctx context.Context, chartPath, chartName string) error {
func InitTSBoilerplate(ctx context.Context, chartPath, chartName string, opts InitTSBoilerplateOptions) error {
tsDir := filepath.Join(chartPath, common.ChartTSSourceDir)
srcDir := filepath.Join(tsDir, "src")

Expand All @@ -64,14 +70,19 @@ func InitTSBoilerplate(ctx context.Context, chartPath, chartName string) error {
return fmt.Errorf("stat %s: %w", tsDir, err)
}

ctxType := defaultRenderContextType
if opts.RenderContextType != "" {
ctxType = opts.RenderContextType
}

files := []struct {
content string
path string
}{
{content: indexTSContent, path: filepath.Join(srcDir, "index.ts")},
{content: helpersTSContent, path: filepath.Join(srcDir, "helpers.ts")},
{content: deploymentTSContent, path: filepath.Join(srcDir, "deployment.ts")},
{content: serviceTSContent, path: filepath.Join(srcDir, "service.ts")},
{content: strings.ReplaceAll(indexTSTmpl, renderContextTypePlaceholder, ctxType), path: filepath.Join(srcDir, "index.ts")},
{content: strings.ReplaceAll(helpersTSTmpl, renderContextTypePlaceholder, ctxType), path: filepath.Join(srcDir, "helpers.ts")},
{content: strings.ReplaceAll(deploymentTSTmpl, renderContextTypePlaceholder, ctxType), path: filepath.Join(srcDir, "deployment.ts")},
{content: strings.ReplaceAll(serviceTSTmpl, renderContextTypePlaceholder, ctxType), path: filepath.Join(srcDir, "service.ts")},
{content: tsconfigContent, path: filepath.Join(tsDir, "tsconfig.json")},
{content: fmt.Sprintf(denoJSONTmpl, denoBuildScript), path: filepath.Join(tsDir, "deno.json")},
{content: fmt.Sprintf(inputExampleContent, chartName), path: filepath.Join(tsDir, "input.example.yaml")},
Expand Down
25 changes: 13 additions & 12 deletions pkg/ts/init_templates.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ const (
"build": "%s"
},
"imports": {
"@nelm/chart-ts-sdk": "npm:@nelm/chart-ts-sdk@^0.1.3"
"@nelm/chart-ts-sdk": "npm:@nelm/chart-ts-sdk@^0.1.4"
}
}
`
deploymentTSContent = `import type { RenderContext } from '@nelm/chart-ts-sdk';
deploymentTSTmpl = `import type { {{RenderContextType}} } from '@nelm/chart-ts-sdk';
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

well, since we started templating it, then let's do it properly via go text/template engine. Just init a new blank engine and pass a context ($) into it with all you need. Will be easier to extend later. And the template will become this instead: {{ $.RenderContextType }}

import { getFullname, getLabels, getSelectorLabels } from './helpers.ts';

export function newDeployment($: RenderContext): object {
export function newDeployment($: {{RenderContextType}}): object {
const name = getFullname($);

return {
Expand Down Expand Up @@ -59,7 +59,7 @@ export function newDeployment($: RenderContext): object {
ts/vendor/
ts/node_modules/
`
helpersTSContent = `import type { RenderContext } from '@nelm/chart-ts-sdk';
helpersTSTmpl = `import type { {{RenderContextType}} } from '@nelm/chart-ts-sdk';

/**
* Truncate string to max length, removing trailing hyphens.
Expand All @@ -73,7 +73,7 @@ export function trunc(str: string, max: number): string {
* Get the fully qualified app name.
* Truncated at 63 chars (DNS naming spec limit).
*/
export function getFullname($: RenderContext): string {
export function getFullname($: {{RenderContextType}}): string {
if ($.Values.fullnameOverride) {
return trunc($.Values.fullnameOverride, 63);
}
Expand All @@ -87,25 +87,25 @@ export function getFullname($: RenderContext): string {
return trunc(` + "`${$.Release.Name}-${chartName}`" + `, 63);
}

export function getLabels($: RenderContext): Record<string, string> {
export function getLabels($: {{RenderContextType}}): Record<string, string> {
return {
'app.kubernetes.io/name': $.Chart.Name,
'app.kubernetes.io/instance': $.Release.Name,
};
}

export function getSelectorLabels($: RenderContext): Record<string, string> {
export function getSelectorLabels($: {{RenderContextType}}): Record<string, string> {
return {
'app.kubernetes.io/name': $.Chart.Name,
'app.kubernetes.io/instance': $.Release.Name,
};
}
`
indexTSContent = `import { RenderContext, RenderResult, runRender } from '@nelm/chart-ts-sdk';
indexTSTmpl = `import { {{RenderContextType}}, RenderResult, render } from '@nelm/chart-ts-sdk';
import { newDeployment } from './deployment.ts';
import { newService } from './service.ts';

function render($: RenderContext): RenderResult {
function generate($: {{RenderContextType}}): RenderResult {
const manifests: object[] = [];

manifests.push(newDeployment($));
Expand All @@ -117,7 +117,7 @@ function render($: RenderContext): RenderResult {
return { manifests };
}

await runRender(render);
await render(generate);
`
inputExampleContent = `Capabilities:
APIVersions:
Expand Down Expand Up @@ -169,10 +169,11 @@ Values:
port: 80
type: ClusterIP
`
serviceTSContent = `import type { RenderContext } from '@nelm/chart-ts-sdk';
renderContextTypePlaceholder = "{{RenderContextType}}"
serviceTSTmpl = `import type { {{RenderContextType}} } from '@nelm/chart-ts-sdk';
import { getFullname, getLabels, getSelectorLabels } from './helpers.ts';

export function newService($: RenderContext): object {
export function newService($: {{RenderContextType}}): object {
return {
apiVersion: 'v1',
kind: 'Service',
Expand Down
46 changes: 31 additions & 15 deletions pkg/ts/init_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -176,16 +176,14 @@ func TestInitTSBoilerplate(t *testing.T) {
chartPath := filepath.Join(t.TempDir(), "test-chart")
require.NoError(t, os.MkdirAll(chartPath, 0o755))

err := ts.InitTSBoilerplate(context.Background(), chartPath, "test-chart")
err := ts.InitTSBoilerplate(context.Background(), chartPath, "test-chart", ts.InitTSBoilerplateOptions{})
require.NoError(t, err)

// Check ts/src/ files
assert.FileExists(t, filepath.Join(chartPath, "ts", "src", "index.ts"))
assert.FileExists(t, filepath.Join(chartPath, "ts", "src", "helpers.ts"))
assert.FileExists(t, filepath.Join(chartPath, "ts", "src", "deployment.ts"))
assert.FileExists(t, filepath.Join(chartPath, "ts", "src", "service.ts"))

// Check ts/ root files
assert.FileExists(t, filepath.Join(chartPath, "ts", "tsconfig.json"))
assert.FileExists(t, filepath.Join(chartPath, "ts", "deno.json"))
assert.FileExists(t, filepath.Join(chartPath, "ts", "input.example.yaml"))
Expand All @@ -195,7 +193,7 @@ func TestInitTSBoilerplate(t *testing.T) {
chartPath := filepath.Join(t.TempDir(), "test-chart")
require.NoError(t, os.MkdirAll(chartPath, 0o755))

err := ts.InitTSBoilerplate(context.Background(), chartPath, "test-chart")
err := ts.InitTSBoilerplate(context.Background(), chartPath, "test-chart", ts.InitTSBoilerplateOptions{})
require.NoError(t, err)

assert.DirExists(t, filepath.Join(chartPath, "ts"))
Expand All @@ -206,7 +204,7 @@ func TestInitTSBoilerplate(t *testing.T) {
chartPath := filepath.Join(t.TempDir(), "my-custom-chart")
require.NoError(t, os.MkdirAll(chartPath, 0o755))

err := ts.InitTSBoilerplate(context.Background(), chartPath, "my-custom-chart")
err := ts.InitTSBoilerplate(context.Background(), chartPath, "my-custom-chart", ts.InitTSBoilerplateOptions{})
require.NoError(t, err)

content, err := os.ReadFile(filepath.Join(chartPath, "ts", "deno.json"))
Expand All @@ -215,26 +213,44 @@ func TestInitTSBoilerplate(t *testing.T) {
assert.Contains(t, string(content), `"@nelm/chart-ts-sdk"`)
})

t.Run("includes render function in index.ts", func(t *testing.T) {
t.Run("uses RenderContext by default", func(t *testing.T) {
chartPath := filepath.Join(t.TempDir(), "test-chart")
require.NoError(t, os.MkdirAll(chartPath, 0o755))

err := ts.InitTSBoilerplate(context.Background(), chartPath, "test-chart")
err := ts.InitTSBoilerplate(context.Background(), chartPath, "test-chart", ts.InitTSBoilerplateOptions{})
require.NoError(t, err)

content, err := os.ReadFile(filepath.Join(chartPath, "ts", "src", "index.ts"))
require.NoError(t, err)
assert.Contains(t, string(content), "function render")
assert.Contains(t, string(content), "function generate")
assert.Contains(t, string(content), "RenderContext")
assert.Contains(t, string(content), "RenderResult")
assert.Contains(t, string(content), "runRender")
assert.Contains(t, string(content), "await render(generate)")
assert.NotContains(t, string(content), "WerfRenderContext")
})

t.Run("uses custom render context type when specified", func(t *testing.T) {
chartPath := filepath.Join(t.TempDir(), "test-chart")
require.NoError(t, os.MkdirAll(chartPath, 0o755))

err := ts.InitTSBoilerplate(context.Background(), chartPath, "test-chart", ts.InitTSBoilerplateOptions{
RenderContextType: "WerfRenderContext",
})
require.NoError(t, err)

for _, file := range []string{"index.ts", "helpers.ts", "deployment.ts", "service.ts"} {
content, err := os.ReadFile(filepath.Join(chartPath, "ts", "src", file))
require.NoError(t, err)
assert.Contains(t, string(content), "WerfRenderContext", "file %s should use WerfRenderContext", file)
assert.NotContains(t, string(content), "import type { RenderContext }", "file %s should not import RenderContext", file)
}
})

t.Run("includes helper functions in helpers.ts", func(t *testing.T) {
chartPath := filepath.Join(t.TempDir(), "test-chart")
require.NoError(t, os.MkdirAll(chartPath, 0o755))

err := ts.InitTSBoilerplate(context.Background(), chartPath, "test-chart")
err := ts.InitTSBoilerplate(context.Background(), chartPath, "test-chart", ts.InitTSBoilerplateOptions{})
require.NoError(t, err)

content, err := os.ReadFile(filepath.Join(chartPath, "ts", "src", "helpers.ts"))
Expand All @@ -248,7 +264,7 @@ func TestInitTSBoilerplate(t *testing.T) {
chartPath := filepath.Join(t.TempDir(), "test-chart")
require.NoError(t, os.MkdirAll(chartPath, 0o755))

err := ts.InitTSBoilerplate(context.Background(), chartPath, "test-chart")
err := ts.InitTSBoilerplate(context.Background(), chartPath, "test-chart", ts.InitTSBoilerplateOptions{})
require.NoError(t, err)

deploymentContent, err := os.ReadFile(filepath.Join(chartPath, "ts", "src", "deployment.ts"))
Expand All @@ -264,7 +280,7 @@ func TestInitTSBoilerplate(t *testing.T) {
chartPath := filepath.Join(t.TempDir(), "test-chart")
require.NoError(t, os.MkdirAll(chartPath, 0o755))

err := ts.InitTSBoilerplate(context.Background(), chartPath, "test-chart")
err := ts.InitTSBoilerplate(context.Background(), chartPath, "test-chart", ts.InitTSBoilerplateOptions{})
require.NoError(t, err)

content, err := os.ReadFile(filepath.Join(chartPath, "ts", "deno.json"))
Expand All @@ -276,7 +292,7 @@ func TestInitTSBoilerplate(t *testing.T) {
chartPath := filepath.Join(t.TempDir(), "test-chart")
require.NoError(t, os.MkdirAll(chartPath, 0o755))

err := ts.InitTSBoilerplate(context.Background(), chartPath, "test-chart")
err := ts.InitTSBoilerplate(context.Background(), chartPath, "test-chart", ts.InitTSBoilerplateOptions{})
require.NoError(t, err)

content, err := os.ReadFile(filepath.Join(chartPath, "ts", "tsconfig.json"))
Expand All @@ -291,7 +307,7 @@ func TestInitTSBoilerplate(t *testing.T) {
chartPath := filepath.Join(t.TempDir(), "my-custom-chart")
require.NoError(t, os.MkdirAll(chartPath, 0o755))

err := ts.InitTSBoilerplate(context.Background(), chartPath, "my-custom-chart")
err := ts.InitTSBoilerplate(context.Background(), chartPath, "my-custom-chart", ts.InitTSBoilerplateOptions{})
require.NoError(t, err)

content, err := os.ReadFile(filepath.Join(chartPath, "ts", "input.example.yaml"))
Expand All @@ -307,7 +323,7 @@ func TestInitTSBoilerplate(t *testing.T) {
tsDir := filepath.Join(chartPath, "ts")
require.NoError(t, os.MkdirAll(tsDir, 0o755))

err := ts.InitTSBoilerplate(context.Background(), chartPath, "test-chart")
err := ts.InitTSBoilerplate(context.Background(), chartPath, "test-chart", ts.InitTSBoilerplateOptions{})
require.Error(t, err)
assert.Contains(t, err.Error(), "typescript directory already exists")
})
Expand Down
Loading