diff --git a/runatlantis.io/docs/api-endpoints.md b/runatlantis.io/docs/api-endpoints.md index ce622979da..72e81f03f8 100644 --- a/runatlantis.io/docs/api-endpoints.md +++ b/runatlantis.io/docs/api-endpoints.md @@ -4,7 +4,8 @@ Aside from interacting via pull request comments, Atlantis could respond to a li ## Main Endpoints -The API endpoints in this section are disabled by default, since these API endpoints could change the infrastructure directly. +The API endpoints in this section are disabled by default, since these API endpoints could change the infrastructure +directly. To enable the API endpoints, `api-secret` should be configured. :::tip Prerequisites @@ -21,13 +22,14 @@ Execute [atlantis plan](using-atlantis.md#atlantis-plan) on the specified reposi #### Parameters -| Name | Type | Required | Description | -|------------|---------|----------|------------------------------------------| -| Repository | string | Yes | Name of the Terraform repository | -| Ref | string | Yes | Git reference, like a branch name | -| Type | string | Yes | Type of the VCS provider (Github/Gitlab) | -| Paths | Path | Yes | Paths to the projects to run the plan | -| PR | int | No | Pull Request number | +| Name | Type | Required | Description | +|------------|--------|----------|--------------------------------------------------------------------------------------| +| Repository | string | Yes | Name of the Terraform repository | +| Ref | string | Yes | Git reference, like a branch name | +| Type | string | Yes | Type of the VCS provider (Github/Gitlab) | +| Paths | Path | Yes | Paths to the projects to run the plan | +| Sha | string | No | SHA of the specific commit to checkout. This is not required but heavily encouraged. | +| PR | int | No | Pull Request number | #### Path @@ -49,6 +51,7 @@ curl --request POST 'https:///api/plan' \ --data-raw '{ "Repository": "repo-name", "Ref": "main", + "Sha": "940222c757012e0922c5fc1e03d5574c5ce79994", "Type": "Github", "Paths": [{ "Directory": ".", @@ -62,29 +65,29 @@ curl --request POST 'https:///api/plan' \ ```json { - "Error": null, - "Failure": "", - "ProjectResults": [ - { - "Command": 1, - "RepoRelDir": ".", - "Workspace": "default", - "Error": null, - "Failure": "", - "PlanSuccess": { - "TerraformOutput": "", - "LockURL": "", - "RePlanCmd": "atlantis plan -d .", - "ApplyCmd": "atlantis apply -d .", - "HasDiverged": false - }, - "PolicyCheckSuccess": null, - "ApplySuccess": "", - "VersionSuccess": "", - "ProjectName": "" - } - ], - "PlansDeleted": false + "Error": null, + "Failure": "", + "ProjectResults": [ + { + "Command": 1, + "RepoRelDir": ".", + "Workspace": "default", + "Error": null, + "Failure": "", + "PlanSuccess": { + "TerraformOutput": "", + "LockURL": "", + "RePlanCmd": "atlantis plan -d .", + "ApplyCmd": "atlantis apply -d .", + "HasDiverged": false + }, + "PolicyCheckSuccess": null, + "ApplySuccess": "", + "VersionSuccess": "", + "ProjectName": "" + } + ], + "PlansDeleted": false } ``` @@ -96,13 +99,14 @@ Execute [atlantis apply](using-atlantis.md#atlantis-apply) on the specified repo #### Parameters -| Name | Type | Required | Description | -|------------|--------|----------|------------------------------------------| -| Repository | string | Yes | Name of the Terraform repository | -| Ref | string | Yes | Git reference, like a branch name | -| Type | string | Yes | Type of the VCS provider (Github/Gitlab) | -| Paths | Path | Yes | Paths to the projects to run the apply | -| PR | int | No | Pull Request number | +| Name | Type | Required | Description | +|------------|--------|----------|--------------------------------------------------------------------------------------| +| Repository | string | Yes | Name of the Terraform repository | +| Ref | string | Yes | Git reference, like a branch name | +| Type | string | Yes | Type of the VCS provider (Github/Gitlab) | +| Paths | Path | Yes | Paths to the projects to run the apply | +| Sha | string | No | SHA of the specific commit to checkout. This is not required but heavily encouraged. | +| PR | int | No | Pull Request number | #### Path @@ -124,6 +128,7 @@ curl --request POST 'https:///api/apply' \ --data-raw '{ "Repository": "repo-name", "Ref": "main", + "Sha": "940222c757012e0922c5fc1e03d5574c5ce79994", "Type": "Github", "Paths": [{ "Directory": ".", @@ -137,29 +142,30 @@ curl --request POST 'https:///api/apply' \ ```json { - "Error": null, - "Failure": "", - "ProjectResults": [ - { - "Command": 0, - "RepoRelDir": ".", - "Workspace": "default", - "Error": null, - "Failure": "", - "PlanSuccess": null, - "PolicyCheckSuccess": null, - "ApplySuccess": "", - "VersionSuccess": "", - "ProjectName": "" - } - ], - "PlansDeleted": false + "Error": null, + "Failure": "", + "ProjectResults": [ + { + "Command": 0, + "RepoRelDir": ".", + "Workspace": "default", + "Error": null, + "Failure": "", + "PlanSuccess": null, + "PolicyCheckSuccess": null, + "ApplySuccess": "", + "VersionSuccess": "", + "ProjectName": "" + } + ], + "PlansDeleted": false } ``` ## Other Endpoints -The endpoints listed in this section are non-destructive and therefore don't require authentication nor special secret token. +The endpoints listed in this section are non-destructive and therefore don't require authentication nor special secret +token. ### GET /status @@ -177,9 +183,9 @@ curl --request GET 'https:///status' ```json { - "shutting_down": false, - "in_progress_operations": 0, - "version": "0.22.3" + "shutting_down": false, + "in_progress_operations": 0, + "version": "0.22.3" } ``` @@ -199,6 +205,6 @@ curl --request GET 'https:///healthz' ```json { - "status": "ok" + "status": "ok" } ``` diff --git a/server/controllers/api_controller.go b/server/controllers/api_controller.go index ff85371469..3fb5eeebe8 100644 --- a/server/controllers/api_controller.go +++ b/server/controllers/api_controller.go @@ -39,6 +39,7 @@ type APIRequest struct { Repository string `validate:"required"` Ref string `validate:"required"` Type string `validate:"required"` + Sha string PR int Projects []string Paths []struct { @@ -233,13 +234,22 @@ func (a *APIController) apiParseAndValidate(r *http.Request) (*APIRequest, *comm return nil, nil, http.StatusForbidden, fmt.Errorf("repo not allowlisted") } + commit := request.Sha + if commit == "" { + // DEPRECATED: To maintain legacy behaviour, we set the commit to the ref. However, + // using the ref does not work in many cases and can also yield unexpected results + // as a ref is a moving target while a SHA is a static target. + commit = request.Ref + a.Logger.Warn("API was called with an empty SHA, this is deprecated. When calling the Atlantis API, the SHA should be specified explicitly.") + } + return &request, &command.Context{ HeadRepo: baseRepo, Pull: models.PullRequest{ Num: request.PR, BaseBranch: request.Ref, HeadBranch: request.Ref, - HeadCommit: request.Ref, + HeadCommit: commit, BaseRepo: baseRepo, }, Scope: a.Scope, diff --git a/server/controllers/api_controller_test.go b/server/controllers/api_controller_test.go index 3b3aa520aa..a3edc9d33d 100644 --- a/server/controllers/api_controller_test.go +++ b/server/controllers/api_controller_test.go @@ -28,6 +28,7 @@ func TestAPIController_Plan(t *testing.T) { body, _ := json.Marshal(controllers.APIRequest{ Repository: "Repo", Ref: "main", + Sha: "abc123", Type: "Gitlab", Projects: []string{"default"}, }) @@ -45,6 +46,7 @@ func TestAPIController_Apply(t *testing.T) { body, _ := json.Marshal(controllers.APIRequest{ Repository: "Repo", Ref: "main", + Sha: "abc123", Type: "Gitlab", Projects: []string{"default"}, })