Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
15 changes: 15 additions & 0 deletions .changeset/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"$schema": "https://unpkg.com/@changesets/config@3.1.1/schema.json",
"changelog": ["@changesets/changelog-github", { "repo": "smartcontractkit/cre-cli" }],
"commit": false,
"fixed": [],
"linked": [],
"access": "restricted",
"baseBranch": "main",
"updateInternalDependencies": "patch",
"ignore": [],
"privatePackages": {
"version": true,
"tag": true
}
}
23 changes: 23 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
name: Release

on:
push:
branches:
- main

jobs:
release:
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read
steps:
- name: release
uses: smartcontractkit/.github/actions/cicd-changesets@cicd-changesets/v1
with:
git-user: app-token-issuer-dev-services[bot]
git-email: app-token-issuer-dev-services[bot]@users.noreply.github.com
aws-region: ${{ secrets.AWS_REGION }}
aws-role-arn: ${{ secrets.AWS_OIDC_CRE_CLI_CI_RELEASE_TOKEN_ISSUER_ROLE_ARN }}
aws-lambda-url: ${{ secrets.AWS_DEV_SERVICES_TOKEN_ISSUER_LAMBDA_URL }}
changesets-create-gh-release: "false"
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

# Dependency directories (remove the comment below to include it)
# vendor/
node_modules/

# Build outputs
bin
Expand Down
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# cre-cli

## 1.8.2

### Patch Changes

