Skip to content

Commit

Permalink
Copy sdkbuild from temporalio/features
Browse files Browse the repository at this point in the history
  • Loading branch information
dandavison committed Feb 12, 2024
1 parent 5a43f3f commit 7c3dcf0
Show file tree
Hide file tree
Showing 10 changed files with 992 additions and 34 deletions.
2 changes: 1 addition & 1 deletion cmd/prepare_worker.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import (

"github.com/spf13/cobra"
"github.com/spf13/pflag"
"github.com/temporalio/features/sdkbuild"
"github.com/temporalio/omes/cmd/cmdoptions"
"github.com/temporalio/omes/sdkbuild"
"go.uber.org/zap"
)

Expand Down
2 changes: 1 addition & 1 deletion cmd/run_worker.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ import (

"github.com/spf13/cobra"
"github.com/spf13/pflag"
"github.com/temporalio/features/sdkbuild"
"github.com/temporalio/omes/cmd/cmdoptions"
"github.com/temporalio/omes/loadgen"
"github.com/temporalio/omes/sdkbuild"
"go.temporal.io/sdk/client"
"go.temporal.io/sdk/testsuite"
)
Expand Down
25 changes: 9 additions & 16 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,18 @@ go 1.20
require (
github.com/gogo/protobuf v1.3.2
github.com/golang/protobuf v1.5.3
github.com/otiai10/copy v1.14.0
github.com/prometheus/client_golang v1.16.0
github.com/spf13/cobra v1.7.0
github.com/spf13/pflag v1.0.5
github.com/stretchr/testify v1.8.4
github.com/temporalio/features v0.0.0-20231218231852-27c681667dae
go.temporal.io/api v1.26.1
go.temporal.io/sdk v1.25.2-0.20231129171107-288a04f72145
go.temporal.io/sdk v1.25.2-0.20240109200522-5ca9a4dfd4c3
go.uber.org/zap v1.25.0
golang.org/x/mod v0.12.0
golang.org/x/mod v0.14.0
golang.org/x/sync v0.5.0
golang.org/x/sys v0.15.0
google.golang.org/protobuf v1.31.0
google.golang.org/protobuf v1.32.0
)

require (
Expand All @@ -36,27 +36,20 @@ require (
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.1 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/otiai10/copy v1.14.0 // indirect
github.com/pborman/uuid v1.2.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/robfig/cron v1.2.0 // indirect
github.com/stretchr/objx v0.5.1 // indirect
go.uber.org/atomic v1.11.0 // indirect
go.uber.org/goleak v1.2.1 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/exp v0.0.0-20231127185646-65229373498e // indirect
golang.org/x/net v0.19.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/time v0.3.0 // indirect
google.golang.org/genproto v0.0.0-20231127180814-3a041ad873d4 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20231127180814-3a041ad873d4 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20231127180814-3a041ad873d4 // indirect
google.golang.org/grpc v1.59.0 // indirect
google.golang.org/genproto v0.0.0-20240102182953-50ed04b92917 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20240102182953-50ed04b92917 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240102182953-50ed04b92917 // indirect
google.golang.org/grpc v1.60.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

// This is dumb, but necesary because Go (for some commands) can't figure out the transitive
// local-replace inside of the features module itself, so we have to help it.
replace (
github.com/temporalio/features/features => github.com/temporalio/features/features v0.0.0-20231218231852-27c681667dae
github.com/temporalio/features/harness/go => github.com/temporalio/features/harness/go v0.0.0-20231218231852-27c681667dae
)
32 changes: 16 additions & 16 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -98,15 +98,13 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/temporalio/features v0.0.0-20231218231852-27c681667dae h1:d5LK3X10VZEWpLhZ5dIPcirvELKVtT4rEV+8wzfgBRM=
github.com/temporalio/features v0.0.0-20231218231852-27c681667dae/go.mod h1:Jm0Yq8DKEkSzcQ1YbZ5yeqrD6iyyWzQMcsXF0G1ylM4=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
go.temporal.io/api v1.26.1 h1:YqGQsOr/Tx4nVdA8wCv74AxesaIzCRHWb3KkHrYqI8k=
go.temporal.io/api v1.26.1/go.mod h1:Y/rALXTprFO+bvAlAfLFoJj7KpQIcL4GDQVN6fhYIa4=
go.temporal.io/sdk v1.25.2-0.20231129171107-288a04f72145 h1:aV7tRpzB3tr9LGs4/SN7MSWSbVx+bgDYfOoGMjk4oEM=
go.temporal.io/sdk v1.25.2-0.20231129171107-288a04f72145/go.mod h1:MHw8PEOVmOJC1yduTVxYq1GsM5kkQg0sIwRST7cRHoo=
go.temporal.io/sdk v1.25.2-0.20240109200522-5ca9a4dfd4c3 h1:XzkvOc0UATBM0SC2SO/GKaXq3JkJwe2rDeRhW2u11zM=
go.temporal.io/sdk v1.25.2-0.20240109200522-5ca9a4dfd4c3/go.mod h1:nRT6pheoo7UXrrgMh26r7t4IuJFZmu277SkaiVp/tZE=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
Expand All @@ -123,15 +121,17 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20231127185646-65229373498e h1:Gvh4YaCaXNs6dKTlfgismwWZKyjVZXwOPfIyUaqU3No=
golang.org/x/exp v0.0.0-20231127185646-65229373498e/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc=
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=
golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
Expand Down Expand Up @@ -190,23 +190,23 @@ google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20231127180814-3a041ad873d4 h1:W12Pwm4urIbRdGhMEg2NM9O3TWKjNcxQhs46V0ypf/k=
google.golang.org/genproto v0.0.0-20231127180814-3a041ad873d4/go.mod h1:5RBcpGRxr25RbDzY5w+dmaqpSEvl8Gwl1x2CICf60ic=
google.golang.org/genproto/googleapis/api v0.0.0-20231127180814-3a041ad873d4 h1:ZcOkrmX74HbKFYnpPY8Qsw93fC29TbJXspYKaBkSXDQ=
google.golang.org/genproto/googleapis/api v0.0.0-20231127180814-3a041ad873d4/go.mod h1:k2dtGpRrbsSyKcNPKKI5sstZkrNCZwpU/ns96JoHbGg=
google.golang.org/genproto/googleapis/rpc v0.0.0-20231127180814-3a041ad873d4 h1:DC7wcm+i+P1rN3Ff07vL+OndGg5OhNddHyTA+ocPqYE=
google.golang.org/genproto/googleapis/rpc v0.0.0-20231127180814-3a041ad873d4/go.mod h1:eJVxU6o+4G1PSczBr85xmyvSNYAKvAYgkub40YGomFM=
google.golang.org/genproto v0.0.0-20240102182953-50ed04b92917 h1:nz5NESFLZbJGPFxDT/HCn+V1mZ8JGNoY4nUpmW/Y2eg=
google.golang.org/genproto v0.0.0-20240102182953-50ed04b92917/go.mod h1:pZqR+glSb11aJ+JQcczCvgf47+duRuzNSKqE8YAQnV0=
google.golang.org/genproto/googleapis/api v0.0.0-20240102182953-50ed04b92917 h1:rcS6EyEaoCO52hQDupoSfrxI3R6C2Tq741is7X8OvnM=
google.golang.org/genproto/googleapis/api v0.0.0-20240102182953-50ed04b92917/go.mod h1:CmlNWB9lSezaYELKS5Ym1r44VrrbPUa7JTvw+6MbpJ0=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240102182953-50ed04b92917 h1:6G8oQ016D88m1xAKljMlBOOGWDZkes4kMhgGFlf8WcQ=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240102182953-50ed04b92917/go.mod h1:xtjpI3tXFPP051KaWnhvxkiubL/6dJ18vLVf7q2pTOU=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk=
google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98=
google.golang.org/grpc v1.60.1 h1:26+wFr+cNqSGFcOXcabYC0lUVJVRa2Sb2ortSK7VrEU=
google.golang.org/grpc v1.60.1/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I=
google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
Expand Down
144 changes: 144 additions & 0 deletions sdkbuild/dotnet.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
package sdkbuild

import (
"context"
"fmt"
"html"
"os"
"os/exec"
"path/filepath"
"runtime"
"strings"
)

// BuildDotNetProgramOptions are options for BuildDotNetProgram.
type BuildDotNetProgramOptions struct {
// Directory that will have a temporary directory created underneath.
BaseDir string
// Required version. If it contains a slash, it is assumed to be a path to the
// base of the repo (and will have a src/Temporalio/Temporalio.csproj child).
// Otherwise it is a NuGet version.
Version string
// If present, this directory is expected to exist beneath base dir. Otherwise
// a temporary dir is created.
DirName string
// Required Program.cs content. If not set, no Program.cs is created (so it)
ProgramContents string
// Required csproj content. This should not contain a dependency on Temporalio
// because this adds a package/project reference near the end.
CsprojContents string
}

// DotNetProgram is a .NET-specific implementation of Program.
type DotNetProgram struct {
dir string
}

var _ Program = (*DotNetProgram)(nil)

func BuildDotNetProgram(ctx context.Context, options BuildDotNetProgramOptions) (*DotNetProgram, error) {
if options.BaseDir == "" {
return nil, fmt.Errorf("base dir required")
} else if options.Version == "" {
return nil, fmt.Errorf("version required")
} else if options.ProgramContents == "" {
return nil, fmt.Errorf("program contents required")
} else if options.CsprojContents == "" {
return nil, fmt.Errorf("csproj contents required")
}

// Create temp dir if needed that we will remove if creating is unsuccessful
success := false
var dir string
if options.DirName != "" {
dir = filepath.Join(options.BaseDir, options.DirName)
} else {
var err error
dir, err = os.MkdirTemp(options.BaseDir, "program-")
if err != nil {
return nil, fmt.Errorf("failed making temp dir: %w", err)
}
defer func() {
if !success {
// Intentionally swallow error
_ = os.RemoveAll(dir)
}
}()
}

// Create program.csproj
var depLine string
// Slash means it is a path
if strings.ContainsAny(options.Version, `/\`) {
// Get absolute path of csproj file
absCsproj, err := filepath.Abs(filepath.Join(options.Version, "src/Temporalio/Temporalio.csproj"))
if err != nil {
return nil, fmt.Errorf("cannot make absolute path from version: %w", err)
} else if _, err := os.Stat(absCsproj); err != nil {
return nil, fmt.Errorf("cannot find version path of %v: %w", absCsproj, err)
}
depLine = `<ProjectReference Include="` + html.EscapeString(absCsproj) + `" />`
// Need to build this csproj first
cmd := exec.CommandContext(ctx, "dotnet", "build", absCsproj)
cmd.Dir = dir
cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr
if err := cmd.Run(); err != nil {
return nil, fmt.Errorf("failed dotnet build of csproj in version: %w", err)
}
} else {
depLine = `<PackageReference Include="Temporalio" Version="` +
html.EscapeString(strings.TrimPrefix(options.Version, "v")) + `" />`
}
// Add the item group for the Temporalio dep just before the ending project tag
endProjectTag := strings.LastIndex(options.CsprojContents, "</Project>")
if endProjectTag == -1 {
return nil, fmt.Errorf("no ending project tag found in csproj contents")
}
csproj := options.CsprojContents[:endProjectTag] + "\n <ItemGroup>\n " + depLine +
"\n </ItemGroup>\n" + options.CsprojContents[endProjectTag:]
if err := os.WriteFile(filepath.Join(dir, "program.csproj"), []byte(csproj), 0644); err != nil {
return nil, fmt.Errorf("failed writing program.csproj: %w", err)
}

// Create Program.cs
if err := os.WriteFile(filepath.Join(dir, "Program.cs"), []byte(options.ProgramContents), 0644); err != nil {
return nil, fmt.Errorf("failed writing Program.cs: %w", err)
}

// Build it into build folder
cmd := exec.CommandContext(ctx, "dotnet", "build", "--output", "build")
cmd.Dir = dir
cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr
if err := cmd.Run(); err != nil {
return nil, fmt.Errorf("failed dotnet build: %w", err)
}

// All good
success = true
return &DotNetProgram{dir}, nil
}

// DotNetProgramFromDir recreates the Go program from a Dir() result of a
// BuildDotNetProgram().
func DotNetProgramFromDir(dir string) (*DotNetProgram, error) {
// Quick sanity check on the presence of program.csproj
if _, err := os.Stat(filepath.Join(dir, "program.csproj")); err != nil {
return nil, fmt.Errorf("failed finding program.csproj in dir: %w", err)
}
return &DotNetProgram{dir}, nil
}

// Dir is the directory to run in.
func (d *DotNetProgram) Dir() string { return d.dir }

// NewCommand makes a new command for the given args.
func (d *DotNetProgram) NewCommand(ctx context.Context, args ...string) (*exec.Cmd, error) {
exe := "./build/program"
if runtime.GOOS == "windows" {
exe += ".exe"
}
cmd := exec.CommandContext(ctx, exe, args...)
cmd.Dir = d.dir
cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr
return cmd, nil
}
Loading

0 comments on commit 7c3dcf0

Please sign in to comment.