Skip to content

Commit 679d53d

Browse files
Integrated Buildkit and improved entrypoint
1 parent c1f337f commit 679d53d

File tree

6 files changed

+185
-49
lines changed

6 files changed

+185
-49
lines changed

action.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ inputs:
1818

1919
runs:
2020
using: "docker"
21-
image: 'Dockerfile'
21+
image: 'docker://ghcr.io/clouddrove/smurf:v1.0.4'
2222
args:
2323
- ${{ inputs.tool }}
2424
- ${{ inputs.command }}

cmd/sdkr/build.go

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ var buildCmd = &cobra.Command{
8383
return fmt.Errorf(color.RedString("Dockerfile not found at %s", configs.DockerfilePath))
8484
}
8585

86+
// In the RunE function, when creating the opts
8687
opts := docker.BuildOptions{
8788
ContextDir: configs.ContextDir,
8889
DockerfilePath: configs.DockerfilePath,
@@ -91,6 +92,7 @@ var buildCmd = &cobra.Command{
9192
Target: configs.Target,
9293
Platform: configs.Platform,
9394
Timeout: time.Duration(configs.BuildTimeout) * time.Second,
95+
BuildKit: configs.BuildKit,
9496
}
9597

9698
err := docker.Build(imageName, tag, opts)
@@ -108,13 +110,14 @@ smurf sdkr build
108110
}
109111

110112
func init() {
111-
buildCmd.Flags().StringVarP(&configs.DockerfilePath, "file", "f", "", "Path to Dockerfile relative to context directory")
112-
buildCmd.Flags().StringVar(&configs.ContextDir, "context", "", "Build context directory (default: current directory)")
113-
buildCmd.Flags().BoolVar(&configs.NoCache, "no-cache", false, "Do not use cache when building the image")
114-
buildCmd.Flags().StringArrayVar(&configs.BuildArgs, "build-arg", []string{}, "Set build-time variables")
115-
buildCmd.Flags().StringVar(&configs.Target, "target", "", "Set the target build stage to build")
116-
buildCmd.Flags().StringVar(&configs.Platform, "platform", "", "Set the platform for the build (e.g., linux/amd64, linux/arm64)")
117-
buildCmd.Flags().IntVar(&configs.BuildTimeout, "timeout", 1500, "Set the build timeout")
113+
buildCmd.Flags().StringVarP(&configs.DockerfilePath, "file", "f", "", "Path to Dockerfile relative to context directory")
114+
buildCmd.Flags().StringVar(&configs.ContextDir, "context", "", "Build context directory (default: current directory)")
115+
buildCmd.Flags().BoolVar(&configs.NoCache, "no-cache", false, "Do not use cache when building the image")
116+
buildCmd.Flags().StringArrayVar(&configs.BuildArgs, "build-arg", []string{}, "Set build-time variables")
117+
buildCmd.Flags().StringVar(&configs.Target, "target", "", "Set the target build stage to build")
118+
buildCmd.Flags().StringVar(&configs.Platform, "platform", "", "Set the platform for the build (e.g., linux/amd64, linux/arm64)")
119+
buildCmd.Flags().IntVar(&configs.BuildTimeout, "timeout", 1500, "Set the build timeout")
120+
buildCmd.Flags().BoolVar(&configs.BuildKit, "buildkit", false, "Enable BuildKit for advanced Dockerfile features")
118121

119-
sdkrCmd.AddCommand(buildCmd)
120-
}
122+
sdkrCmd.AddCommand(buildCmd)
123+
}

configs/configs.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import (
88
"gopkg.in/yaml.v2"
99
)
1010

11+
var BuildKit bool
12+
1113
// Config represents the structure of the configuration file
1214
func LoadConfig(filePath string) (*Config, error) {
1315
data, err := ioutil.ReadFile(filePath)
@@ -38,4 +40,4 @@ func ExportEnvironmentVariables(vars map[string]string) error {
3840
}
3941
}
4042
return nil
41-
}
43+
}

entrypoint.sh

Lines changed: 40 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,74 +1,78 @@
11
#!/bin/bash
22
set -e
33

4-
# Debugging info
5-
echo "Starting entrypoint script..."
6-
echo "Current User: $(whoami)"
7-
echo "Working Directory: $(pwd)"
8-
echo "AWS Region: ${AWS_REGION:-not set}"
9-
echo "EKS Cluster: ${EKS_CLUSTER_NAME:-not set}"
10-
11-
# Function to check file existence and non-emptiness
124
check_file_exists() {
135
if [ ! -s "$1" ]; then
14-
echo "Error: $1 is either missing or empty."
6+
echo "Error: $1 is either missing or empty."
157
exit 1
168
fi
179
}
1810

