Skip to content

Commit a596197

Browse files
zulkhairTest Userezavada
authored
feat: WE V2 build (#242)
Closes: DEVP-221 This is a workaround to be able to build WEv2 projects from World CLI using the `world build` command. It uses a new ARGUS_WEV2_GITHUB_TOKEN environment variable to be able to pull from the go-ecs private repo for dependencies, which is not a long term solution. <!--- Add a prefix to indicate what kind of release this pull request corresponds to: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert ---> ## Overview > Description of the overall background and high-level changes that this PR introduces <!--- Example: This pull request improves documentation of area A by adding ... ---> ## Brief Changelog <!--- Example: - The metadata is stored in the blob store on job creation time as a persistent artifact - Deployments RPC transmits only the blob storage reference - Daemons retrieve the RPC data from the blob cache ---> ## Testing and Verifying <!--- Pick one of the following options: - This change is a trivial rework/code cleanup without any test coverage. - This change is already covered by existing tests, such as <describe test>. - This change added tests and can be verified as follows: - Added unit test that validates ... - Added integration tests for end-to-end deployment with ... - Extended integration test for ... - Manually verified the change by ... ---> <!-- greptile_comment --> ## Greptile Summary Implements a temporary workaround for building WE V2 projects via World CLI by adding GitHub token authentication and modifying build processes. - Modified `common/docker/client_image.go` to support private repo access by adding SSH keys and GitHub token handling - Updated `common/docker/service/cardinal.Dockerfile` to use GitHub token auth and removed debug build stage - Changed `cmd/world/cardinal/build.go` to create default config when none exists, with infinite build timeout - Disabled parallel test execution in `cmd_setup_test.go` to prevent race conditions - Security concern: SSH keys are being copied into Docker build context, which requires careful handling <!-- /greptile_comment --> --------- Co-authored-by: Test User <test@example.com> Co-authored-by: Ed Zavada <edmund@argus.gg>
1 parent 77ca434 commit a596197

7 files changed

Lines changed: 91 additions & 58 deletions

File tree

cmd/world/cardinal/build.go

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package cardinal
33
import (
44
"context"
55
"fmt"
6+
"os"
67

78
"github.com/docker/docker/api/types/registry"
89
"github.com/rotisserie/eris"
@@ -18,7 +19,25 @@ import (
1819
func (h *Handler) Build(ctx context.Context, f models.BuildCardinalFlags) error {
1920
cfg, err := config.GetConfig(&f.Config)
2021
if err != nil {
21-
return err
22+
// No config file found, create a default config
23+
printer.Infoln("No config file found, creating a default config")
24+
25+
// Get current working directory for Cardinal v2 projects
26+
cwd, err := os.Getwd()
27+
if err != nil {
28+
return eris.Wrap(err, "Failed to get current working directory")
29+
}
30+
31+
// Create a default config
32+
cfg = &config.Config{
33+
RootDir: cwd,
34+
GameDir: cwd,
35+
Detach: false,
36+
Build: true,
37+
DockerEnv: make(map[string]string),
38+
}
39+
40+
cfg.DockerEnv[DockerCardinalEnvLogLevel] = zerolog.DebugLevel.String()
2241
}
2342
cfg.Timeout = -1
2443

@@ -50,6 +69,12 @@ func (h *Handler) Build(ctx context.Context, f models.BuildCardinalFlags) error
5069
printer.Infoln("Building Cardinal game shard image...")
5170
printer.Infoln("This may take a few minutes.")
5271

72+
// Set the namespace
73+
if cfg.DockerEnv["CARDINAL_NAMESPACE"] == "" {
74+
cfg.DockerEnv["CARDINAL_NAMESPACE"] = "defaultnamespace"
75+
}
76+
printer.Infof("Namespace: %s\n", cfg.DockerEnv["CARDINAL_NAMESPACE"])
77+
5378
group, groupCtx := errgroup.WithContext(ctx)
5479

5580
// Create docker client

cmd/world/internal/controllers/cmd_setup/cmd_setup_test.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ func TestSetupCommandSuite(t *testing.T) {
5959

6060
// TestLoginScenarios tests various login scenarios.
6161
func (s *SetupCommandSuite) TestLoginScenarios() {
62-
s.T().Parallel()
62+
// s.T().Parallel()
6363

6464
testCases := []struct {
6565
name string
@@ -161,7 +161,7 @@ func (s *SetupCommandSuite) TestLoginScenarios() {
161161

162162
// TestHandleOrganizationInvitationsAcceptInvitation tests accepting organization invitations.
163163
func (s *SetupCommandSuite) TestHandleOrganizationInvitationsAcceptInvitation() {
164-
s.T().Parallel()
164+
// s.T().Parallel()
165165
controller, mockAPI, mockConfig, mockInput, mockRepo, mockOrgHandler, mockProjectHandler := s.createTestController()
166166
ctx := context.Background()
167167

@@ -311,7 +311,7 @@ func (s *SetupCommandSuite) TestRepoLookupSuccess() {
311311

312312
// TestRepoLookupNotLoggedIn tests repository lookup when user is not logged in.
313313
func (s *SetupCommandSuite) TestRepoLookupNotLoggedIn() {
314-
s.T().Parallel()
314+
// s.T().Parallel()
315315
controller, mockAPI, mockConfig, mockInput, mockRepo, mockOrgHandler, mockProjectHandler := s.createTestController()
316316
ctx := context.Background()
317317

@@ -343,7 +343,7 @@ func (s *SetupCommandSuite) TestRepoLookupNotLoggedIn() {
343343

344344
// TestNeedOrgDataNoOrgsCreateNew tests creating a new organization when none exist.
345345
func (s *SetupCommandSuite) TestNeedOrgDataNoOrgsCreateNew() {
346-
s.T().Parallel()
346+
// s.T().Parallel()
347347
controller, mockAPI, mockConfig, mockInput, mockRepo, mockOrgHandler, mockProjectHandler := s.createTestController()
348348
ctx := context.Background()
349349

@@ -777,7 +777,7 @@ func (s *SetupCommandSuite) TestRepoLookupNewProjectDiscovered() {
777777

778778
// TestOrganizationInvitationScenarios tests organization invitation handling.
779779
func (s *SetupCommandSuite) TestOrganizationInvitationScenarios() {
780-
s.T().Parallel()
780+
// s.T().Parallel()
781781

782782
testCases := []struct {
783783
name string
@@ -852,7 +852,7 @@ func (s *SetupCommandSuite) TestOrganizationInvitationScenarios() {
852852

853853
// TestOrganizationDataScenarios tests organization data handling scenarios.
854854
func (s *SetupCommandSuite) TestOrganizationDataScenarios() {
855-
s.T().Parallel()
855+
// s.T().Parallel()
856856

857857
testCases := []struct {
858858
name string
@@ -1004,7 +1004,7 @@ func (s *SetupCommandSuite) TestOrganizationDataScenarios() {
10041004

10051005
// TestProjectDataScenarios tests project data handling scenarios.
10061006
func (s *SetupCommandSuite) TestProjectDataScenarios() {
1007-
s.T().Parallel()
1007+
// s.T().Parallel()
10081008

10091009
testCases := []struct {
10101010
name string
@@ -1199,7 +1199,7 @@ func (s *SetupCommandSuite) TestProjectDataScenarios() {
11991199

12001200
// TestExistingDataScenarios tests existing data handling scenarios.
12011201
func (s *SetupCommandSuite) TestExistingDataScenarios() {
1202-
s.T().Parallel()
1202+
// s.T().Parallel()
12031203

12041204
testCases := []struct {
12051205
name string

common/docker/client_image.go

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -147,10 +147,19 @@ func (c *Client) buildImage(ctx context.Context, dockerService service.Service)
147147
// Read the tar archive
148148
tarReader := bytes.NewReader(buf.Bytes())
149149

150+
sourcePath := "."
151+
githubToken := os.Getenv("ARGUS_WEV2_GITHUB_TOKEN")
152+
if githubToken == "" {
153+
return nil, eris.New("ARGUS_WEV2_GITHUB_TOKEN is not set")
154+
}
150155
buildOptions := build.ImageBuildOptions{
151156
Dockerfile: "Dockerfile",
152157
Tags: []string{dockerService.Image},
153158
Target: dockerService.BuildTarget,
159+
BuildArgs: map[string]*string{
160+
"SOURCE_PATH": &sourcePath,
161+
"GITHUB_TOKEN": &githubToken,
162+
},
154163
}
155164

156165
if service.BuildkitSupport {
@@ -178,9 +187,10 @@ func (c *Client) addFileToTarWriter(baseDir string, tw *tar.Writer) error {
178187
if err != nil {
179188
return eris.Wrapf(err, "Failed to get relative path %s", path)
180189
}
181-
// Skip files that are not world.toml or inside the cardinal directory
182-
if info.Name() != "world.toml" && !strings.HasPrefix(filepath.ToSlash(relPath), "cardinal/") {
183-
return nil
190+
191+
// Skip .git directory and all files inside it
192+
if info.Name() == ".git" {
193+
return filepath.SkipDir
184194
}
185195

186196
// Create a tar header for the file or directory

common/docker/client_internal_test.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,11 @@ func TestStartUndetach(t *testing.T) {
211211
func TestBuild(t *testing.T) {
212212
t.Parallel()
213213

214+
// Skip test if GitHub token is not available
215+
if os.Getenv("ARGUS_WEV2_GITHUB_TOKEN") == "" {
216+
t.Skip("Skipping build test - ARGUS_WEV2_GITHUB_TOKEN not set")
217+
}
218+
214219
namespace := getUniqueNamespace(t)
215220

216221
// Create a temporary directory

common/docker/client_util.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ func checkBuildkitSupport(cli *client.Client) bool {
3232
return false
3333
}
3434

35-
// Check if DOCKER_BUILDKIT environment variable is set to 1
35+
// Always return true to enable BuildKit (or check environment variable)
3636
buildKitEnv := os.Getenv("DOCKER_BUILDKIT")
37-
return buildKitEnv == "1"
37+
return buildKitEnv == "1" || buildKitEnv == ""
3838
}
Lines changed: 18 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,61 +1,39 @@
11
################################
22
# Build Image - Normal
33
################################
4-
FROM golang:1.24-bookworm AS build
4+
FROM golang:1.24 AS build
5+
6+
ARG SOURCE_PATH
7+
ARG GITHUB_TOKEN
58

69
WORKDIR /go/src/app
710

8-
# Copy the go module files and download the dependencies
9-
# We do this before copying the rest of the source code to avoid
10-
# having to re-download the dependencies every time we build the image
11-
COPY /cardinal/go.mod /cardinal/go.sum ./
12-
RUN go mod download
11+
# Set Go environment variables for private repositories
12+
ENV GOPRIVATE=github.com/argus-labs/*,pkg.world.dev/*
13+
14+
# Configure git to use HTTPS with GitHub token
15+
RUN --mount=type=secret,id=github_token \
16+
git config --global url."https://$(cat /run/secrets/github_token):x-oauth-basic@github.com/".insteadOf "https://github.com/"
17+
18+
# Copy the entire source code
19+
COPY /${SOURCE_PATH} ./
20+
21+
# Download dependencies
22+
RUN go mod tidy
1323

1424
# Set the GOCACHE environment variable to /root/.cache/go-build to speed up build
1525
ENV GOCACHE=/root/.cache/go-build
1626

17-
# Copy the rest of the source code and build the binary
18-
COPY /cardinal ./
27+
# Build the binary
1928
RUN --mount=type=cache,target="/root/.cache/go-build" go build -v -o /go/bin/app
2029

2130
################################
2231
# Runtime Image - Normal
2332
################################
2433
FROM gcr.io/distroless/base-debian12 AS runtime
2534

26-
# Copy world.toml to the image
27-
COPY world.toml world.toml
28-
2935
# Copy the binary from the build image
3036
COPY --from=build /go/bin/app /usr/bin
3137

3238
# Run the binary
33-
CMD ["app"]
34-
35-
################################
36-
# Runtime Image - Debug
37-
################################
38-
FROM golang:1.24-bookworm AS runtime-debug
39-
40-
WORKDIR /go/src/app
41-
42-
# Install delve
43-
RUN go install github.com/go-delve/delve/cmd/dlv@latest
44-
45-
# Copy the go module files and download the dependencies
46-
# We do this before copying the rest of the source code to avoid
47-
# having to re-download the dependencies every time we build the image
48-
COPY /cardinal/go.mod /cardinal/go.sum ./
49-
RUN go mod download
50-
51-
# Set the GOCACHE environment variable to /root/.cache/go-build to speed up build
52-
ENV GOCACHE=/root/.cache/go-build
53-
54-
# Copy the rest of the source code and build the binary with debugging symbols
55-
COPY /cardinal ./
56-
RUN --mount=type=cache,target="/root/.cache/go-build" go build -gcflags="all=-N -l" -v -o /usr/bin/app
57-
58-
# Copy world.toml to the image
59-
COPY world.toml world.toml
60-
61-
CMD ["dlv", "--listen=:40000", "--headless=true", "--api-version=2", "--accept-multiclient", "exec", "/usr/bin/app"]
39+
CMD ["app"]

common/docker/service/cardinal.go

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,27 @@ package service
33
import (
44
_ "embed"
55
"fmt"
6-
"strings"
76

87
"github.com/docker/docker/api/types/container"
98
"github.com/docker/go-connections/nat"
109
"pkg.world.dev/world-cli/common/config"
1110
)
1211

1312
const (
14-
// mountCache is the Docker mount command to cache the go build cache.
15-
mountCacheScript = `--mount=type=cache,target="/root/.cache/go-build"`
13+
// mountCache is the Docker mount command to cache the go build cache.
14+
// mountCacheScript = `--mount=type=cache,target="/root/.cache/go-build"`
15+
// mountSecret is the Docker mount command for GitHub token secret.
16+
// mountSecretScript = `--mount=type=secret,id=github_token`
17+
// gitConfigWithSecret is the git config command that uses the secret mount.
18+
//
19+
// gitConfigWithSecret = `RUN --mount=type=secret,id=github_token \
20+
// git config --global \
21+
// url."https://$(cat /run/secrets/github_token):x-oauth-basic@github.com/".insteadOf "https://github.com/"`
22+
//
23+
// gitConfigWithEnv is the git config command that uses environment variable.
24+
//
25+
// gitConfigWithEnv = `RUN git config --global \
26+
// url."https://${GITHUB_TOKEN}:x-oauth-basic@github.com/".insteadOf "https://github.com/"`
1627
)
1728

1829
//nolint:gochecknoglobals // dockerfileContent is embedded at compile time and is read-only
@@ -36,7 +47,11 @@ func Cardinal(cfg *config.Config) Service {
3647

3748
dockerfile := dockerfileContent
3849
if !BuildkitSupport {
39-
dockerfile = strings.ReplaceAll(dockerfile, mountCacheScript, "")
50+
// dockerfile = strings.ReplaceAll(dockerfile, mountCacheScript, "")
51+
// dockerfile = strings.ReplaceAll(dockerfile, gitConfigWithSecret, gitConfigWithEnv)
52+
// (not recommended) uncomment the lines above and comment out the panic if you want to support insecure builds
53+
// without BuildKit. Insecure because this embeds the GitHub token value in the image layers
54+
panic("BuildKit is required to build the Cardinal image. Please enable BuildKit in your Docker configuration.")
4055
}
4156

4257
// Set env variables

0 commit comments

Comments
 (0)