- [#332](https://github.com/smartcontractkit/cre-cli/pull/332) [`31c1ab8`](https://github.com/smartcontractkit/cre-cli/commit/31c1ab8a500fa8ad1518ea610628302ba5ee76f2) Thanks [@timothyF95](https://github.com/timothyF95)! - Submit oauth secrets to vault DON

## 1.8.1

### Patch Changes

- [#333](https://github.com/smartcontractkit/cre-cli/pull/333) [`e6c2be1`](https://github.com/smartcontractkit/cre-cli/commit/e6c2be1c8ec1dfb635698b6731bbf11ca7c9ee67) Thanks [@timothyF95](https://github.com/timothyF95)! - Changeset test PR
47 changes: 27 additions & 20 deletions RELEASE_GUIDE.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,27 @@
# How to create a new release
Let's assume we want to create a release for version `v0.1.0`.

Steps:
1. Create a new branch from `main` with the name `releases/v0.1.x`
2. Create a tag on the release branch `git tag -a v0.1.0 -m "Release v0.1.0" -s`
3. Push the tag to the remote `git push origin v0.1.0`
4. Wait for `build-and-release` pipeline to run.
- Once pipeline is successful, the release will be created as a Draft
- Verify all is good and publish release as needed (set as latest if that is the case)

# How to fix a bug in an existing release
Let's assume we want to fix a bug in the release `v0.1.0`.

Steps:
1. Create a new branch from `releases/v0.1.x`.
2. Fix the bug.
3. Create a PR against the branch `releases/v0.1.x`.
4. Go through the review process and merge the PR.
5. Create a release with a tag `v0.1.1` from the branch `releases/v0.1.x`.
# Release Process

This project uses [Changesets](https://github.com/changesets/changesets) for versioning and release management.

## Adding a changeset

When your PR includes changes that warrant a version bump, run:

```bash
pnpm changeset
```

Select the bump type (major, minor, or patch) and provide a summary. This creates a `.changeset/*.md` file that should be committed with your PR.

## How releases happen

1. PRs with changeset files are merged to `main`.
2. The `release.yml` workflow detects pending changesets and opens (or updates) a **"Version Packages"** PR. This PR bumps `package.json`, updates `CHANGELOG.md`, and consumes the changeset files.
3. When the Version Packages PR is merged, the workflow creates a `v*` tag.
4. The tag triggers `build-and-release.yml`, which builds and signs binaries across all platforms and creates a draft GitHub Release.
5. Review the draft release and publish it.

## Hotfixing an existing release

1. Create a branch from the relevant release tag (e.g. `git checkout -b hotfix/v1.3.1 v1.3.0`).
2. Fix the bug and add a changeset (`pnpm changeset` -- typically a `patch`).
3. Follow the standard PR and merge process against `main`.
49 changes: 38 additions & 11 deletions cmd/common/compile.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,45 @@ const makefileName = "Makefile"

var defaultWasmOutput = filepath.Join("wasm", "workflow.wasm")

const (
// SkipTypeChecksFlag is passed through to cre-compile for TypeScript workflows (matches @chainlink/cre-sdk).
SkipTypeChecksFlag = "--skip-type-checks"
// SkipTypeChecksCLIFlag is the Cobra/Viper flag name (no leading dashes).
SkipTypeChecksCLIFlag = "skip-type-checks"
)

// WorkflowCompileOptions configures workflow compilation for CompileWorkflowToWasm.
type WorkflowCompileOptions struct {
// StripSymbols, when true, strips debug symbols from Go WASM builds (smaller binary for deploy).
StripSymbols bool
// SkipTypeChecks, when true, passes SkipTypeChecksFlag to cre-compile for TypeScript workflows.
SkipTypeChecks bool
}

// getBuildCmd returns a single step that builds the workflow and returns the WASM bytes.
// If stripSymbols is true, debug symbols are stripped from the binary to reduce size.
func getBuildCmd(workflowRootFolder, mainFile, language string, stripSymbols bool) (func() ([]byte, error), error) {
func getBuildCmd(workflowRootFolder, mainFile, language string, opts WorkflowCompileOptions) (func() ([]byte, error), error) {
tmpPath := filepath.Join(workflowRootFolder, ".cre_build_tmp.wasm")
switch language {
case constants.WorkflowLanguageTypeScript:
cmd := exec.Command("bun", "cre-compile", mainFile, tmpPath)
args := []string{"cre-compile", mainFile, tmpPath}
if opts.SkipTypeChecks {
args = append(args, SkipTypeChecksFlag)
}
cmd := exec.Command("bun", args...)
cmd.Dir = workflowRootFolder
return func() ([]byte, error) {
out, err := cmd.CombinedOutput()
if err != nil {
return nil, fmt.Errorf("%w\nbuild output:\n%s", err, strings.TrimSpace(string(out)))
outStr := strings.TrimSpace(string(out))
if strings.Contains(outStr, "Script not found") && strings.Contains(outStr, "cre-compile") {
return nil, fmt.Errorf("TypeScript compilation failed: 'cre-compile' command not found.\n\n" +
"The 'cre-compile' tool is provided by the @chainlink/cre-sdk package.\n\n" +
"To fix:\n" +
" • Run 'bun install' in your project to install dependencies\n" +
" • Update your project dependencies with 'cre update <workflow-folder>'\n" +
" • If starting fresh, use 'cre workflow init' to scaffold a properly configured workflow")
}
return nil, fmt.Errorf("%w\nbuild output:\n%s", err, outStr)
}
b, err := os.ReadFile(tmpPath)
_ = os.Remove(tmpPath)
Expand All @@ -37,7 +64,7 @@ func getBuildCmd(workflowRootFolder, mainFile, language string, stripSymbols boo
case constants.WorkflowLanguageGolang:
// Build the package (.) so all .go files (main.go, workflow.go, etc.) are compiled together
ldflags := "-buildid="
if stripSymbols {
if opts.StripSymbols {
ldflags = "-buildid= -w -s"
}
cmd := exec.Command(
Expand Down Expand Up @@ -78,7 +105,7 @@ func getBuildCmd(workflowRootFolder, mainFile, language string, stripSymbols boo
default:
// Build the package (.) so all .go files are compiled together
ldflags := "-buildid="
if stripSymbols {
if opts.StripSymbols {
ldflags = "-buildid= -w -s"
}
cmd := exec.Command(
Expand All @@ -105,10 +132,10 @@ func getBuildCmd(workflowRootFolder, mainFile, language string, stripSymbols boo
}

// CompileWorkflowToWasm compiles the workflow at workflowPath and returns the WASM binary.
// If stripSymbols is true, debug symbols are stripped to reduce binary size (used for deploy).
// If false, debug symbols are kept for better error messages (used for simulate).
// For custom builds (WASM language with Makefile), stripSymbols has no effect.
func CompileWorkflowToWasm(workflowPath string, stripSymbols bool) ([]byte, error) {
// opts.StripSymbols: for Go builds, true strips debug symbols (deploy); false keeps them (simulate).
// opts.SkipTypeChecks: for TypeScript, passes SkipTypeChecksFlag to cre-compile.
// For custom Makefile WASM builds, StripSymbols and SkipTypeChecks have no effect.
func CompileWorkflowToWasm(workflowPath string, opts WorkflowCompileOptions) ([]byte, error) {
workflowRootFolder, workflowMainFile, err := WorkflowPathRootAndMain(workflowPath)
if err != nil {
return nil, fmt.Errorf("workflow path: %w", err)
Expand Down Expand Up @@ -140,7 +167,7 @@ func CompileWorkflowToWasm(workflowPath string, stripSymbols bool) ([]byte, erro
return nil, fmt.Errorf("unsupported workflow language for file %s", workflowMainFile)
}

buildStep, err := getBuildCmd(workflowRootFolder, workflowMainFile, language, stripSymbols)
buildStep, err := getBuildCmd(workflowRootFolder, workflowMainFile, language, opts)
if err != nil {
return nil, err
}
Expand Down
29 changes: 20 additions & 9 deletions cmd/common/compile_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,29 +47,29 @@ func TestFindMakefileRoot(t *testing.T) {
func TestCompileWorkflowToWasm_Go_Success(t *testing.T) {
t.Run("basic_workflow", func(t *testing.T) {
path := deployTestdataPath("basic_workflow", "main.go")
wasm, err := CompileWorkflowToWasm(path, true)
wasm, err := CompileWorkflowToWasm(path, WorkflowCompileOptions{StripSymbols: true})
require.NoError(t, err)
assert.NotEmpty(t, wasm)
})

t.Run("configless_workflow", func(t *testing.T) {
path := deployTestdataPath("configless_workflow", "main.go")
wasm, err := CompileWorkflowToWasm(path, true)
wasm, err := CompileWorkflowToWasm(path, WorkflowCompileOptions{StripSymbols: true})
require.NoError(t, err)
assert.NotEmpty(t, wasm)
})

t.Run("missing_go_mod", func(t *testing.T) {
path := deployTestdataPath("missing_go_mod", "main.go")
wasm, err := CompileWorkflowToWasm(path, true)
wasm, err := CompileWorkflowToWasm(path, WorkflowCompileOptions{StripSymbols: true})
require.NoError(t, err)
assert.NotEmpty(t, wasm)
})
}

func TestCompileWorkflowToWasm_Go_Malformed_Fails(t *testing.T) {
path := deployTestdataPath("malformed_workflow", "main.go")
_, err := CompileWorkflowToWasm(path, true)
_, err := CompileWorkflowToWasm(path, WorkflowCompileOptions{StripSymbols: true})
require.Error(t, err)
assert.Contains(t, err.Error(), "failed to compile workflow")
assert.Contains(t, err.Error(), "undefined: sdk.RemovedFunctionThatFailsCompilation")
Expand All @@ -80,7 +80,7 @@ func TestCompileWorkflowToWasm_Wasm_Success(t *testing.T) {
_ = os.Remove(wasmPath)
t.Cleanup(func() { _ = os.Remove(wasmPath) })

wasm, err := CompileWorkflowToWasm(wasmPath, true)
wasm, err := CompileWorkflowToWasm(wasmPath, WorkflowCompileOptions{StripSymbols: true})
require.NoError(t, err)
assert.NotEmpty(t, wasm)

Expand All @@ -96,14 +96,14 @@ func TestCompileWorkflowToWasm_Wasm_Fails(t *testing.T) {
wasmPath := filepath.Join(wasmDir, "workflow.wasm")
require.NoError(t, os.WriteFile(wasmPath, []byte("not really wasm"), 0600))

_, err := CompileWorkflowToWasm(wasmPath, true)
_, err := CompileWorkflowToWasm(wasmPath, WorkflowCompileOptions{StripSymbols: true})
require.Error(t, err)
assert.Contains(t, err.Error(), "no Makefile found")
})

t.Run("make_build_fails", func(t *testing.T) {
path := deployTestdataPath("wasm_make_fails", "wasm", "workflow.wasm")
_, err := CompileWorkflowToWasm(path, true)
_, err := CompileWorkflowToWasm(path, WorkflowCompileOptions{StripSymbols: true})
require.Error(t, err)
assert.Contains(t, err.Error(), "failed to compile workflow")
assert.Contains(t, err.Error(), "build output:")
Expand All @@ -118,7 +118,7 @@ func TestCompileWorkflowToWasm_TS_Success(t *testing.T) {
mainPath := filepath.Join(dir, "main.ts")
require.NoError(t, os.WriteFile(mainPath, []byte(`export async function main() { return "ok"; }
`), 0600))
require.NoError(t, os.WriteFile(filepath.Join(dir, "package.json"), []byte(`{"name":"test","dependencies":{"@chainlink/cre-sdk":"latest"}}
require.NoError(t, os.WriteFile(filepath.Join(dir, "package.json"), []byte(`{"name":"test","dependencies":{"@chainlink/cre-sdk":"^1.5.0"}}
`), 0600))
install := exec.Command("bun", "install")
install.Dir = dir
Expand All @@ -127,7 +127,18 @@ func TestCompileWorkflowToWasm_TS_Success(t *testing.T) {
if err := install.Run(); err != nil {
t.Skipf("bun install failed (network or cre-sdk): %v", err)
}
wasm, err := CompileWorkflowToWasm(mainPath, true)
require.NoError(t, os.WriteFile(filepath.Join(dir, "tsconfig.json"), []byte(`{
"compilerOptions": {
"target": "ES2022",
"module": "ESNext",
"moduleResolution": "bundler",
"skipLibCheck": true,
"types": []
},
"include": ["main.ts"]
}
`), 0600))
wasm, err := CompileWorkflowToWasm(mainPath, WorkflowCompileOptions{StripSymbols: true})
if err != nil {
t.Skipf("TS compile failed (published cre-sdk may lack full layout): %v", err)
}
Expand Down
Loading
Loading