1911
aws_eks_login() {
12+
if [[ "$PROVIDER" != "aws" || "$TOOL" != "helm" ]]; then
13+
return 0
14+
fi
15+
2016
if [[ -z "$AWS_ACCESS_KEY_ID" || -z "$AWS_SECRET_ACCESS_KEY" || -z "$AWS_DEFAULT_REGION" || -z "$EKS_CLUSTER_NAME" ]]; then
21-
echo "⚠️ Warning: Required environment variables not set. Please ensure the following are set:"
22-
echo " - AWS_ACCESS_KEY_ID"
23-
echo " - AWS_SECRET_ACCESS_KEY"
24-
echo " - AWS_DEFAULT_REGION"
25-
echo " - EKS_CLUSTER_NAME"
26-
echo "Skipping AWS and EKS login."
17+
echo "❌ AWS credentials or EKS cluster name missing!"
2718
return 1
2819
fi
2920

30-
echo "🔹 Configuring AWS credentials..."
3121
aws configure set aws_access_key_id "$AWS_ACCESS_KEY_ID"
3222
aws configure set aws_secret_access_key "$AWS_SECRET_ACCESS_KEY"
33-
aws configure set default.region "$AWS_DEFAULT_REGION"
34-
echo "✅ AWS credentials configured successfully."
23+
aws configure set region "$AWS_DEFAULT_REGION"
3524

36-
# EKS Cluster Login
37-
echo "🔹 Getting EKS token for cluster: $EKS_CLUSTER_NAME..."
38-
aws eks update-kubeconfig --region "$AWS_DEFAULT_REGION" --name "$EKS_CLUSTER_NAME"
39-
if [ $? -eq 0 ]; then
40-
echo "✅ Successfully configured EKS cluster access."
25+
if aws eks update-kubeconfig --region "$AWS_DEFAULT_REGION" --name "$EKS_CLUSTER_NAME"; then
26+
echo "✅ Successfully updated kubeconfig for EKS."
27+
return 0
4128
else
42-
echo "❌ Failed to configure EKS cluster access."
29+
echo "❌ Failed to update kubeconfig for EKS."
30+
return 1
31+
fi
32+
}
33+
34+
aws_login() {
35+
if [[ "$PROVIDER" != "aws" || "$TOOL" != "terraform" ]]; then
36+
return 0
37+
fi
38+
39+
if [[ -z "$AWS_ACCESS_KEY_ID" || -z "$AWS_SECRET_ACCESS_KEY" || -z "$AWS_DEFAULT_REGION" ]]; then
40+
echo "❌ AWS credentials missing!"
4341
return 1
4442
fi
43+
44+
aws configure set aws_access_key_id "$AWS_ACCESS_KEY_ID"
45+
aws configure set aws_secret_access_key "$AWS_SECRET_ACCESS_KEY"
46+
aws configure set region "$AWS_DEFAULT_REGION"
4547
}
4648

47-
# Docker login if credentials are provided
49+
# AWS Login for EKS if needed
50+
if [[ "$PROVIDER" == "aws" && "$TOOL" == "helm" ]]; then
51+
aws_eks_login
52+
fi
53+
54+
# AWS Login for Terraform if needed
55+
if [[ "$PROVIDER" == "aws" && "$TOOL" == "terraform" ]]; then
56+
aws_login
57+
fi
58+
59+
# Docker Login
4860
if [[ -n "$DOCKER_USERNAME" && -n "$DOCKER_PASSWORD" ]]; then
49-
echo "$DOCKER_PASSWORD" | docker login --username "$DOCKER_USERNAME" --password-stdin
61+
echo "$DOCKER_PASSWORD" | docker login --username "$DOCKER_USERNAME" --password-stdin -q
5062
echo "✅ Successfully logged into Docker Hub."
5163
fi
5264

53-
# Perform AWS and EKS login
54-
aws_eks_login
55-
56-
# Initialize command with base command
65+
# Executing Smurf Command
5766
SMURF_CMD="/usr/local/bin/smurf"
5867

