Commit 80ca71a6 authored by Yann Hodique's avatar Yann Hodique Committed by GitHub

feat(kurtosis-devnet): handle building local artifacts (#13496)

This will allow us to point kurtosis to these artifacts, and deploy
them from HEAD.

Right now I'm assuming we have some available "just" recipes for them.
We might decide to do things differently down the road.
parent 6b221441
set shell := ["/bin/bash", "-c"]
# Internal recipes for kurtosis-devnet
_contracts-build BUNDLE='contracts-bundle.tar.gz':
just ../packages/contracts-bedrock/forge-build
tar -czf {{BUNDLE}} -C ../packages/contracts-bedrock artifacts forge-artifacts cache
_docker_build TAG TARGET='' CONTEXT='.' DOCKERFILE='Dockerfile':
docker buildx build -t {{TAG}} \
-f {{CONTEXT}}/{{DOCKERFILE}} \
{{ if TARGET != '' { "--target " + TARGET } else { "" } }} \
--build-arg GIT_COMMIT={git_commit} \
--build-arg GIT_DATE={git_date} \
{{CONTEXT}}
_docker_build_stack TAG TARGET='': (_docker_build TAG TARGET "../" "ops/docker/op-stack-go/Dockerfile")
cannon-image TAG='cannon:devnet': (_docker_build_stack TAG "cannon-target")
op-program-image TAG='op-program:devnet': (_docker_build_stack TAG "op-program-target")
op-wheel-image TAG='op-wheel:devnet': (_docker_build_stack TAG "op-wheel-target")
op-node-image TAG='op-node:devnet': (_docker_build_stack TAG "op-node-target")
op-challenger-image TAG='op-challenger:devnet': (_docker_build_stack TAG "op-challenger-target")
op-dispute-mon-image TAG='op-dispute-mon:devnet': (_docker_build_stack TAG "op-dispute-mon-target")
op-batcher-image TAG='op-batcher:devnet': (_docker_build_stack TAG "op-batcher-target")
op-proposer-image TAG='op-proposer:devnet': (_docker_build_stack TAG "op-proposer-target")
op-conductor-image TAG='op-conductor:devnet': (_docker_build_stack TAG "op-conductor-target")
da-server-image TAG='da-server:devnet': (_docker_build_stack TAG "da-server-target")
op-supervisor-image TAG='op-supervisor:devnet': (_docker_build_stack TAG "op-supervisor-target")
op-deployer-image TAG='op-deployer:devnet': (_docker_build_stack TAG "op-deployer-target")
package build
import (
"bytes"
"fmt"
"log"
"os/exec"
"text/template"
)
// ContractBuilder handles building smart contracts using just commands
type ContractBuilder struct {
// Base directory where the build commands should be executed
baseDir string
// Template for the build command
cmdTemplate *template.Template
// Dry run mode
dryRun bool
}
const (
contractsCmdTemplateStr = "just _contracts-build {{.BundlePath}}"
)
var defaultContractTemplate *template.Template
func init() {
defaultContractTemplate = template.Must(template.New("contract_build_cmd").Parse(contractsCmdTemplateStr))
}
type ContractBuilderOptions func(*ContractBuilder)
func WithContractBaseDir(baseDir string) ContractBuilderOptions {
return func(b *ContractBuilder) {
b.baseDir = baseDir
}
}
func WithContractTemplate(cmdTemplate *template.Template) ContractBuilderOptions {
return func(b *ContractBuilder) {
b.cmdTemplate = cmdTemplate
}
}
func WithContractDryRun(dryRun bool) ContractBuilderOptions {
return func(b *ContractBuilder) {
b.dryRun = dryRun
}
}
// NewContractBuilder creates a new ContractBuilder instance
func NewContractBuilder(opts ...ContractBuilderOptions) *ContractBuilder {
b := &ContractBuilder{
baseDir: ".",
cmdTemplate: defaultContractTemplate,
dryRun: false,
}
for _, opt := range opts {
opt(b)
}
return b
}
// templateData holds the data for the command template
type contractTemplateData struct {
Layer string
BundlePath string
}
// Build executes the contract build command
func (b *ContractBuilder) Build(layer string, bundlePath string) error {
log.Printf("Building contracts bundle: %s", bundlePath)
// Prepare template data
data := contractTemplateData{
Layer: layer,
BundlePath: bundlePath,
}
// Execute template to get command string
var cmdBuf bytes.Buffer
if err := b.cmdTemplate.Execute(&cmdBuf, data); err != nil {
return fmt.Errorf("failed to execute command template: %w", err)
}
// Create command
cmd := exec.Command("sh", "-c", cmdBuf.String())
cmd.Dir = b.baseDir
if !b.dryRun {
output, err := cmd.CombinedOutput()
if err != nil {
return fmt.Errorf("contract build command failed: %w\nOutput: %s", err, string(output))
}
}
return nil
}
package build
import (
"bytes"
"fmt"
"log"
"os/exec"
"text/template"
)
// DockerBuilder handles building docker images using just commands
type DockerBuilder struct {
// Base directory where the build commands should be executed
baseDir string
// Template for the build command
cmdTemplate *template.Template
// Dry run mode
dryRun bool
}
const cmdTemplateStr = "just {{.ProjectName}}-image {{.ImageTag}}"
var defaultCmdTemplate *template.Template
func init() {
defaultCmdTemplate = template.Must(template.New("docker_build_cmd").Parse(cmdTemplateStr))
}
type DockerBuilderOptions func(*DockerBuilder)
func WithDockerCmdTemplate(cmdTemplate *template.Template) DockerBuilderOptions {
return func(b *DockerBuilder) {
b.cmdTemplate = cmdTemplate
}
}
func WithDockerBaseDir(baseDir string) DockerBuilderOptions {
return func(b *DockerBuilder) {
b.baseDir = baseDir
}
}
func WithDockerDryRun(dryRun bool) DockerBuilderOptions {
return func(b *DockerBuilder) {
b.dryRun = dryRun
}
}
// NewDockerBuilder creates a new DockerBuilder instance
func NewDockerBuilder(opts ...DockerBuilderOptions) *DockerBuilder {
b := &DockerBuilder{
baseDir: ".",
cmdTemplate: defaultCmdTemplate,
dryRun: false,
}
for _, opt := range opts {
opt(b)
}
return b
}
// templateData holds the data for the command template
type templateData struct {
ImageTag string
ProjectName string
}
// Build executes the docker build command for the given project and image tag
func (b *DockerBuilder) Build(projectName, imageTag string) (string, error) {
log.Printf("Building docker image for project: %s with tag: %s", projectName, imageTag)
// Prepare template data
data := templateData{
ImageTag: imageTag,
ProjectName: projectName,
}
// Execute template to get command string
var cmdBuf bytes.Buffer
if err := b.cmdTemplate.Execute(&cmdBuf, data); err != nil {
return "", fmt.Errorf("failed to execute command template: %w", err)
}
// Create command
cmd := exec.Command("sh", "-c", cmdBuf.String())
cmd.Dir = b.baseDir
if !b.dryRun {
output, err := cmd.CombinedOutput()
if err != nil {
return "", fmt.Errorf("build command failed: %w\nOutput: %s", err, string(output))
}
}
// Return the image tag as confirmation of successful build
return imageTag, nil
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment