diff --git a/.github/workflows/build-release.yml b/.github/workflows/build-release.yml
index 614a4d3..8d73fac 100644
--- a/.github/workflows/build-release.yml
+++ b/.github/workflows/build-release.yml
@@ -11,6 +11,11 @@ on:
- 'main'
paths:
- '.github/workflows/build-release.yml'
+ - 'cmd/**'
+ - 'pkg/**'
+ - 'internal/**'
+ - 'go.mod'
+ - 'go.sum'
- 'templates/**'
- 'tests/**'
- 'manifest.yaml'
@@ -56,6 +61,9 @@ jobs:
with:
persist-credentials: false
token: ${{ steps.generate_token.outputs.token }}
+ # These two required for builds to successfully amend commits
+ ref: ${{ github.head_ref }}
+ fetch-depth: 2
- name: Install Tool Versions
uses: jdx/mise-action@052520c41a328779551db19a76697ffa34f3eabc
with:
@@ -74,6 +82,9 @@ jobs:
run: mise run buildtest
env:
GITHUB_TOKEN: ${{ steps.generate_token.outputs.token }}
+ ## <>
+
+ ## <>
- name: Run Tests
run: mise run runtest
env:
@@ -95,7 +106,13 @@ jobs:
- name: Checkout
uses: actions/checkout@v4
with:
+ fetch-depth: 0
+ fetch-tags: true
token: ${{ secrets.GITHUB_TOKEN }}
+ - name: Set git User
+ run: |
+ git config user.name github-actions
+ git config user.email github-actions@github.com
- name: Install Tool Versions
uses: jdx/mise-action@052520c41a328779551db19a76697ffa34f3eabc
with:
@@ -108,3 +125,7 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: npx semantic-release
+
+ ## <>
+
+ ## <>
diff --git a/.gitignore b/.gitignore
index e73eb47..c179996 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,6 +4,7 @@
*.dll
*.so
*.dylib
+__debug_bin*
# Editor files
*.swp
@@ -36,6 +37,9 @@ vendor
# macOS
.DS_Store
+# Currently a build artifact for native modules
+CHANGELOG.md
+
# Ignore literally everything under the tests directory (except the README) -- specifically include the dir and stencil.yaml file
# for each test case in the ignores block below
tests/*
diff --git a/.mise.toml b/.mise.toml
index 6041558..f0cc1dd 100644
--- a/.mise.toml
+++ b/.mise.toml
@@ -2,6 +2,8 @@
nodejs = "22"
yarn = "1.22.22"
+
+
[tasks.cleantest]
description = "Helper to clean the test directory"
dir = "tests"
diff --git a/.vscode/settings.json b/.vscode/settings.json
index cc06081..d059932 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -1,4 +1,10 @@
{
+ "go.lintTool": "golangci-lint",
+ "go.lintFlags": [
+ "--fast"
+ ],
+ "go.formatTool": "goimports",
+ "go.useLanguageServer": true,
"files.trimTrailingWhitespace": true,
"files.exclude": {
"**/bin": true,
diff --git a/README.md b/README.md
index 6a619e8..0197f11 100644
--- a/README.md
+++ b/README.md
@@ -10,4 +10,5 @@ In the `arguments` section of the `manifest.yaml` file, you can specify the foll
| -------------------- | --------------- | -------------------------------------------------------------- |
| `description` | Required | Friendly-but-short description string for the frontend app |
| `owner` | Required | Pod or Portfolio ID for the owner of the frontend app |
+| `nativeModule` | `false` | Does this template module include native module golang code |
| `buildAndTestRunner` | `ubuntu-latest` | The github actions runner to use for the build and test CI job |
diff --git a/manifest.yaml b/manifest.yaml
index d359ad8..b656a10 100644
--- a/manifest.yaml
+++ b/manifest.yaml
@@ -20,11 +20,19 @@ arguments:
schema:
type: string
## <>
+ nativeModule:
+ required: false
+ description: Does this template module include native module golang code
+ schema:
+ type: boolean
buildAndTestRunner:
required: false
description: The github actions runner to use for the build and test CI job
schema:
type: string
+ packageJsonDeps:
+ required: false
+ description: The package.json dependencies to add to the generated package.json
## <>
modules:
- name: github.com/udemy/eng-team-management
diff --git a/stencil.lock b/stencil.lock
index 6e11896..89c2007 100644
--- a/stencil.lock
+++ b/stencil.lock
@@ -1,10 +1,10 @@
-version: 0.10.0
+version: 0.10.2
modules:
- name: github.com/udemy/eng-team-management
url: https://github.com/udemy/eng-team-management
version:
- commit: 4d5cf0c23526a24ccc553310dba01b1fbddc0911
- tag: v0.1.8
+ commit: 8eacc46158f50de1a13f754b4e5634749de3252c
+ tag: v0.2.5
- name: github.com/udemy/stencil-templatemodule
url: ./
version:
diff --git a/templates/.github/workflows/build-release.yml.tpl b/templates/.github/workflows/build-release.yml.tpl
index 42213f0..8473987 100644
--- a/templates/.github/workflows/build-release.yml.tpl
+++ b/templates/.github/workflows/build-release.yml.tpl
@@ -11,10 +11,17 @@ on:
- 'main'
paths:
- '.github/workflows/build-release.yml'
+ - 'cmd/**'
+ - 'pkg/**'
+ - 'internal/**'
+ - 'go.mod'
+ - 'go.sum'
- 'templates/**'
- 'tests/**'
- 'manifest.yaml'
- 'stencil.yaml'
+ - '.goreleaser.yaml'
+ - '.mise.toml'
env:
GH_ROLE_ARN: arn:aws:iam::602046956384:role/GithubActions-github-actions-services-repos-Role
@@ -56,6 +63,9 @@ jobs:
with:
persist-credentials: false
token: {{ "${{ steps.generate_token.outputs.token }}" }}
+ # These two required for builds to successfully amend commits
+ ref: {{ "${{ github.head_ref }}" }}
+ fetch-depth: 2
- name: Install Tool Versions
uses: jdx/mise-action@052520c41a328779551db19a76697ffa34f3eabc
with:
@@ -67,6 +77,36 @@ jobs:
with:
github-token: {{ "${{ github.token }}" }}
version: 'latest'
+{{- if stencil.Arg "nativeModule" }}
+ - name: Get Go directories
+ id: go
+ run: |
+ echo "cache_dir=$(go env GOCACHE)" >> "$GITHUB_OUTPUT"
+ echo "mod_cache_dir=$(go env GOMODCACHE)" >> "$GITHUB_OUTPUT"
+ - uses: actions/cache@v4
+ with:
+ path: {{ "${{ steps.go.outputs.cache_dir }}" }}
+ key: {{ "${{ github.workflow }}-${{ runner.os }}-go-build-cache-${{ hashFiles('**/go.sum') }}" }}
+ - uses: actions/cache@v4
+ with:
+ path: {{ "${{ steps.go.outputs.mod_cache_dir }}" }}
+ key: {{ "${{ github.workflow }}-${{ runner.os }}-go-mod-cache-${{ hashFiles('go.sum') }}" }}
+ - name: Lint
+ uses: golangci/golangci-lint-action@v4
+ with:
+ version: latest
+ # We already use setup-go's pkg cache and actions/cache's build cache, so don't double-up
+ skip-pkg-cache: true
+ skip-build-cache: true
+ args: --timeout=6m
+ - name: Build Go binary
+ run: mise run build
+ - name: Run Go Tests
+ run: go run gotest.tools/gotestsum@v1.11.0
+ ## <>
+{{ file.Block "gotestvars" }}
+ ## <>
+{{- end }}
## <>
{{ file.Block "buildtestauth" }}
## <>
@@ -74,6 +114,9 @@ jobs:
run: mise run buildtest
env:
GITHUB_TOKEN: {{ "${{ steps.generate_token.outputs.token }}" }}
+ ## <>
+{{ file.Block "buildTestEnvVars" }}
+ ## <>
- name: Run Tests
run: mise run runtest
env:
@@ -95,16 +138,70 @@ jobs:
- name: Checkout
uses: actions/checkout@v4
with:
+ fetch-depth: 0
+ fetch-tags: true
token: {{ "${{ secrets.GITHUB_TOKEN }}" }}
+ - name: Set git User
+ run: |
+ git config user.name github-actions
+ git config user.email github-actions@github.com
- name: Install Tool Versions
uses: jdx/mise-action@052520c41a328779551db19a76697ffa34f3eabc
with:
experimental: true
env:
GH_TOKEN: {{ "${{ secrets.GITHUB_TOKEN }}" }}
+{{- if stencil.Arg "nativeModule" }}
+ - name: Get Go directories
+ id: go
+ run: |
+ echo "cache_dir=$(go env GOCACHE)" >> "$GITHUB_OUTPUT"
+ echo "mod_cache_dir=$(go env GOMODCACHE)" >> "$GITHUB_OUTPUT"
+ - uses: actions/cache@v4
+ with:
+ path: {{ "${{ steps.go.outputs.cache_dir }}" }}
+ key: {{ "${{ github.workflow }}-${{ runner.os }}-go-build-cache-${{ hashFiles('**/go.sum') }}" }}
+ - uses: actions/cache@v4
+ with:
+ path: {{ "${{ steps.go.outputs.mod_cache_dir }}" }}
+ key: {{ "${{ github.workflow }}-${{ runner.os }}-go-mod-cache-${{ hashFiles('go.sum') }}" }}
+ - name: Retrieve goreleaser version
+ run: |-
+ echo "version=$(mise current goreleaser)" >> "$GITHUB_OUTPUT"
+ id: goreleaser
+ - name: Get next version
+ id: next_version
+ run: |-
+ get-next-version --target github-action
+ - name: Create Tag
+ if: {{ "${{ steps.next_version.outputs.hasNextVersion == 'true' }}" }}
+ run: |-
+ git tag -a {{ "\"v${{ steps.next_version.outputs.version }}\" -m \"Release v${{ steps.next_version.outputs.version }}\"" }}
+ - name: Generate CHANGELOG
+ if: {{ "${{ steps.next_version.outputs.hasNextVersion == 'true' }}" }}
+ run: |-
+ mise run changelog
+ - name: Create release artifacts and Github Release
+ if: {{ "${{ steps.next_version.outputs.hasNextVersion == 'true' }}" }}
+ uses: goreleaser/goreleaser-action@v6
+ with:
+ distribution: goreleaser
+ version: {{ "v${{ steps.goreleaser.outputs.version }}" }}
+ args: release --release-notes CHANGELOG.md --clean
+ env:
+ GITHUB_TOKEN: {{ "${{ secrets.GITHUB_TOKEN }}" }}
+ ## <>
+{{ file.Block "goreleaserEnvVars" }}
+ ## <>
+{{- else }}
- name: Install Semantic-Release
run: yarn install
- name: Release
env:
GITHUB_TOKEN: {{ "${{ secrets.GITHUB_TOKEN }}" }}
run: npx semantic-release
+{{- end }}
+
+ ## <>
+{{ file.Block "extraActions" }}
+ ## <>
diff --git a/templates/.gitignore.tpl b/templates/.gitignore.tpl
index 5b8429e..8432740 100644
--- a/templates/.gitignore.tpl
+++ b/templates/.gitignore.tpl
@@ -4,6 +4,7 @@
*.dll
*.so
*.dylib
+__debug_bin*
# Editor files
*.swp
@@ -36,6 +37,9 @@ vendor
# macOS
.DS_Store
+# Currently a build artifact for native modules
+CHANGELOG.md
+
# Ignore literally everything under the tests directory (except the README) -- specifically include the dir and stencil.yaml file
# for each test case in the ignores block below
tests/*
diff --git a/templates/.golangci.yml.tpl b/templates/.golangci.yml.tpl
new file mode 100644
index 0000000..51def48
--- /dev/null
+++ b/templates/.golangci.yml.tpl
@@ -0,0 +1,114 @@
+{{- if not (stencil.Arg "nativeModule") -}}
+{{- file.Delete -}}
+{{- end -}}
+# yaml-language-server: $schema=https://json.schemastore.org/golangci-lint
+# Linter settings
+linters-settings:
+ depguard:
+ rules:
+ main:
+ deny:
+ - pkg: github.com/go-logr/logr
+ desc: Use the pkg/log logging package
+ - pkg: github.com/sirupsen/logrus
+ desc: Use the pkg/log logging package
+ - pkg: log
+ desc: Use the pkg/log logging package
+ errcheck:
+ check-blank: true
+ govet:
+ enable-all: true
+ disable:
+ - fieldalignment
+ settings:
+ shadow:
+ strict: true
+ gocyclo:
+ min-complexity: 25
+ dupl:
+ threshold: 100
+ goconst:
+ min-len: 3
+ min-occurrences: 3
+ lll:
+ line-length: 140
+ gocritic:
+ enabled-tags:
+ - diagnostic
+ - experimental
+ - opinionated
+ - performance
+ - style
+ disabled-checks:
+ - whyNoLint # Doesn't seem to work properly
+ funlen:
+ lines: 500
+ statements: 50
+
+linters:
+ # Inverted configuration with enable-all and disable is not scalable during updates of golangci-lint.
+ disable-all: true
+ enable:
+ - bodyclose
+ - copyloopvar
+ - depguard
+ - dogsled
+ - errcheck
+ - errorlint
+ - exhaustive # Checks exhaustiveness of enum switch statements.
+ - funlen
+ - gochecknoinits
+ - goconst
+ - gocritic
+ - gocyclo
+ - gofmt
+ - goimports
+ - revive
+ - gosec
+ - gosimple
+ - govet
+ - ineffassign
+ - lll
+ # - misspell # The reason we're disabling this right now is because it uses 1/2 of the memory of the run.
+ - nakedret
+ - staticcheck
+ - typecheck
+ - unconvert
+ - unparam
+ - unused
+ - whitespace
+
+issues:
+ exclude:
+ # We allow error shadowing
+ - 'declaration of "err" shadows declaration at'
+ - "var-naming: don't use an underscore in package name"
+
+ # Excluding configuration per-path, per-linter, per-text and per-source
+ exclude-rules:
+ # Exclude some linters from running on tests files.
+ - path: _test\.go
+ linters:
+ - gocyclo
+ - errcheck
+ - gosec
+ - funlen
+ - gochecknoglobals # Globals in test files are tolerated.
+ - goconst # Repeated consts in test files are tolerated.
+ # This rule is buggy and breaks on our `///Block` lines. Disable for now.
+ - linters:
+ - gocritic
+ text: "commentFormatting: put a space"
+ # This rule incorrectly flags nil references after assert.Assert(t, x != nil)
+ - path: _test\.go
+ text: "SA5011"
+ linters:
+ - staticcheck
+ - linters:
+ - lll
+ source: "^//go:generate "
+
+output:
+ formats:
+ - format: colored-line-number
+ sort-results: true
diff --git a/templates/.goreleaser.yaml.tpl b/templates/.goreleaser.yaml.tpl
new file mode 100644
index 0000000..48393d7
--- /dev/null
+++ b/templates/.goreleaser.yaml.tpl
@@ -0,0 +1,48 @@
+{{- if not (stencil.Arg "nativeModule") -}}
+{{- file.Delete -}}
+{{- end -}}
+# yaml-language-server: $schema=https://goreleaser.com/static/schema.json
+version: 2
+project_name: {{ .Config.Name }}
+report_sizes: true
+metadata:
+ mod_timestamp: "{{ "{{ .CommitTimestamp }}" }}"
+builds:
+ - main: ./cmd/plugin
+ flags:
+ - -trimpath
+ ldflags:
+ - -s
+ - -w
+ ## <>
+{{ file.Block "pluginLdflags" }}
+ ## <>
+ env:
+ - CGO_ENABLED=0
+ goarch:
+ - amd64
+ - arm64
+ ## <>
+{{ file.Block "pluginExtraArch" }}
+ ## <>
+ goos:
+ - linux
+ - darwin
+ - windows
+ ## <>
+{{ file.Block "pluginExtraOS" }}
+ ## <>
+ ignore:
+ - goos: windows
+ goarch: arm
+ mod_timestamp: "{{ "{{ .CommitTimestamp }}" }}"
+checksum:
+ name_template: "checksums.txt"
+snapshot:
+ name_template: "{{ "{{ incpatch .Version }}-next" }}"
+changelog:
+ use: git
+release:
+ prerelease: "auto"
+ footer: |-
+ {{ "**Full Changelog**: https://github.com/udemy/eng-team-management/compare/{{ .PreviousTag }}...{{ .Tag }}" }}
diff --git a/templates/.mise.toml.tpl b/templates/.mise.toml.tpl
index b8e9827..64fe59b 100644
--- a/templates/.mise.toml.tpl
+++ b/templates/.mise.toml.tpl
@@ -1,6 +1,45 @@
[tools]
nodejs = "22"
yarn = "1.22.22"
+{{- if stencil.Arg "nativeModule" }}
+git-cliff = "latest"
+golang = "1.23"
+golangci-lint = "1.60"
+goreleaser = "latest"
+"go:gotest.tools/gotestsum" = "v1.12.0"
+"go:golang.org/x/tools/cmd/goimports" = "latest"
+"go:github.com/thenativeweb/get-next-version" = "latest"
+{{- end }}
+
+{{ if stencil.Arg "nativeModule" -}}
+[tasks.build]
+description = "Build a binary for the current platform/architecture"
+run = "go build -trimpath -o ./bin/ -v ./cmd/..."
+
+[tasks.changelog]
+description = "Generate a changelog for the current version"
+outputs = ["CHANGELOG.md"]
+run = ["git-cliff --latest --output CHANGELOG.md"]
+
+[tasks.fmt]
+alias = "format"
+description = "Format code"
+run = ["go mod tidy", "gofmt -s -w .", "goimports -w ."]
+
+[tasks.lint]
+description = "Run linters"
+run = "golangci-lint run"
+
+[tasks.next-version]
+description = """Get the version number that would be released if a release was ran right now.
+Pass --rc to get the next release candidate version.
+"""
+run = ["./.github/scripts/get-next-version.sh"]
+
+[tasks.test]
+description = "Run tests"
+run = "gotestsum"
+{{- end }}
[tasks.cleantest]
description = "Helper to clean the test directory"
diff --git a/templates/.vscode/extensions.json.tpl b/templates/.vscode/extensions.json.tpl
index 08f27d7..f9733a1 100644
--- a/templates/.vscode/extensions.json.tpl
+++ b/templates/.vscode/extensions.json.tpl
@@ -6,6 +6,9 @@
"redhat.vscode-yaml",
"foxundermoon.shell-format",
"vsls-contrib.codetour",
+{{- if stencil.Arg "nativeModule" }}
+ "golang.go",
+{{- end }}
"tamasfe.even-better-toml"
]
}
diff --git a/templates/.vscode/settings.json.tpl b/templates/.vscode/settings.json.tpl
index cc06081..d059932 100644
--- a/templates/.vscode/settings.json.tpl
+++ b/templates/.vscode/settings.json.tpl
@@ -1,4 +1,10 @@
{
+ "go.lintTool": "golangci-lint",
+ "go.lintFlags": [
+ "--fast"
+ ],
+ "go.formatTool": "goimports",
+ "go.useLanguageServer": true,
"files.trimTrailingWhitespace": true,
"files.exclude": {
"**/bin": true,
diff --git a/templates/cmd/plugin/instance.go.tpl b/templates/cmd/plugin/instance.go.tpl
new file mode 100644
index 0000000..af22a77
--- /dev/null
+++ b/templates/cmd/plugin/instance.go.tpl
@@ -0,0 +1,67 @@
+{{- if not (stencil.Arg "nativeModule") -}}
+{{- file.Delete -}}
+{{- else -}}
+{{- file.Static -}}
+{{- end -}}
+package main
+
+import (
+ "context"
+ "encoding/json"
+ "fmt"
+ "io"
+ "os"
+ "os/exec"
+ "strings"
+
+ "github.com/pkg/errors"
+ "go.rgst.io/stencil/pkg/extensions/apiv1"
+)
+
+// _ ensures that Instance fits the apiv1.Implementation interface.
+var _ apiv1.Implementation = &Instance{}
+
+// Instance contains a [apiv1.Implementation] satisfying plugin.
+type Instance struct {
+ ctx context.Context
+}
+
+// NewInstance creates a new [Instance].
+func NewInstance(ctx context.Context) (*Instance, error) {
+ return &Instance{
+ ctx: ctx,
+ }, nil
+}
+
+// GetConfig returns a [apiv1.Config] for the [Instance].
+func (*Instance) GetConfig() (*apiv1.Config, error) {
+ return &apiv1.Config{}, nil
+}
+
+func (*Instance) GetTemplateFunctions() ([]*apiv1.TemplateFunction, error) {
+ return []*apiv1.TemplateFunction{
+ {
+ Name: "DoSomething",
+ NumberOfArguments: 1,
+ },
+ }, nil
+}
+
+func (i *Instance) ExecuteTemplateFunction(tfe *apiv1.TemplateFunctionExec) (any, error) {
+ switch tfe.Name { //nolint:gocritic
+ case "DoSomething":
+ return i.DoSomething(tfe)
+ }
+
+ return nil, fmt.Errorf("unknown template function: %s", tfe.Name)
+}
+
+// DoSomething does something, we promise
+func (i *Instance) DoSomething(t *apiv1.TemplateFunctionExec) (any, error) {
+ someArg, ok := t.Arguments[0].(string)
+ if !ok {
+ return nil, fmt.Errorf("expected string argument, got %T", t.Arguments[0])
+ }
+
+ return nil, nil
+}
diff --git a/templates/cmd/plugin/instance_test.go.tpl b/templates/cmd/plugin/instance_test.go.tpl
new file mode 100644
index 0000000..1e06fb4
--- /dev/null
+++ b/templates/cmd/plugin/instance_test.go.tpl
@@ -0,0 +1,33 @@
+{{- if not (stencil.Arg "nativeModule") -}}
+{{- file.Delete -}}
+{{- else -}}
+{{- file.Static -}}
+{{- end -}}
+package main
+
+import (
+ "context"
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+ "go.rgst.io/stencil/pkg/extensions/apiv1"
+)
+
+func TestGetTeam(t *testing.T) {
+ i, err := NewInstance(context.Background())
+ assert.NoError(t, err)
+
+ tiRaw, err := i.GetTeamByID(&apiv1.TemplateFunctionExec{Arguments: []any{"platform"}})
+ assert.NoError(t, err)
+ ti := tiRaw.(models.OwningTeam)
+
+ assert.Equal(t, "platform", *ti.ID)
+}
+
+func TestGetInvalidTeam(t *testing.T) {
+ i, err := NewInstance(context.Background())
+ assert.NoError(t, err)
+
+ _, err = i.GetTeamByID(&apiv1.TemplateFunctionExec{Arguments: []any{"sdfsdfsdfwesd"}})
+ assert.Error(t, err)
+}
diff --git a/templates/cmd/plugin/plugin.go.tpl b/templates/cmd/plugin/plugin.go.tpl
new file mode 100644
index 0000000..35bfa81
--- /dev/null
+++ b/templates/cmd/plugin/plugin.go.tpl
@@ -0,0 +1,29 @@
+{{- if not (stencil.Arg "nativeModule") -}}
+{{- file.Delete -}}
+{{- end -}}
+package main
+
+import (
+ "context"
+ "os"
+
+ "go.rgst.io/stencil/pkg/extensions/apiv1"
+ "go.rgst.io/stencil/pkg/slogext"
+)
+
+// main starts the native extension
+func main() {
+ ctx := context.Background()
+ log := slogext.New()
+
+ pi, err := NewInstance(ctx)
+ if err != nil {
+ log.WithError(err).Error("failed to create plugin instance")
+ os.Exit(1)
+ }
+
+ if err := apiv1.NewExtensionImplementation(pi, log); err != nil {
+ log.WithError(err).Error("failed to create extension")
+ os.Exit(1)
+ }
+}
diff --git a/templates/go.mod.tpl b/templates/go.mod.tpl
new file mode 100644
index 0000000..0fd481e
--- /dev/null
+++ b/templates/go.mod.tpl
@@ -0,0 +1,18 @@
+{{- if not (stencil.Arg "nativeModule") -}}
+{{- file.Delete -}}
+{{- end -}}
+module github.com/udemy/{{ .Config.Name }}
+
+go 1.23.1
+
+// <>
+{{- if empty (trim (file.Block "requires")) }}
+require (
+ github.com/pkg/errors v0.9.1
+ github.com/stretchr/testify v1.9.0
+ go.rgst.io/stencil v0.10.2
+)
+{{- else }}
+{{ file.Block "requires" }}
+{{- end }}
+// <>
diff --git a/templates/manifest.yaml.tpl b/templates/manifest.yaml.tpl
index d4b58d3..ece6005 100644
--- a/templates/manifest.yaml.tpl
+++ b/templates/manifest.yaml.tpl
@@ -1,4 +1,9 @@
name: github.com/udemy/{{ .Config.Name }}
+{{- if stencil.Arg "nativeModule" }}
+type: templates,extension
+{{- else }}
+type: templates
+{{- end }}
dirReplacements:
## <>
{{ file.Block "dirReplacements" }}
diff --git a/templates/package.json.tpl b/templates/package.json.tpl
index 65992e4..59f4b83 100644
--- a/templates/package.json.tpl
+++ b/templates/package.json.tpl
@@ -1,6 +1,9 @@
{
"name": "{{ .Config.Name }}",
"devDependencies": {
+{{- range $key, $value := (stencil.Arg "packageJsonDeps") }}
+ "{{ $key }}": "{{ $value }}",
+{{- end }}
"semantic-release": "23.0.8"
},
"dependencies": {