Skip to content

Commit 71e56f0

Browse files
authored
Merge branch 'main' into extend-api
Signed-off-by: PePe Amengual <[email protected]>
2 parents 16fe0d8 + 766dac9 commit 71e56f0

22 files changed

+416
-86
lines changed

.github/workflows/lint.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ jobs:
6565
go-version-file: go.mod
6666

6767
- name: golangci-lint
68-
uses: golangci/golangci-lint-action@ec5d18412c0aeab7936cb16880d708ba2a64e1ae # v6
68+
uses: golangci/golangci-lint-action@e60da84bfae8c7920a47be973d75e15710aa8bd7 # v6
6969
with:
7070
# renovate: datasource=github-releases depName=golangci/golangci-lint
7171
version: v1.62.2

.github/workflows/scorecard.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,6 @@ jobs:
5656

5757
# Upload the results to GitHub's code scanning dashboard.
5858
- name: 'Upload to code-scanning'
59-
uses: github/codeql-action/upload-sarif@48ab28a6f5dbc2a99bf1e0131198dd8f1df78169 # v3.28.0
59+
uses: github/codeql-action/upload-sarif@17a820bf2e43b47be2c72b39cc905417bc1ab6d0 # v3.28.6
6060
with:
6161
sarif_file: results.sarif