59-
# Add tool as first argument if provided
6068
if [[ $# -gt 0 ]]; then
6169
SMURF_CMD="$SMURF_CMD $1"
6270
shift
6371
fi
6472

65-
# Add remaining arguments
6673
if [[ $# -gt 0 ]]; then
6774
SMURF_CMD="$SMURF_CMD $*"
6875
fi
6976

70-
# Debug output
7177
echo "🔹 Executing command: $SMURF_CMD"
72-
73-
# Execute the final command
74-
exec $SMURF_CMD
78+
exec $SMURF_CMD

internal/docker/build.go

Lines changed: 127 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
package docker
22

33
import (
4+
"bufio"
45
"context"
56
"encoding/json"
67
"fmt"
78
"io"
9+
"os"
10+
"os/exec"
811
"path/filepath"
912
"strings"
1013
"time"
@@ -65,6 +68,7 @@ func Build(imageName, tag string, opts BuildOptions) error {
6568
}
6669

6770
fullImageName := fmt.Sprintf("%s:%s", imageName, tag)
71+
// In the Build function, modify the buildOptions
6872
buildOptions := types.ImageBuildOptions{
6973
Tags: []string{fullImageName},
7074
Dockerfile: relDockerfilePath,
@@ -79,6 +83,128 @@ func Build(imageName, tag string, opts BuildOptions) error {
7983
NetworkMode: "default",
8084
}
8185

86+
// Add this before the ImageBuild call
87+
if opts.BuildKit {
88+
// Enable BuildKit
89+
os.Setenv("DOCKER_BUILDKIT", "1")
90+
}
91+
92+
if opts.BuildKit {
93+
buildOptions.Version = types.BuilderBuildKit
94+
}
95+
96+
// Build function modification
97+
98+
// Modify this part in your docker.Build function
99+
if opts.BuildKit {
100+
spinner.UpdateText("Running build with BuildKit enabled...")
101+
102+
// Construct docker command arguments
103+
args := []string{"build"}
104+
105+
// Add the tag
106+
args = append(args, "--tag", fullImageName)
107+
108+
// Add other build options
109+
if opts.NoCache {
110+
args = append(args, "--no-cache")
111+
}
112+
if relDockerfilePath != "" {
113+
args = append(args, "--file", relDockerfilePath)
114+
}
115+
for k, v := range opts.BuildArgs {
116+
args = append(args, "--build-arg", fmt.Sprintf("%s=%s", k, v))
117+
}
118+
if opts.Target != "" {
119+
args = append(args, "--target", opts.Target)
120+
}
121+
if platform != "" {
122+
args = append(args, "--platform", platform)
123+
}
124+
125+
// Add the context directory as the last argument
126+
args = append(args, opts.ContextDir)
127+
128+
// Create and configure the command
129+
cmd := exec.Command("docker", args...)
130+
131+
// Set environment with BuildKit enabled
132+
cmd.Env = append(os.Environ(), "DOCKER_BUILDKIT=1")
133+
134+
// Create pipes for stdout and stderr
135+
stdoutPipe, err := cmd.StdoutPipe()
136+
if err != nil {
137+
return fmt.Errorf(color.RedString("failed to create stdout pipe: %v", err))
138+
}
139+
stderrPipe, err := cmd.StderrPipe()
140+
if err != nil {
141+
return fmt.Errorf(color.RedString("failed to create stderr pipe: %v", err))
142+
}
143+
144+
// Start the command
145+
if err := cmd.Start(); err != nil {
146+
return fmt.Errorf(color.RedString("failed to start build: %v", err))
147+
}
148+
149+
spinner.Success()
150+
progressBar, _ := pterm.DefaultProgressbar.WithTotal(100).WithTitle("Building").Start()
151+
152+
// Process stdout
153+
go func() {
154+
scanner := bufio.NewScanner(stdoutPipe)
155+
for scanner.Scan() {
156+
line := scanner.Text()
157+
if strings.HasPrefix(line, "Step ") {
158+
pterm.Info.Println(color.CyanString(line))
159+
progressBar.Add(5)
160+
} else {
161+
trimmed := strings.TrimSpace(line)
162+
if trimmed != "" {
163+
pterm.Debug.Println(trimmed)
164+
}
165+
}
166+
}
167+
}()
168+
169+
// Process stderr
170+
go func() {
171+
scanner := bufio.NewScanner(stderrPipe)
172+
for scanner.Scan() {
173+
line := scanner.Text()
174+
pterm.Debug.Println(color.YellowString(line))
175+
}
176+
}()
177+
178+
// Wait for the command to complete
179+
if err := cmd.Wait(); err != nil {
180+
progressBar.Stop()
181+
return fmt.Errorf(color.RedString("BuildKit build failed: %v", err))
182+
}
183+
184+
progressBar.Add(100 - progressBar.Current)
185+
186+
time.Sleep(2 * time.Second)
187+
188+
inspect, _, err := cli.ImageInspectWithRaw(ctx, fullImageName)
189+
if err != nil {
190+
return fmt.Errorf(color.RedString("failed to get image info: %v", err))
191+
}
192+
193+
panel := pterm.DefaultBox.WithTitle("Build Complete").Sprintf(` %s %s %s %s %s %s %s `,
194+
color.GreenString("✓ Image Built Successfully"),
195+
color.CyanString("Image: %s", fullImageName),
196+
color.CyanString("ID: %s", inspect.ID[:12]),
197+
color.CyanString("Size: %.2f MB", float64(inspect.Size)/1024/1024),
198+
color.CyanString("Platform: %s/%s", inspect.Os, inspect.Architecture),
199+
color.CyanString("Created: %s", inspect.Created[:19]),
200+
color.CyanString("Layers: %d", len(inspect.RootFS.Layers)),
201+
)
202+
203+
fmt.Println(panel)
204+
return nil
205+
}
206+
207+
// The rest of your original Build function continues below for non-BuildKit builds
82208
resp, err := cli.ImageBuild(ctx, buildCtx, buildOptions)
83209
if err != nil {
84210
spinner.Fail()
@@ -150,4 +276,4 @@ func Build(imageName, tag string, opts BuildOptions) error {
150276

151277
fmt.Println(panel)
152278
return nil
153-
}
279+
}

internal/docker/types.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ type BuildOptions struct {
1111
Target string
1212
Platform string
1313
Timeout time.Duration
14+
BuildKit bool
1415
}
1516

1617
// ImageInfo struct to hold information about a Docker image
@@ -40,4 +41,4 @@ type jsonMessage struct {
4041
Status string `json:"status"`
4142
Error string `json:"error"`
4243
Progress string `json:"progress"`
43-
}
44+
}

0 commit comments

Comments
 (0)