Dockerfile.dev

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
FROM ghcr.io/runatlantis/atlantis:latest@sha256:f95cdf8f42370abf68d9e095930de8812e3b2a0dd66c9ffc39a69c8f49727989
1+
FROM ghcr.io/runatlantis/atlantis:latest@sha256:9145babb08e8a3e80e6367af8bf8e443d75be622864ce80a0410a40de5e0f4ac
22
COPY atlantis /usr/local/bin/atlantis
33
WORKDIR /atlantis/src

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ require (
2121
github.com/gorilla/mux v1.8.1
2222
github.com/gorilla/websocket v1.5.3
2323
github.com/hashicorp/go-getter/v2 v2.2.3
24-
github.com/hashicorp/go-multierror v1.1.1
2524
github.com/hashicorp/go-version v1.7.0
2625
github.com/hashicorp/golang-lru/v2 v2.0.7
2726
github.com/hashicorp/hc-install v0.9.0
@@ -96,6 +95,7 @@ require (
9695
github.com/gorilla/css v1.0.1 // indirect
9796
github.com/hashicorp/errwrap v1.1.0 // indirect
9897
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
98+
github.com/hashicorp/go-multierror v1.1.1 // indirect
9999
github.com/hashicorp/go-retryablehttp v0.7.7 // indirect
100100
github.com/hashicorp/go-safetemp v1.0.0 // indirect
101101
github.com/hashicorp/hcl v1.0.0 // indirect

server/controllers/api_controller.go

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ type APIController struct {
3333
RepoAllowlistChecker *events.RepoAllowlistChecker
3434
Scope tally.Scope
3535
VCSClient vcs.Client
36+
WorkingDir events.WorkingDir
37+
WorkingDirLocker events.WorkingDirLocker
3638
CommitStatusUpdater events.CommitStatusUpdater
3739
}
3840

@@ -93,12 +95,18 @@ func (a *APIController) Plan(w http.ResponseWriter, r *http.Request) {
9395
return
9496
}
9597

98+
err = a.apiSetup(ctx)
99+
if err != nil {
100+
a.apiReportError(w, http.StatusInternalServerError, err)
101+
return
102+
}
103+
96104
result, err := a.apiPlan(request, ctx)
97105
if err != nil {
98106
a.apiReportError(w, http.StatusInternalServerError, err)
99107
return
100108
}
101-
defer a.Locker.UnlockByPull(ctx.HeadRepo.FullName, 0) // nolint: errcheck
109+
defer a.Locker.UnlockByPull(ctx.HeadRepo.FullName, ctx.Pull.Num) // nolint: errcheck
102110
if result.HasErrors() {
103111
code = http.StatusInternalServerError
104112
}
@@ -121,13 +129,19 @@ func (a *APIController) Apply(w http.ResponseWriter, r *http.Request) {
121129
return
122130
}
123131

132+
err = a.apiSetup(ctx)
133+
if err != nil {
134+
a.apiReportError(w, http.StatusInternalServerError, err)
135+
return
136+
}
137+
124138
// We must first make the plan for all projects
125139
_, err = a.apiPlan(request, ctx)
126140
if err != nil {
127141
a.apiReportError(w, http.StatusInternalServerError, err)
128142
return
129143
}
130-
defer a.Locker.UnlockByPull(ctx.HeadRepo.FullName, 0) // nolint: errcheck
144+
defer a.Locker.UnlockByPull(ctx.HeadRepo.FullName, ctx.Pull.Num) // nolint: errcheck
131145

132146
// We can now prepare and run the apply step
133147
result, err := a.apiApply(request, ctx)
@@ -147,6 +161,27 @@ func (a *APIController) Apply(w http.ResponseWriter, r *http.Request) {
147161
a.respond(w, logging.Warn, code, "%s", string(response))
148162
}
149163

164+
func (a *APIController) apiSetup(ctx *command.Context) error {
165+
pull := ctx.Pull
166+
baseRepo := ctx.Pull.BaseRepo
167+
headRepo := ctx.HeadRepo
168+
169+
unlockFn, err := a.WorkingDirLocker.TryLock(baseRepo.FullName, pull.Num, events.DefaultWorkspace, events.DefaultRepoRelDir)
170+
if err != nil {
171+
return err
172+
}
173+
ctx.Log.Debug("got workspace lock")
174+
defer unlockFn()
175+
176+
// ensure workingDir is present
177+
_, _, err = a.WorkingDir.Clone(ctx.Log, headRepo, pull, events.DefaultWorkspace)
178+
if err != nil {
179+
return err
180+
}
181+
182+
return nil
183+
}
184+
150185
func (a *APIController) apiPlan(request *APIRequest, ctx *command.Context) (*command.Result, error) {
151186
cmds, cc, err := request.getCommands(ctx, a.ProjectCommandBuilder.BuildPlanCommands)
152187
if err != nil {

server/controllers/api_controller_test.go

Lines changed: 176 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -70,36 +70,194 @@ func testPlan(t *testing.T, ref, commit, baseBranch string) {
7070

7171
projectCommandBuilder.VerifyWasCalledOnce().BuildPlanCommands(cmdContext, commentCmd)
7272
projectCommandRunner.VerifyWasCalledOnce().Plan(Any[command.ProjectContext]())
73+
74+
cases := []struct {
75+
repository string
76+
ref string
77+
vcsType string
78+
pr int
79+
projects []string
80+
paths []struct {
81+
Directory string
82+
Workspace string
83+
}
84+
}{
85+
{
86+
repository: "Repo",
87+
ref: "main",
88+
vcsType: "Gitlab",
89+
projects: []string{"default"},
90+
},
91+
{
92+
repository: "Repo",
93+
ref: "main",
94+
vcsType: "Gitlab",
95+
pr: 1,
96+
},
97+
{
98+
repository: "Repo",
99+
ref: "main",
100+
vcsType: "Gitlab",
101+
paths: []struct {
102+
Directory string
103+
Workspace string
104+
}{
105+
{
106+
Directory: ".",
107+
Workspace: "myworkspace",
108+
},
109+
{
110+
Directory: "./myworkspace2",
111+
Workspace: "myworkspace2",
112+
},
113+
},
114+
},
115+
{
116+
repository: "Repo",
117+
ref: "main",
118+
vcsType: "Gitlab",
119+
pr: 1,
120+
projects: []string{"test"},
121+
paths: []struct {
122+
Directory string
123+
Workspace string
124+
}{
125+
{
126+
Directory: ".",
127+
Workspace: "myworkspace",
128+
},
129+
},
130+
},
131+
}
132+
133+
expectedCalls := 0
134+
for _, c := range cases {
135+
body, _ := json.Marshal(controllers.APIRequest{
136+
Repository: c.repository,
137+
Ref: c.ref,
138+
Type: c.vcsType,
139+
PR: c.pr,
140+
Projects: c.projects,
141+
Paths: c.paths,
142+
})
143+
144+
req, _ := http.NewRequest("POST", "", bytes.NewBuffer(body))
145+
req.Header.Set(atlantisTokenHeader, atlantisToken)
146+
w := httptest.NewRecorder()
147+
ac.Plan(w, req)
148+
ResponseContains(t, w, http.StatusOK, "")
149+
150+
expectedCalls += len(c.projects)
151+
expectedCalls += len(c.paths)
152+
}
153+
154+
projectCommandBuilder.VerifyWasCalled(Times(expectedCalls)).BuildPlanCommands(Any[*command.Context](), Any[*events.CommentCommand]())
155+
projectCommandRunner.VerifyWasCalled(Times(expectedCalls)).Plan(Any[command.ProjectContext]())
73156
}
74157

75158
func TestAPIController_Apply(t *testing.T) {
76159
ac, projectCommandBuilder, projectCommandRunner := setup(t)
77-
body, _ := json.Marshal(controllers.APIRequest{
78-
Repository: "Repo",
79-
Ref: "main",
80-
Type: "Gitlab",
81-
Projects: []string{"default"},
82-
})
83-
req, _ := http.NewRequest("POST", "", bytes.NewBuffer(body))
84-
req.Header.Set(atlantisTokenHeader, atlantisToken)
85-
w := httptest.NewRecorder()
86-
ac.Apply(w, req)
87-
ResponseContains(t, w, http.StatusOK, "")
88-
projectCommandBuilder.VerifyWasCalledOnce().BuildApplyCommands(Any[*command.Context](), Any[*events.CommentCommand]())
89-
projectCommandRunner.VerifyWasCalledOnce().Plan(Any[command.ProjectContext]())
90-
projectCommandRunner.VerifyWasCalledOnce().Apply(Any[command.ProjectContext]())
160+
161+
cases := []struct {
162+
repository string
163+
ref string
164+
vcsType string
165+
pr int
166+
projects []string
167+
paths []struct {
168+
Directory string
169+
Workspace string
170+
}
171+
}{
172+
{
173+
repository: "Repo",
174+
ref: "main",
175+
vcsType: "Gitlab",
176+
projects: []string{"default"},
177+
},
178+
{
179+
repository: "Repo",
180+
ref: "main",
181+
vcsType: "Gitlab",
182+
pr: 1,
183+
},
184+
{
185+
repository: "Repo",
186+
ref: "main",
187+
vcsType: "Gitlab",
188+
paths: []struct {
189+
Directory string
190+
Workspace string
191+
}{
192+
{
193+
Directory: ".",
194+
Workspace: "myworkspace",
195+
},
196+
{
197+
Directory: "./myworkspace2",
198+
Workspace: "myworkspace2",
199+
},
200+
},
201+
},
202+
{
203+
repository: "Repo",
204+
ref: "main",
205+
vcsType: "Gitlab",
206+
pr: 1,
207+
projects: []string{"test"},
208+
paths: []struct {
209+
Directory string
210+
Workspace string
211+
}{
212+
{
213+
Directory: ".",
214+
Workspace: "myworkspace",
215+
},
216+
},
217+
},
218+
}
219+
220+
expectedCalls := 0
221+
for _, c := range cases {
222+
body, _ := json.Marshal(controllers.APIRequest{
223+
Repository: c.repository,
224+
Ref: c.ref,
225+
Type: c.vcsType,
226+
PR: c.pr,
227+
Projects: c.projects,
228+
Paths: c.paths,
229+
})
230+
231+
req, _ := http.NewRequest("POST", "", bytes.NewBuffer(body))
232+
req.Header.Set(atlantisTokenHeader, atlantisToken)
233+
w := httptest.NewRecorder()
234+
ac.Apply(w, req)
235+
ResponseContains(t, w, http.StatusOK, "")
236+
237+
expectedCalls += len(c.projects)
238+
expectedCalls += len(c.paths)
239+
}
240+
241+
projectCommandBuilder.VerifyWasCalled(Times(expectedCalls)).BuildApplyCommands(Any[*command.Context](), Any[*events.CommentCommand]())
242+
projectCommandRunner.VerifyWasCalled(Times(expectedCalls)).Plan(Any[command.ProjectContext]())
243+
projectCommandRunner.VerifyWasCalled(Times(expectedCalls)).Apply(Any[command.ProjectContext]())
91244
}
92245

93246
func setup(t *testing.T) (controllers.APIController, *MockProjectCommandBuilder, *MockProjectCommandRunner) {
94247
RegisterMockTestingT(t)
95248
locker := NewMockLocker()
96249
logger := logging.NewNoopLogger(t)
97-
scope, _, _ := metrics.NewLoggingScope(logger, "null")
98250
parser := NewMockEventParsing()
99-
vcsClient := NewMockClient()
100251
repoAllowlistChecker, err := events.NewRepoAllowlistChecker("*")
252+
scope, _, _ := metrics.NewLoggingScope(logger, "null")
253+
vcsClient := NewMockClient()
254+
workingDir := NewMockWorkingDir()
101255
Ok(t, err)
102256

257+
workingDirLocker := NewMockWorkingDirLocker()
258+
When(workingDirLocker.TryLock(Any[string](), Any[int](), Eq(events.DefaultWorkspace), Eq(events.DefaultRepoRelDir))).
259+
ThenReturn(func() {}, nil)
260+
103261
projectCommandBuilder := NewMockProjectCommandBuilder()
104262
When(projectCommandBuilder.BuildPlanCommands(Any[*command.Context](), Any[*events.CommentCommand]())).
105263
ThenReturn([]command.ProjectContext{{
@@ -143,6 +301,8 @@ func setup(t *testing.T) (controllers.APIController, *MockProjectCommandBuilder,
143301
PostWorkflowHooksCommandRunner: postWorkflowHooksCommandRunner,
144302
VCSClient: vcsClient,
145303
RepoAllowlistChecker: repoAllowlistChecker,
304+
WorkingDir: workingDir,
305+
WorkingDirLocker: workingDirLocker,
146306
CommitStatusUpdater: commitStatusUpdater,
147307
}
148308
return ac, projectCommandBuilder, projectCommandRunner

server/controllers/events/testdata/test-repos/policy-checks-diff-owner/exp-output-approve-policies.txt

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,7 @@ Ran Approve Policies for 1 projects:
66
### 1. dir: `.` workspace: `default`
77
**Approve Policies Error**
88
```
9-
1 error occurred:
10-
* policy set: test_policy user runatlantis is not a policy owner - please contact policy owners to approve failing policies
11-
12-
9+
policy set: test_policy user runatlantis is not a policy owner - please contact policy owners to approve failing policies
1310
```
1411
#### Policy Approval Status:
1512
```

server/core/db/boltdb.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -504,3 +504,7 @@ func (b *BoltDB) projectResultToProject(p command.ProjectResult) models.ProjectS
504504
Status: p.PlanStatus(),
505505
}
506506
}
507+
508+
func (b *BoltDB) Close() error {
509+
return b.db.Close()
510+
}

0 commit comments

Comments
 (0)