├── .adr-dir ├── .node-version ├── e2e ├── .gitignore ├── .gitconfig ├── Makefile ├── go.mod └── github.go ├── server ├── events │ ├── testdata │ │ ├── fs │ │ │ ├── repoA │ │ │ │ ├── baz │ │ │ │ │ ├── init.tf │ │ │ │ │ └── mods.tf │ │ │ │ ├── qux │ │ │ │ │ └── quxx │ │ │ │ │ │ ├── init.tf │ │ │ │ │ │ └── mods.tf │ │ │ │ └── modules │ │ │ │ │ ├── bar │ │ │ │ │ └── bar.tf │ │ │ │ │ └── foo │ │ │ │ │ ├── foo.tf │ │ │ │ │ └── mods.tf │ │ │ └── repoB │ │ │ │ ├── dev │ │ │ │ └── quxx │ │ │ │ │ ├── init.tf │ │ │ │ │ └── mods.tf │ │ │ │ ├── modules │ │ │ │ ├── bar │ │ │ │ │ └── bar.tf │ │ │ │ └── foo │ │ │ │ │ ├── foo.tf │ │ │ │ │ └── mods.tf │ │ │ │ └── prod │ │ │ │ └── quxx │ │ │ │ ├── init.tf │ │ │ │ └── mods.tf │ │ └── test-repos │ │ │ ├── no-cloud-block │ │ │ └── main.tf │ │ │ ├── workspace-configured │ │ │ └── main.tf │ │ │ └── cloud-block-without-workspace-name │ │ │ └── main.tf │ ├── vcs │ │ ├── vcs.go │ │ ├── bitbucketserver │ │ │ └── bitbucketserver.go │ │ ├── github_config.go │ │ ├── bitbucketcloud │ │ │ └── bitbucketcloud.go │ │ ├── testdata │ │ │ ├── azuredevops-policyevaluations.json │ │ │ ├── github-branch-protection-no-required-checks.json │ │ │ └── github-branch-protection-required-checks.json │ │ └── client_test.go │ ├── templates │ │ ├── apply_unwrapped_success.tmpl │ │ ├── version_unwrapped_success.tmpl │ │ ├── failure_with_log.tmpl │ │ ├── unwrapped_err_with_log.tmpl │ │ ├── single_project_version_unsuccessful.tmpl │ │ ├── failure.tmpl │ │ ├── log.tmpl │ │ ├── apply_wrapped_success.tmpl │ │ ├── diverged.tmpl │ │ ├── version_wrapped_success.tmpl │ │ ├── unwrapped_err.tmpl │ │ ├── policy_check.tmpl │ │ ├── wrapped_err.tmpl │ │ ├── single_project_plan_unsuccessful.tmpl │ │ ├── import_success_unwrapped.tmpl │ │ ├── state_rm_success_unwrapped.tmpl │ │ ├── multi_project_header.tmpl │ │ ├── single_project_apply.tmpl │ │ ├── single_project_import_success.tmpl │ │ ├── single_project_state_rm_success.tmpl │ │ ├── approve_all_projects.tmpl │ │ ├── single_project_version_success.tmpl │ │ ├── import_success_wrapped.tmpl │ │ ├── state_rm_success_wrapped.tmpl │ │ ├── multi_project_apply.tmpl │ │ ├── multi_project_import.tmpl │ │ ├── multi_project_state_rm.tmpl │ │ ├── multi_project_version.tmpl │ │ ├── single_project_plan_success.tmpl │ │ ├── plan_success_unwrapped.tmpl │ │ ├── single_project_policy_unsuccessful.tmpl │ │ ├── plan_success_wrapped.tmpl │ │ ├── policy_check_results_unwrapped.tmpl │ │ ├── multi_project_plan.tmpl │ │ ├── multi_project_policy_unsuccessful.tmpl │ │ └── policy_check_results_wrapped.tmpl │ ├── pull_status_fetcher.go │ ├── terraform │ │ └── ansi │ │ │ ├── strip.go │ │ │ └── strip_test.go │ ├── models │ │ └── commit_status_test.go │ ├── command │ │ ├── lock.go │ │ ├── result.go │ │ └── scope_tags.go │ ├── command_type.go │ └── db_updater.go ├── controllers │ └── events │ │ └── testdata │ │ └── test-repos │ │ ├── simple-yaml │ │ ├── staging.tfvars │ │ ├── exp-output-apply-locked.txt │ │ ├── exp-output-merge.txt │ │ ├── main.tf │ │ ├── exp-output-apply-default.txt │ │ ├── exp-output-apply-staging.txt │ │ ├── atlantis.yaml │ │ └── exp-output-apply-all.txt │ │ ├── tfvars-yaml │ │ ├── default.tfvars │ │ ├── staging.tfvars │ │ ├── default.backend.tfvars │ │ ├── staging.backend.tfvars │ │ ├── exp-output-merge.txt │ │ ├── main.tf │ │ ├── exp-output-apply-default.txt │ │ ├── exp-output-apply-staging.txt │ │ └── atlantis.yaml │ │ ├── tfvars-yaml-no-autoplan │ │ ├── default.tfvars │ │ ├── staging.tfvars │ │ ├── default.backend.tfvars │ │ ├── staging.backend.tfvars │ │ ├── exp-output-merge.txt │ │ ├── main.tf │ │ ├── exp-output-apply-default.txt │ │ ├── exp-output-apply-staging.txt │ │ └── atlantis.yaml │ │ ├── import-single-project │ │ ├── exp-output-apply-no-projects.txt │ │ ├── exp-output-merge.txt │ │ ├── main.tf │ │ ├── exp-output-import-dummy1.txt │ │ ├── exp-output-import-dummy2.txt │ │ └── exp-output-plan-again.txt │ │ ├── automerge │ │ ├── dir1 │ │ │ └── main.tf │ │ ├── dir2 │ │ │ └── main.tf │ │ ├── atlantis.yaml │ │ ├── exp-output-automerge.txt │ │ ├── exp-output-merge.txt │ │ ├── exp-output-apply-dir1.txt │ │ └── exp-output-apply-dir2.txt │ │ ├── policy-checks │ │ ├── atlantis.yaml │ │ ├── exp-output-approve-policies.txt │ │ ├── main.tf │ │ ├── exp-output-merge.txt │ │ ├── exp-output-apply-failed.txt │ │ ├── repos.yaml │ │ ├── exp-output-apply.txt │ │ ├── policies │ │ │ └── policy.rego │ │ └── exp-output-auto-policy-check.txt │ │ ├── import-multiple-project │ │ ├── atlantis.yaml │ │ ├── dir1 │ │ │ └── main.tf │ │ ├── dir2 │ │ │ └── main.tf │ │ ├── exp-output-import-multiple-projects.txt │ │ ├── exp-output-merge.txt │ │ └── exp-output-import-dummy1.txt │ │ ├── policy-checks-success-silent │ │ ├── main.tf │ │ ├── atlantis.yaml │ │ ├── exp-output-merge.txt │ │ ├── exp-output-apply.txt │ │ ├── repos.yaml │ │ ├── policies │ │ │ └── policy.rego │ │ └── exp-output-autoplan.txt │ │ ├── state-rm-multiple-project │ │ ├── atlantis.yaml │ │ ├── dir1 │ │ │ └── main.tf │ │ ├── dir2 │ │ │ └── main.tf │ │ ├── exp-output-merged.txt │ │ ├── exp-output-import-dummy1.txt │ │ ├── exp-output-import-dummy2.txt │ │ └── exp-output-state-rm-multiple-projects.txt │ │ ├── policy-checks-apply-reqs │ │ ├── atlantis.yaml │ │ ├── exp-output-approve-policies.txt │ │ ├── main.tf │ │ ├── exp-output-merge.txt │ │ ├── exp-output-apply-failed.txt │ │ ├── repos.yaml │ │ ├── exp-output-apply.txt │ │ ├── policies │ │ │ └── policy.rego │ │ └── exp-output-auto-policy-check.txt │ │ ├── policy-checks-diff-owner │ │ ├── atlantis.yaml │ │ ├── main.tf │ │ ├── exp-output-merge.txt │ │ ├── exp-output-apply-failed.txt │ │ ├── repos.yaml │ │ ├── policies │ │ │ └── policy.rego │ │ ├── exp-output-approve-policies.txt │ │ └── exp-output-auto-policy-check.txt │ │ ├── policy-checks-extra-args │ │ ├── atlantis.yaml │ │ ├── exp-output-approve-policies.txt │ │ ├── main.tf │ │ ├── exp-output-merge.txt │ │ ├── exp-output-apply-failed.txt │ │ ├── exp-output-apply.txt │ │ ├── repos.yaml │ │ └── policies │ │ │ └── policy.rego │ │ ├── policy-checks-multi-projects │ │ ├── atlantis.yaml │ │ ├── dir1 │ │ │ └── main.tf │ │ ├── dir2 │ │ │ └── main.tf │ │ ├── exp-output-merge.txt │ │ ├── repos.yaml │ │ ├── exp-output-apply.txt │ │ └── policies │ │ │ └── policy.rego │ │ ├── policy-checks-clear-approval │ │ ├── atlantis.yaml │ │ ├── exp-output-approve-policies-success.txt │ │ ├── exp-output-approve-policies.txt │ │ ├── main.tf │ │ ├── exp-output-merge.txt │ │ ├── exp-output-apply-failed.txt │ │ ├── repos.yaml │ │ ├── exp-output-apply.txt │ │ ├── policies │ │ │ └── policy.rego │ │ ├── exp-output-approve-policies-clear.txt │ │ └── exp-output-auto-policy-check.txt │ │ ├── policy-checks-custom-run-steps │ │ ├── atlantis.yaml │ │ ├── exp-output-approve-policies.txt │ │ ├── main.tf │ │ ├── exp-output-apply-failed.txt │ │ ├── exp-output-merge.txt │ │ ├── exp-output-apply.txt │ │ ├── repos.yaml │ │ └── policies │ │ │ └── policy.rego │ │ ├── repo-config-file │ │ ├── infrastructure │ │ │ ├── staging │ │ │ │ └── main.tf │ │ │ ├── production │ │ │ │ └── main.tf │ │ │ └── custom-name-atlantis.yaml │ │ ├── exp-output-merge.txt │ │ └── exp-output-apply.txt │ │ ├── import-workspace │ │ ├── atlantis.yaml │ │ ├── exp-output-merge.txt │ │ ├── dir1 │ │ │ └── main.tf │ │ ├── exp-output-import-dir1-ops-dummy1.txt │ │ ├── exp-output-import-dir1-ops-dummy2.txt │ │ └── exp-output-plan.txt │ │ ├── policy-checks-disabled-previous-match │ │ ├── atlantis.yaml │ │ ├── exp-output-approve-policies.txt │ │ ├── main.tf │ │ ├── exp-output-apply-failed.txt │ │ ├── exp-output-merge.txt │ │ ├── exp-output-apply.txt │ │ ├── repos.yaml │ │ ├── policies │ │ │ └── policy.rego │ │ └── exp-output-auto-policy-check.txt │ │ ├── policy-checks-disabled-repo-server-side │ │ ├── atlantis.yaml │ │ ├── exp-output-approve-policies.txt │ │ ├── main.tf │ │ ├── exp-output-merge.txt │ │ ├── exp-output-apply-failed.txt │ │ ├── exp-output-apply.txt │ │ ├── repos.yaml │ │ └── policies │ │ │ └── policy.rego │ │ ├── policy-checks-enabled-repo-server-side │ │ ├── atlantis.yaml │ │ ├── exp-output-approve-policies.txt │ │ ├── main.tf │ │ ├── exp-output-merge.txt │ │ ├── exp-output-apply-failed.txt │ │ ├── exp-output-apply.txt │ │ ├── repos.yaml │ │ └── policies │ │ │ └── policy.rego │ │ ├── state-rm-workspace │ │ ├── atlantis.yaml │ │ ├── exp-output-merge.txt │ │ ├── dir1 │ │ │ └── main.tf │ │ ├── exp-output-state-rm-dummy1.txt │ │ ├── exp-output-import-dummy1.txt │ │ └── exp-output-plan.txt │ │ ├── policy-checks-enabled-repo │ │ ├── atlantis.yaml │ │ ├── exp-output-approve-policies.txt │ │ ├── main.tf │ │ ├── exp-output-apply-failed.txt │ │ ├── exp-output-merge.txt │ │ ├── repos.yaml │ │ ├── exp-output-apply.txt │ │ ├── policies │ │ │ └── policy.rego │ │ └── exp-output-auto-policy-check.txt │ │ ├── policy-checks-disabled-repo │ │ ├── atlantis.yaml │ │ ├── exp-output-approve-policies.txt │ │ ├── main.tf │ │ ├── exp-output-apply-failed.txt │ │ ├── exp-output-merge.txt │ │ ├── repos.yaml │ │ ├── exp-output-apply.txt │ │ ├── policies │ │ │ └── policy.rego │ │ └── exp-output-auto-policy-check.txt │ │ ├── workspace-parallel-yaml │ │ ├── production │ │ │ └── main.tf │ │ ├── staging │ │ │ └── main.tf │ │ ├── exp-output-merge.txt │ │ ├── exp-output-apply-all-staging.txt │ │ ├── exp-output-apply-all-production.txt │ │ └── atlantis.yaml │ │ ├── server-side-cfg │ │ ├── main.tf │ │ ├── atlantis.yaml │ │ ├── exp-output-merge.txt │ │ ├── exp-output-apply-default-workspace.txt │ │ ├── exp-output-apply-staging-workspace.txt │ │ └── repos.yaml │ │ ├── simple │ │ ├── exp-output-merge.txt │ │ ├── exp-output-merge-workspaces.txt │ │ ├── exp-output-allow-command-unknown-import.txt │ │ ├── main.tf │ │ ├── exp-output-apply.txt │ │ ├── exp-output-apply-var.txt │ │ ├── exp-output-apply-var-default-workspace.txt │ │ ├── exp-output-apply-var-new-workspace.txt │ │ ├── exp-output-auto-policy-check.txt │ │ └── exp-output-apply-var-all.txt │ │ ├── modules │ │ ├── staging │ │ │ └── main.tf │ │ ├── production │ │ │ └── main.tf │ │ ├── exp-output-merge-only-staging.txt │ │ ├── exp-output-merge.txt │ │ ├── exp-output-merge-all-dirs.txt │ │ ├── modules │ │ │ └── null │ │ │ │ └── main.tf │ │ ├── exp-output-apply-staging.txt │ │ └── exp-output-apply-production.txt │ │ ├── modules-yaml │ │ ├── staging │ │ │ └── main.tf │ │ ├── production │ │ │ └── main.tf │ │ ├── exp-output-merge-only-staging.txt │ │ ├── exp-output-merge.txt │ │ ├── modules │ │ │ └── null │ │ │ │ └── main.tf │ │ ├── atlantis.yaml │ │ ├── exp-output-merge-all-dirs.txt │ │ ├── exp-output-apply-staging.txt │ │ ├── exp-output-apply-production.txt │ │ ├── exp-output-plan-staging.txt │ │ └── exp-output-plan-production.txt │ │ ├── state-rm-single-project │ │ ├── exp-output-merged.txt │ │ ├── exp-output-state-rm-foreach.txt │ │ ├── main.tf │ │ ├── exp-output-state-rm-multiple.txt │ │ ├── exp-output-import-simple.txt │ │ ├── exp-output-import-count.txt │ │ ├── exp-output-import-foreach.txt │ │ └── exp-output-plan.txt │ │ ├── import-single-project-var │ │ ├── exp-output-merge.txt │ │ ├── main.tf │ │ ├── exp-output-import-count.txt │ │ ├── exp-output-import-foreach.txt │ │ └── exp-output-plan-again.txt │ │ └── simple-with-lockfile │ │ └── main.tf ├── static │ └── images │ │ ├── atlantis-icon.png │ │ └── atlantis-icon_512.png ├── metrics │ ├── counter.go │ ├── common.go │ ├── counter_test.go │ └── scope_test.go ├── core │ ├── config │ │ ├── valid │ │ │ └── valid.go │ │ └── raw │ │ │ ├── raw_test.go │ │ │ ├── stage.go │ │ │ └── raw.go │ └── runtime │ │ ├── pull_approved_checker.go │ │ ├── version_step_runner.go │ │ ├── models │ │ └── filepath.go │ │ └── executor.go ├── logging │ └── log.go ├── utils │ ├── slices.go │ └── spellcheck.go └── scheduled │ ├── runtime_stats_test.go │ └── executor_service_test.go ├── runatlantis.io ├── terraform │ └── versions.tf ├── docs │ ├── images │ │ ├── plan.png │ │ ├── status.png │ │ ├── automerge.png │ │ ├── locks-ui.png │ │ ├── plan_output.png │ │ ├── lock-comment.png │ │ ├── lock-detail-ui.png │ │ ├── merge-strategy.png │ │ ├── branch-strategy.png │ │ ├── example-comment.png │ │ ├── pr-comment-help.png │ │ ├── apply-requirement.png │ │ ├── lock-delete-comment.png │ │ ├── policy-check-approval.png │ │ ├── policy-check-apply-failure.png │ │ └── policy-check-apply-status-failure.png │ ├── apply-requirements.md │ ├── how-atlantis-works.md │ ├── README.md │ ├── streaming-logs.md │ ├── configuring-atlantis.md │ └── installation-guide.md ├── .vuepress │ ├── public │ │ ├── hero.png │ │ ├── favicon.ico │ │ ├── favicon-128.png │ │ ├── favicon-16x16.png │ │ ├── favicon-32x32.png │ │ ├── favicon-96x96.png │ │ ├── mstile-144x144.png │ │ ├── mstile-150x150.png │ │ ├── mstile-310x150.png │ │ ├── mstile-310x310.png │ │ ├── mstile-70x70.png │ │ ├── workflow-min.png │ │ ├── favicon-196x196.png │ │ ├── _redirects │ │ ├── mobile-workflow-min.png │ │ ├── apple-touch-icon-114x114.png │ │ ├── apple-touch-icon-120x120.png │ │ ├── apple-touch-icon-144x144.png │ │ ├── apple-touch-icon-152x152.png │ │ ├── apple-touch-icon-57x57.png │ │ ├── apple-touch-icon-60x60.png │ │ ├── apple-touch-icon-72x72.png │ │ ├── apple-touch-icon-76x76.png │ │ ├── checkmark.svg │ │ ├── powerful.svg │ │ ├── hightower-super-dope.svg │ │ └── coding.svg │ ├── styles │ │ └── palette.scss │ └── theme │ │ └── index.js ├── guide │ ├── images │ │ ├── bitbucket-webhook.png │ │ ├── atlantis-walkthrough-icon.png │ │ └── bitbucket-server-webhook.png │ └── test-drive.md └── README.md ├── Dockerfile.dev ├── kustomize └── kustomization.yaml ├── testing ├── hooks │ └── post_push ├── http.go └── README.md ├── .dockerignore ├── CODEOWNERS ├── scripts ├── go-generate.sh ├── coverage.sh └── e2e-deps.sh ├── SECURITY.md ├── .gitattributes ├── .codecov.yml ├── .golangci.yml ├── package.json ├── .gitignore ├── .github ├── workflows │ ├── pr-lint.yml │ ├── renovate-config.yml │ ├── labeler.yml │ ├── lint.yml │ ├── stale.yml │ ├── atlantis-image-required.yml │ ├── test.yml │ ├── lint-required.yml │ ├── website-required.yml │ ├── test-required.yml │ └── codeql-required.yml ├── labeler.yml ├── release.yml └── PULL_REQUEST_TEMPLATE.md ├── cmd ├── cmd.go └── root.go ├── docs └── adr │ └── 0001-record-architecture-decisions.md └── .circleci └── config.yml /.adr-dir: -------------------------------------------------------------------------------- 1 | docs/adr 2 | -------------------------------------------------------------------------------- /.node-version: -------------------------------------------------------------------------------- 1 | 18.17.1 2 | -------------------------------------------------------------------------------- /e2e/.gitignore: -------------------------------------------------------------------------------- 1 | atlantis-tests 2 | -------------------------------------------------------------------------------- /server/events/testdata/fs/repoA/baz/init.tf: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /server/events/vcs/vcs.go: -------------------------------------------------------------------------------- 1 | package vcs 2 | -------------------------------------------------------------------------------- /server/events/testdata/fs/repoA/qux/quxx/init.tf: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /server/events/testdata/fs/repoB/dev/quxx/init.tf: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /server/events/testdata/fs/repoA/modules/bar/bar.tf: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /server/events/testdata/fs/repoA/modules/foo/foo.tf: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /server/events/testdata/fs/repoB/modules/bar/bar.tf: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /server/events/testdata/fs/repoB/modules/foo/foo.tf: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /server/events/testdata/fs/repoB/prod/quxx/init.tf: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /e2e/.gitconfig: -------------------------------------------------------------------------------- 1 | [user] 2 | name = atlantisbot 3 | email = lkysow+atlantis@gmail.com -------------------------------------------------------------------------------- /server/events/vcs/bitbucketserver/bitbucketserver.go: -------------------------------------------------------------------------------- 1 | package bitbucketserver 2 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/simple-yaml/staging.tfvars: -------------------------------------------------------------------------------- 1 | var= "fromfile" -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/tfvars-yaml/default.tfvars: -------------------------------------------------------------------------------- 1 | var = "default" -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/tfvars-yaml/staging.tfvars: -------------------------------------------------------------------------------- 1 | var = "staging" -------------------------------------------------------------------------------- /runatlantis.io/terraform/versions.tf: -------------------------------------------------------------------------------- 1 | 2 | terraform { 3 | required_version = ">= 0.12" 4 | } 5 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/tfvars-yaml-no-autoplan/default.tfvars: -------------------------------------------------------------------------------- 1 | var = "default" -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/tfvars-yaml-no-autoplan/staging.tfvars: -------------------------------------------------------------------------------- 1 | var = "staging" -------------------------------------------------------------------------------- /server/events/testdata/fs/repoA/baz/mods.tf: -------------------------------------------------------------------------------- 1 | module "bar" { 2 | source = "../modules/bar" 3 | } 4 | -------------------------------------------------------------------------------- /server/events/testdata/fs/repoA/modules/foo/mods.tf: -------------------------------------------------------------------------------- 1 | module "bar" { 2 | source = "../bar" 3 | } 4 | -------------------------------------------------------------------------------- /server/events/testdata/fs/repoA/qux/quxx/mods.tf: -------------------------------------------------------------------------------- 1 | module "foo" { 2 | source = "../../modules/foo" 3 | } -------------------------------------------------------------------------------- /server/events/testdata/fs/repoB/modules/foo/mods.tf: -------------------------------------------------------------------------------- 1 | module "bar" { 2 | source = "../bar" 3 | } 4 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/tfvars-yaml/default.backend.tfvars: -------------------------------------------------------------------------------- 1 | path = "default.tfstate" -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/tfvars-yaml/staging.backend.tfvars: -------------------------------------------------------------------------------- 1 | path = "staging.tfstate" -------------------------------------------------------------------------------- /server/events/testdata/fs/repoB/dev/quxx/mods.tf: -------------------------------------------------------------------------------- 1 | module "foo" { 2 | source = "../../modules/foo" 3 | } 4 | -------------------------------------------------------------------------------- /server/events/testdata/fs/repoB/prod/quxx/mods.tf: -------------------------------------------------------------------------------- 1 | module "foo" { 2 | source = "../../modules/foo" 3 | } -------------------------------------------------------------------------------- /server/events/testdata/test-repos/no-cloud-block/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">=1.2" 3 | } 4 | -------------------------------------------------------------------------------- /runatlantis.io/docs/images/plan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/atlantis/main/runatlantis.io/docs/images/plan.png -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/tfvars-yaml-no-autoplan/default.backend.tfvars: -------------------------------------------------------------------------------- 1 | path = "default.tfstate" -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/tfvars-yaml-no-autoplan/staging.backend.tfvars: -------------------------------------------------------------------------------- 1 | path = "staging.tfstate" -------------------------------------------------------------------------------- /runatlantis.io/docs/images/status.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/atlantis/main/runatlantis.io/docs/images/status.png -------------------------------------------------------------------------------- /Dockerfile.dev: -------------------------------------------------------------------------------- 1 | FROM ghcr.io/runatlantis/atlantis:latest 2 | COPY atlantis /usr/local/bin/atlantis 3 | WORKDIR /atlantis/src 4 | -------------------------------------------------------------------------------- /runatlantis.io/.vuepress/public/hero.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/atlantis/main/runatlantis.io/.vuepress/public/hero.png -------------------------------------------------------------------------------- /runatlantis.io/docs/images/automerge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/atlantis/main/runatlantis.io/docs/images/automerge.png -------------------------------------------------------------------------------- /runatlantis.io/docs/images/locks-ui.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/atlantis/main/runatlantis.io/docs/images/locks-ui.png -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/import-single-project/exp-output-apply-no-projects.txt: -------------------------------------------------------------------------------- 1 | Ran Apply for 0 projects: -------------------------------------------------------------------------------- /server/static/images/atlantis-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/atlantis/main/server/static/images/atlantis-icon.png -------------------------------------------------------------------------------- /kustomize/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kustomize.config.k8s.io/v1beta1 2 | kind: Kustomization 3 | resources: 4 | - bundle.yaml 5 | -------------------------------------------------------------------------------- /runatlantis.io/docs/images/plan_output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/atlantis/main/runatlantis.io/docs/images/plan_output.png -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/automerge/dir1/main.tf: -------------------------------------------------------------------------------- 1 | resource "null_resource" "automerge" { 2 | count = 1 3 | } 4 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/automerge/dir2/main.tf: -------------------------------------------------------------------------------- 1 | resource "null_resource" "automerge" { 2 | count = 1 3 | } 4 | -------------------------------------------------------------------------------- /server/static/images/atlantis-icon_512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/atlantis/main/server/static/images/atlantis-icon_512.png -------------------------------------------------------------------------------- /runatlantis.io/.vuepress/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/atlantis/main/runatlantis.io/.vuepress/public/favicon.ico -------------------------------------------------------------------------------- /runatlantis.io/docs/images/lock-comment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/atlantis/main/runatlantis.io/docs/images/lock-comment.png -------------------------------------------------------------------------------- /runatlantis.io/docs/images/lock-detail-ui.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/atlantis/main/runatlantis.io/docs/images/lock-detail-ui.png -------------------------------------------------------------------------------- /runatlantis.io/docs/images/merge-strategy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/atlantis/main/runatlantis.io/docs/images/merge-strategy.png -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/simple-yaml/exp-output-apply-locked.txt: -------------------------------------------------------------------------------- 1 | **Error:** Running `atlantis apply` is disabled. 2 | -------------------------------------------------------------------------------- /runatlantis.io/.vuepress/public/favicon-128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/atlantis/main/runatlantis.io/.vuepress/public/favicon-128.png -------------------------------------------------------------------------------- /runatlantis.io/docs/images/branch-strategy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/atlantis/main/runatlantis.io/docs/images/branch-strategy.png -------------------------------------------------------------------------------- /runatlantis.io/docs/images/example-comment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/atlantis/main/runatlantis.io/docs/images/example-comment.png -------------------------------------------------------------------------------- /runatlantis.io/docs/images/pr-comment-help.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/atlantis/main/runatlantis.io/docs/images/pr-comment-help.png -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks/atlantis.yaml: -------------------------------------------------------------------------------- 1 | version: 3 2 | projects: 3 | - dir: . 4 | workspace: default 5 | -------------------------------------------------------------------------------- /testing/hooks/post_push: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | docker tag $IMAGE_NAME $DOCKER_REPO:$SOURCE_COMMIT 4 | docker push $DOCKER_REPO:$SOURCE_COMMIT 5 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | * 2 | !cmd/ 3 | !server/ 4 | !testdrive/ 5 | !main.go 6 | !go.mod 7 | !go.sum 8 | !docker-entrypoint.sh 9 | !atlantis 10 | -------------------------------------------------------------------------------- /runatlantis.io/.vuepress/public/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/atlantis/main/runatlantis.io/.vuepress/public/favicon-16x16.png -------------------------------------------------------------------------------- /runatlantis.io/.vuepress/public/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/atlantis/main/runatlantis.io/.vuepress/public/favicon-32x32.png -------------------------------------------------------------------------------- /runatlantis.io/.vuepress/public/favicon-96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/atlantis/main/runatlantis.io/.vuepress/public/favicon-96x96.png -------------------------------------------------------------------------------- /runatlantis.io/.vuepress/public/mstile-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/atlantis/main/runatlantis.io/.vuepress/public/mstile-144x144.png -------------------------------------------------------------------------------- /runatlantis.io/.vuepress/public/mstile-150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/atlantis/main/runatlantis.io/.vuepress/public/mstile-150x150.png -------------------------------------------------------------------------------- /runatlantis.io/.vuepress/public/mstile-310x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/atlantis/main/runatlantis.io/.vuepress/public/mstile-310x150.png -------------------------------------------------------------------------------- /runatlantis.io/.vuepress/public/mstile-310x310.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/atlantis/main/runatlantis.io/.vuepress/public/mstile-310x310.png -------------------------------------------------------------------------------- /runatlantis.io/.vuepress/public/mstile-70x70.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/atlantis/main/runatlantis.io/.vuepress/public/mstile-70x70.png -------------------------------------------------------------------------------- /runatlantis.io/.vuepress/public/workflow-min.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/atlantis/main/runatlantis.io/.vuepress/public/workflow-min.png -------------------------------------------------------------------------------- /runatlantis.io/docs/images/apply-requirement.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/atlantis/main/runatlantis.io/docs/images/apply-requirement.png -------------------------------------------------------------------------------- /runatlantis.io/docs/images/lock-delete-comment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/atlantis/main/runatlantis.io/docs/images/lock-delete-comment.png -------------------------------------------------------------------------------- /runatlantis.io/guide/images/bitbucket-webhook.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/atlantis/main/runatlantis.io/guide/images/bitbucket-webhook.png -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/import-multiple-project/atlantis.yaml: -------------------------------------------------------------------------------- 1 | version: 3 2 | projects: 3 | - dir: dir1 4 | - dir: dir2 5 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-success-silent/main.tf: -------------------------------------------------------------------------------- 1 | output "workspace" { 2 | value = terraform.workspace 3 | } 4 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/state-rm-multiple-project/atlantis.yaml: -------------------------------------------------------------------------------- 1 | version: 3 2 | projects: 3 | - dir: dir1 4 | - dir: dir2 5 | -------------------------------------------------------------------------------- /server/events/templates/apply_unwrapped_success.tmpl: -------------------------------------------------------------------------------- 1 | {{ define "applyUnwrappedSuccess" -}} 2 | ```diff 3 | {{ .Output }} 4 | ``` 5 | {{ end -}} 6 | -------------------------------------------------------------------------------- /server/events/templates/version_unwrapped_success.tmpl: -------------------------------------------------------------------------------- 1 | {{ define "versionUnwrappedSuccess" -}} 2 | ``` 3 | {{ .Output }} 4 | ``` 5 | {{ end }} 6 | -------------------------------------------------------------------------------- /runatlantis.io/.vuepress/public/favicon-196x196.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/atlantis/main/runatlantis.io/.vuepress/public/favicon-196x196.png -------------------------------------------------------------------------------- /runatlantis.io/.vuepress/styles/palette.scss: -------------------------------------------------------------------------------- 1 | $accentColor: #0074db; 2 | $textColor: #2c3e50; 3 | $borderColor: #eaecef; 4 | $codeBgColor: #282c34; 5 | -------------------------------------------------------------------------------- /runatlantis.io/docs/images/policy-check-approval.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/atlantis/main/runatlantis.io/docs/images/policy-check-approval.png -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/automerge/atlantis.yaml: -------------------------------------------------------------------------------- 1 | version: 3 2 | automerge: true 3 | projects: 4 | - dir: dir1 5 | - dir: dir2 6 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-apply-reqs/atlantis.yaml: -------------------------------------------------------------------------------- 1 | version: 3 2 | projects: 3 | - dir: . 4 | workspace: default 5 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-diff-owner/atlantis.yaml: -------------------------------------------------------------------------------- 1 | version: 3 2 | projects: 3 | - dir: . 4 | workspace: default 5 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-extra-args/atlantis.yaml: -------------------------------------------------------------------------------- 1 | version: 3 2 | projects: 3 | - dir: . 4 | workspace: default 5 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-multi-projects/atlantis.yaml: -------------------------------------------------------------------------------- 1 | version: 3 2 | projects: 3 | - dir: dir1 4 | - dir: dir2 5 | -------------------------------------------------------------------------------- /runatlantis.io/.vuepress/public/_redirects: -------------------------------------------------------------------------------- 1 | /guide/getting-started.html /guide/ 2 | /docs/atlantis-yaml-reference.html /docs/repo-level-atlantis-yaml.html 3 | -------------------------------------------------------------------------------- /runatlantis.io/.vuepress/public/mobile-workflow-min.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/atlantis/main/runatlantis.io/.vuepress/public/mobile-workflow-min.png -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/automerge/exp-output-automerge.txt: -------------------------------------------------------------------------------- 1 | Automatically merging because all plans have been successfully applied. 2 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-clear-approval/atlantis.yaml: -------------------------------------------------------------------------------- 1 | version: 3 2 | projects: 3 | - dir: . 4 | workspace: default 5 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-custom-run-steps/atlantis.yaml: -------------------------------------------------------------------------------- 1 | version: 3 2 | projects: 3 | - dir: . 4 | workspace: default 5 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-success-silent/atlantis.yaml: -------------------------------------------------------------------------------- 1 | version: 3 2 | projects: 3 | - dir: . 4 | workspace: default 5 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/repo-config-file/infrastructure/staging/main.tf: -------------------------------------------------------------------------------- 1 | resource "null_resource" "staging" { 2 | count = "1" 3 | } 4 | -------------------------------------------------------------------------------- /server/events/templates/failure_with_log.tmpl: -------------------------------------------------------------------------------- 1 | {{ define "failureWithLog" -}} 2 | {{ template "failure" . -}} 3 | {{- template "log" . -}} 4 | {{ end -}} 5 | -------------------------------------------------------------------------------- /runatlantis.io/docs/images/policy-check-apply-failure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/atlantis/main/runatlantis.io/docs/images/policy-check-apply-failure.png -------------------------------------------------------------------------------- /runatlantis.io/guide/images/atlantis-walkthrough-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/atlantis/main/runatlantis.io/guide/images/atlantis-walkthrough-icon.png -------------------------------------------------------------------------------- /runatlantis.io/guide/images/bitbucket-server-webhook.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/atlantis/main/runatlantis.io/guide/images/bitbucket-server-webhook.png -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/import-workspace/atlantis.yaml: -------------------------------------------------------------------------------- 1 | version: 3 2 | projects: 3 | - name: dir1-ops 4 | dir: dir1 5 | workspace: ops 6 | -------------------------------------------------------------------------------- /runatlantis.io/.vuepress/public/apple-touch-icon-114x114.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/atlantis/main/runatlantis.io/.vuepress/public/apple-touch-icon-114x114.png -------------------------------------------------------------------------------- /runatlantis.io/.vuepress/public/apple-touch-icon-120x120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/atlantis/main/runatlantis.io/.vuepress/public/apple-touch-icon-120x120.png -------------------------------------------------------------------------------- /runatlantis.io/.vuepress/public/apple-touch-icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/atlantis/main/runatlantis.io/.vuepress/public/apple-touch-icon-144x144.png -------------------------------------------------------------------------------- /runatlantis.io/.vuepress/public/apple-touch-icon-152x152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/atlantis/main/runatlantis.io/.vuepress/public/apple-touch-icon-152x152.png -------------------------------------------------------------------------------- /runatlantis.io/.vuepress/public/apple-touch-icon-57x57.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/atlantis/main/runatlantis.io/.vuepress/public/apple-touch-icon-57x57.png -------------------------------------------------------------------------------- /runatlantis.io/.vuepress/public/apple-touch-icon-60x60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/atlantis/main/runatlantis.io/.vuepress/public/apple-touch-icon-60x60.png -------------------------------------------------------------------------------- /runatlantis.io/.vuepress/public/apple-touch-icon-72x72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/atlantis/main/runatlantis.io/.vuepress/public/apple-touch-icon-72x72.png -------------------------------------------------------------------------------- /runatlantis.io/.vuepress/public/apple-touch-icon-76x76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/atlantis/main/runatlantis.io/.vuepress/public/apple-touch-icon-76x76.png -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-disabled-previous-match/atlantis.yaml: -------------------------------------------------------------------------------- 1 | version: 3 2 | projects: 3 | - dir: . 4 | workspace: default 5 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-disabled-repo-server-side/atlantis.yaml: -------------------------------------------------------------------------------- 1 | version: 3 2 | projects: 3 | - dir: . 4 | workspace: default 5 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-enabled-repo-server-side/atlantis.yaml: -------------------------------------------------------------------------------- 1 | version: 3 2 | projects: 3 | - dir: . 4 | workspace: default 5 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/repo-config-file/infrastructure/production/main.tf: -------------------------------------------------------------------------------- 1 | resource "null_resource" "production" { 2 | count = "1" 3 | } 4 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/state-rm-workspace/atlantis.yaml: -------------------------------------------------------------------------------- 1 | version: 3 2 | projects: 3 | - name: dir1-ops 4 | dir: dir1 5 | workspace: ops 6 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/import-multiple-project/dir1/main.tf: -------------------------------------------------------------------------------- 1 | resource "random_id" "dummy1" { 2 | keepers = {} 3 | byte_length = 1 4 | } 5 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/import-multiple-project/dir2/main.tf: -------------------------------------------------------------------------------- 1 | resource "random_id" "dummy2" { 2 | keepers = {} 3 | byte_length = 1 4 | } 5 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/state-rm-multiple-project/dir1/main.tf: -------------------------------------------------------------------------------- 1 | resource "random_id" "dummy" { 2 | keepers = {} 3 | byte_length = 1 4 | } 5 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/state-rm-multiple-project/dir2/main.tf: -------------------------------------------------------------------------------- 1 | resource "random_id" "dummy" { 2 | keepers = {} 3 | byte_length = 1 4 | } 5 | -------------------------------------------------------------------------------- /server/events/templates/unwrapped_err_with_log.tmpl: -------------------------------------------------------------------------------- 1 | {{ define "unwrappedErrWithLog" -}} 2 | {{ template "unwrappedErr" . }} 3 | {{- template "log" . -}} 4 | {{ end -}} 5 | -------------------------------------------------------------------------------- /runatlantis.io/docs/images/policy-check-apply-status-failure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/atlantis/main/runatlantis.io/docs/images/policy-check-apply-status-failure.png -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-enabled-repo/atlantis.yaml: -------------------------------------------------------------------------------- 1 | version: 3 2 | projects: 3 | - dir: . 4 | workspace: default 5 | policy_check: true 6 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-disabled-repo/atlantis.yaml: -------------------------------------------------------------------------------- 1 | version: 3 2 | projects: 3 | - dir: . 4 | workspace: default 5 | policy_check: false 6 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks/exp-output-approve-policies.txt: -------------------------------------------------------------------------------- 1 | Approved Policies for 1 projects: 2 | 3 | 1. dir: `.` workspace: `default` 4 | 5 | 6 | -------------------------------------------------------------------------------- /runatlantis.io/docs/apply-requirements.md: -------------------------------------------------------------------------------- 1 | # Apply Requirements 2 | 3 | :::warning REDIRECT 4 | This page is moved to [Command Requirements](/docs/command-requirements.html). 5 | ::: 6 | -------------------------------------------------------------------------------- /server/events/templates/single_project_version_unsuccessful.tmpl: -------------------------------------------------------------------------------- 1 | {{ define "singleProjectVersionUnsuccessful" -}} 2 | {{ template "singleProjectPlanUnsuccessful" . }} 3 | {{ end -}} 4 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-apply-reqs/exp-output-approve-policies.txt: -------------------------------------------------------------------------------- 1 | Approved Policies for 1 projects: 2 | 3 | 1. dir: `.` workspace: `default` 4 | 5 | 6 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-clear-approval/exp-output-approve-policies-success.txt: -------------------------------------------------------------------------------- 1 | Approved Policies for 1 projects: 2 | 3 | 1. dir: `.` workspace: `default` -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-extra-args/exp-output-approve-policies.txt: -------------------------------------------------------------------------------- 1 | Approved Policies for 1 projects: 2 | 3 | 1. dir: `.` workspace: `default` 4 | 5 | 6 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-clear-approval/exp-output-approve-policies.txt: -------------------------------------------------------------------------------- 1 | Approved Policies for 1 projects: 2 | 3 | 1. dir: `.` workspace: `default` 4 | 5 | 6 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-custom-run-steps/exp-output-approve-policies.txt: -------------------------------------------------------------------------------- 1 | Approved Policies for 1 projects: 2 | 3 | 1. dir: `.` workspace: `default` 4 | 5 | 6 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-disabled-repo/exp-output-approve-policies.txt: -------------------------------------------------------------------------------- 1 | Approved Policies for 1 projects: 2 | 3 | 1. dir: `.` workspace: `default` 4 | 5 | 6 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-enabled-repo/exp-output-approve-policies.txt: -------------------------------------------------------------------------------- 1 | Approved Policies for 1 projects: 2 | 3 | 1. dir: `.` workspace: `default` 4 | 5 | 6 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/workspace-parallel-yaml/production/main.tf: -------------------------------------------------------------------------------- 1 | resource "null_resource" "this" { 2 | } 3 | output "workspace" { 4 | value = terraform.workspace 5 | } 6 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/workspace-parallel-yaml/staging/main.tf: -------------------------------------------------------------------------------- 1 | resource "null_resource" "this" { 2 | } 3 | output "workspace" { 4 | value = terraform.workspace 5 | } 6 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/import-multiple-project/exp-output-import-multiple-projects.txt: -------------------------------------------------------------------------------- 1 | **Import Failed**: import cannot run on multiple projects. please specify one project. 2 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks/main.tf: -------------------------------------------------------------------------------- 1 | resource "null_resource" "simple" { 2 | count = 1 3 | } 4 | 5 | output "workspace" { 6 | value = terraform.workspace 7 | } 8 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/repo-config-file/infrastructure/custom-name-atlantis.yaml: -------------------------------------------------------------------------------- 1 | version: 3 2 | projects: 3 | - dir: infrastructure/staging 4 | - dir: infrastructure/production 5 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/server-side-cfg/main.tf: -------------------------------------------------------------------------------- 1 | resource "null_resource" "simple" { 2 | count = 1 3 | } 4 | 5 | output "workspace" { 6 | value = terraform.workspace 7 | } 8 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/simple/exp-output-merge.txt: -------------------------------------------------------------------------------- 1 | Locks and plans deleted for the projects and workspaces modified in this pull request: 2 | 3 | - dir: `.` workspace: `default` -------------------------------------------------------------------------------- /server/events/templates/failure.tmpl: -------------------------------------------------------------------------------- 1 | {{ define "failure" -}} 2 | **{{ .Command }} Failed**: {{ .Failure }} 3 | {{- if ne .RenderedContext ""}} 4 | {{ .RenderedContext }} 5 | {{- end }} 6 | {{ end -}} 7 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/modules/staging/main.tf: -------------------------------------------------------------------------------- 1 | module "null" { 2 | source = "../modules/null" 3 | var = "staging" 4 | } 5 | output "var" { 6 | value = module.null.var 7 | } 8 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-disabled-previous-match/exp-output-approve-policies.txt: -------------------------------------------------------------------------------- 1 | Approved Policies for 1 projects: 2 | 3 | 1. dir: `.` workspace: `default` 4 | 5 | 6 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-disabled-repo-server-side/exp-output-approve-policies.txt: -------------------------------------------------------------------------------- 1 | Approved Policies for 1 projects: 2 | 3 | 1. dir: `.` workspace: `default` 4 | 5 | 6 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-enabled-repo-server-side/exp-output-approve-policies.txt: -------------------------------------------------------------------------------- 1 | Approved Policies for 1 projects: 2 | 3 | 1. dir: `.` workspace: `default` 4 | 5 | 6 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/server-side-cfg/atlantis.yaml: -------------------------------------------------------------------------------- 1 | version: 3 2 | projects: 3 | - dir: . 4 | workspace: default 5 | - dir: . 6 | workspace: staging 7 | workflow: staging 8 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/tfvars-yaml/exp-output-merge.txt: -------------------------------------------------------------------------------- 1 | Locks and plans deleted for the projects and workspaces modified in this pull request: 2 | 3 | - dir: `.` workspace: `default` -------------------------------------------------------------------------------- /server/metrics/counter.go: -------------------------------------------------------------------------------- 1 | package metrics 2 | 3 | import tally "github.com/uber-go/tally/v4" 4 | 5 | func InitCounter(scope tally.Scope, name string) { 6 | s := scope.Counter(name) 7 | s.Inc(0) 8 | } 9 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/import-workspace/exp-output-merge.txt: -------------------------------------------------------------------------------- 1 | Locks and plans deleted for the projects and workspaces modified in this pull request: 2 | 3 | - dir: `dir1` workspace: `ops` -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/modules-yaml/staging/main.tf: -------------------------------------------------------------------------------- 1 | module "null" { 2 | source = "../modules/null" 3 | var = "staging" 4 | } 5 | output "var" { 6 | value = module.null.var 7 | } 8 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-apply-reqs/main.tf: -------------------------------------------------------------------------------- 1 | resource "null_resource" "simple" { 2 | count = 1 3 | } 4 | 5 | output "workspace" { 6 | value = terraform.workspace 7 | } 8 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-diff-owner/main.tf: -------------------------------------------------------------------------------- 1 | resource "null_resource" "simple" { 2 | count = 1 3 | } 4 | 5 | output "workspace" { 6 | value = terraform.workspace 7 | } 8 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-disabled-repo/main.tf: -------------------------------------------------------------------------------- 1 | resource "null_resource" "simple" { 2 | count = 1 3 | } 4 | 5 | output "workspace" { 6 | value = terraform.workspace 7 | } 8 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-enabled-repo/main.tf: -------------------------------------------------------------------------------- 1 | resource "null_resource" "simple" { 2 | count = 1 3 | } 4 | 5 | output "workspace" { 6 | value = terraform.workspace 7 | } 8 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-extra-args/main.tf: -------------------------------------------------------------------------------- 1 | resource "null_resource" "simple" { 2 | count = 1 3 | } 4 | 5 | output "workspace" { 6 | value = terraform.workspace 7 | } 8 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks/exp-output-merge.txt: -------------------------------------------------------------------------------- 1 | Locks and plans deleted for the projects and workspaces modified in this pull request: 2 | 3 | - dir: `.` workspace: `default` 4 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/state-rm-workspace/exp-output-merge.txt: -------------------------------------------------------------------------------- 1 | Locks and plans deleted for the projects and workspaces modified in this pull request: 2 | 3 | - dir: `dir1` workspace: `ops` -------------------------------------------------------------------------------- /server/core/config/valid/valid.go: -------------------------------------------------------------------------------- 1 | // Package valid contains definitions of valid yaml configuration after its 2 | // been parsed and validated. 3 | package valid 4 | 5 | const DefaultAutoPlanEnabled = true 6 | -------------------------------------------------------------------------------- /server/events/templates/log.tmpl: -------------------------------------------------------------------------------- 1 | {{ define "log" -}} 2 | {{ if .Verbose }} 3 |
Log 4 |

5 | 6 | ``` 7 | {{.Log}}``` 8 |

9 | {{ end -}} 10 | {{ end -}} 11 | -------------------------------------------------------------------------------- /server/events/vcs/github_config.go: -------------------------------------------------------------------------------- 1 | package vcs 2 | 3 | // GithubConfig allows for custom github-specific functionality and behavior 4 | type GithubConfig struct { 5 | AllowMergeableBypassApply bool 6 | } 7 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/modules/production/main.tf: -------------------------------------------------------------------------------- 1 | module "null" { 2 | source = "../modules/null" 3 | var = "production" 4 | } 5 | output "var" { 6 | value = module.null.var 7 | } 8 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-clear-approval/main.tf: -------------------------------------------------------------------------------- 1 | resource "null_resource" "simple" { 2 | count = 1 3 | } 4 | 5 | output "workspace" { 6 | value = terraform.workspace 7 | } 8 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-custom-run-steps/main.tf: -------------------------------------------------------------------------------- 1 | resource "null_resource" "simple" { 2 | count = 1 3 | } 4 | 5 | output "workspace" { 6 | value = terraform.workspace 7 | } 8 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks/exp-output-apply-failed.txt: -------------------------------------------------------------------------------- 1 | Ran Apply for dir: `.` workspace: `default` 2 | 3 | **Apply Failed**: All policies must pass for project before running apply. -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/simple-yaml/exp-output-merge.txt: -------------------------------------------------------------------------------- 1 | Locks and plans deleted for the projects and workspaces modified in this pull request: 2 | 3 | - dir: `.` workspaces: `default`, `staging` -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/state-rm-single-project/exp-output-merged.txt: -------------------------------------------------------------------------------- 1 | Locks and plans deleted for the projects and workspaces modified in this pull request: 2 | 3 | - dir: `.` workspace: `default` -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/tfvars-yaml-no-autoplan/exp-output-merge.txt: -------------------------------------------------------------------------------- 1 | Locks and plans deleted for the projects and workspaces modified in this pull request: 2 | 3 | - dir: `.` workspace: `default` -------------------------------------------------------------------------------- /server/events/templates/apply_wrapped_success.tmpl: -------------------------------------------------------------------------------- 1 | {{ define "applyWrappedSuccess" -}} 2 |
Show Output 3 | 4 | {{ template "applyUnwrappedSuccess" . }} 5 |
6 | {{ end -}} 7 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/import-single-project/exp-output-merge.txt: -------------------------------------------------------------------------------- 1 | Locks and plans deleted for the projects and workspaces modified in this pull request: 2 | 3 | - dir: `.` workspace: `default` 4 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/modules-yaml/production/main.tf: -------------------------------------------------------------------------------- 1 | module "null" { 2 | source = "../modules/null" 3 | var = "production" 4 | } 5 | output "var" { 6 | value = module.null.var 7 | } 8 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/modules/exp-output-merge-only-staging.txt: -------------------------------------------------------------------------------- 1 | Locks and plans deleted for the projects and workspaces modified in this pull request: 2 | 3 | - dir: `staging` workspace: `default` -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-apply-reqs/exp-output-merge.txt: -------------------------------------------------------------------------------- 1 | Locks and plans deleted for the projects and workspaces modified in this pull request: 2 | 3 | - dir: `.` workspace: `default` 4 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-diff-owner/exp-output-merge.txt: -------------------------------------------------------------------------------- 1 | Locks and plans deleted for the projects and workspaces modified in this pull request: 2 | 3 | - dir: `.` workspace: `default` 4 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-disabled-previous-match/main.tf: -------------------------------------------------------------------------------- 1 | resource "null_resource" "simple" { 2 | count = 1 3 | } 4 | 5 | output "workspace" { 6 | value = terraform.workspace 7 | } 8 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-extra-args/exp-output-merge.txt: -------------------------------------------------------------------------------- 1 | Locks and plans deleted for the projects and workspaces modified in this pull request: 2 | 3 | - dir: `.` workspace: `default` 4 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-multi-projects/dir1/main.tf: -------------------------------------------------------------------------------- 1 | resource "null_resource" "simple" { 2 | count = 1 3 | } 4 | 5 | output "workspace" { 6 | value = terraform.workspace 7 | } 8 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-multi-projects/dir2/main.tf: -------------------------------------------------------------------------------- 1 | resource "null_resource" "forbidden" { 2 | count = 1 3 | } 4 | 5 | output "workspace" { 6 | value = terraform.workspace 7 | } 8 | -------------------------------------------------------------------------------- /server/events/templates/diverged.tmpl: -------------------------------------------------------------------------------- 1 | {{ define "diverged" -}} 2 | {{ if .HasDiverged }} 3 | :warning: The branch we're merging into is ahead, it is recommended to pull new commits first. 4 | {{ end -}} 5 | {{ end -}} 6 | -------------------------------------------------------------------------------- /server/events/templates/version_wrapped_success.tmpl: -------------------------------------------------------------------------------- 1 | {{ define "versionWrappedSuccess" -}} 2 |
Show Output 3 | 4 | {{ template "versionUnwrappedSuccess" . }} 5 |
6 | {{ end -}} 7 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/import-single-project-var/exp-output-merge.txt: -------------------------------------------------------------------------------- 1 | Locks and plans deleted for the projects and workspaces modified in this pull request: 2 | 3 | - dir: `.` workspace: `default` 4 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-apply-reqs/exp-output-apply-failed.txt: -------------------------------------------------------------------------------- 1 | Ran Apply for dir: `.` workspace: `default` 2 | 3 | **Apply Failed**: All policies must pass for project before running apply. -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-clear-approval/exp-output-merge.txt: -------------------------------------------------------------------------------- 1 | Locks and plans deleted for the projects and workspaces modified in this pull request: 2 | 3 | - dir: `.` workspace: `default` 4 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-diff-owner/exp-output-apply-failed.txt: -------------------------------------------------------------------------------- 1 | Ran Apply for dir: `.` workspace: `default` 2 | 3 | **Apply Failed**: All policies must pass for project before running apply. -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-disabled-repo-server-side/main.tf: -------------------------------------------------------------------------------- 1 | resource "null_resource" "simple" { 2 | count = 1 3 | } 4 | 5 | output "workspace" { 6 | value = terraform.workspace 7 | } 8 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-disabled-repo/exp-output-apply-failed.txt: -------------------------------------------------------------------------------- 1 | Ran Apply for dir: `.` workspace: `default` 2 | 3 | **Apply Failed**: All policies must pass for project before running apply. -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-disabled-repo/exp-output-merge.txt: -------------------------------------------------------------------------------- 1 | Locks and plans deleted for the projects and workspaces modified in this pull request: 2 | 3 | - dir: `.` workspace: `default` 4 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-enabled-repo-server-side/main.tf: -------------------------------------------------------------------------------- 1 | resource "null_resource" "simple" { 2 | count = 1 3 | } 4 | 5 | output "workspace" { 6 | value = terraform.workspace 7 | } 8 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-enabled-repo/exp-output-apply-failed.txt: -------------------------------------------------------------------------------- 1 | Ran Apply for dir: `.` workspace: `default` 2 | 3 | **Apply Failed**: All policies must pass for project before running apply. -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-enabled-repo/exp-output-merge.txt: -------------------------------------------------------------------------------- 1 | Locks and plans deleted for the projects and workspaces modified in this pull request: 2 | 3 | - dir: `.` workspace: `default` 4 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-extra-args/exp-output-apply-failed.txt: -------------------------------------------------------------------------------- 1 | Ran Apply for dir: `.` workspace: `default` 2 | 3 | **Apply Failed**: All policies must pass for project before running apply. -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-success-silent/exp-output-merge.txt: -------------------------------------------------------------------------------- 1 | Locks and plans deleted for the projects and workspaces modified in this pull request: 2 | 3 | - dir: `.` workspace: `default` 4 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/server-side-cfg/exp-output-merge.txt: -------------------------------------------------------------------------------- 1 | Locks and plans deleted for the projects and workspaces modified in this pull request: 2 | 3 | - dir: `.` workspaces: `default`, `staging` 4 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-clear-approval/exp-output-apply-failed.txt: -------------------------------------------------------------------------------- 1 | Ran Apply for dir: `.` workspace: `default` 2 | 3 | **Apply Failed**: All policies must pass for project before running apply. -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-custom-run-steps/exp-output-apply-failed.txt: -------------------------------------------------------------------------------- 1 | Ran Apply for dir: `.` workspace: `default` 2 | 3 | **Apply Failed**: All policies must pass for project before running apply. -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-custom-run-steps/exp-output-merge.txt: -------------------------------------------------------------------------------- 1 | Locks and plans deleted for the projects and workspaces modified in this pull request: 2 | 3 | - dir: `.` workspace: `default` 4 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/simple/exp-output-merge-workspaces.txt: -------------------------------------------------------------------------------- 1 | Locks and plans deleted for the projects and workspaces modified in this pull request: 2 | 3 | - dir: `.` workspaces: `default`, `new_workspace` -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-disabled-previous-match/exp-output-apply-failed.txt: -------------------------------------------------------------------------------- 1 | Ran Apply for dir: `.` workspace: `default` 2 | 3 | **Apply Failed**: All policies must pass for project before running apply. -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-disabled-previous-match/exp-output-merge.txt: -------------------------------------------------------------------------------- 1 | Locks and plans deleted for the projects and workspaces modified in this pull request: 2 | 3 | - dir: `.` workspace: `default` 4 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-disabled-repo-server-side/exp-output-merge.txt: -------------------------------------------------------------------------------- 1 | Locks and plans deleted for the projects and workspaces modified in this pull request: 2 | 3 | - dir: `.` workspace: `default` 4 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-enabled-repo-server-side/exp-output-merge.txt: -------------------------------------------------------------------------------- 1 | Locks and plans deleted for the projects and workspaces modified in this pull request: 2 | 3 | - dir: `.` workspace: `default` 4 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/simple/exp-output-allow-command-unknown-import.txt: -------------------------------------------------------------------------------- 1 | ``` 2 | Error: unknown command "import". 3 | Run 'atlantis --help' for usage. 4 | Available commands(--allow-commands): plan, apply 5 | ``` -------------------------------------------------------------------------------- /server/events/templates/unwrapped_err.tmpl: -------------------------------------------------------------------------------- 1 | {{ define "unwrappedErr" -}} 2 | **{{.Command}} Error** 3 | ``` 4 | {{.Error}} 5 | ``` 6 | {{- if ne .RenderedContext ""}} 7 | {{ .RenderedContext }} 8 | {{- end }} 9 | {{- end }} 10 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-disabled-repo-server-side/exp-output-apply-failed.txt: -------------------------------------------------------------------------------- 1 | Ran Apply for dir: `.` workspace: `default` 2 | 3 | **Apply Failed**: All policies must pass for project before running apply. -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-enabled-repo-server-side/exp-output-apply-failed.txt: -------------------------------------------------------------------------------- 1 | Ran Apply for dir: `.` workspace: `default` 2 | 3 | **Apply Failed**: All policies must pass for project before running apply. -------------------------------------------------------------------------------- /runatlantis.io/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | home: true 3 | pageClass: home-custom 4 | heroImage: /hero.png 5 | heroText: Atlantis 6 | actionText: Get Started → 7 | actionLink: /guide/ 8 | title: Terraform Pull Request Automation 9 | --- 10 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/modules/exp-output-merge.txt: -------------------------------------------------------------------------------- 1 | Locks and plans deleted for the projects and workspaces modified in this pull request: 2 | 3 | - dir: `staging` workspace: `default` 4 | - dir: `.` workspace: `default` 5 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/automerge/exp-output-merge.txt: -------------------------------------------------------------------------------- 1 | Locks and plans deleted for the projects and workspaces modified in this pull request: 2 | 3 | - dir: `dir1` workspace: `default` 4 | - dir: `dir2` workspace: `default` 5 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/modules-yaml/exp-output-merge-only-staging.txt: -------------------------------------------------------------------------------- 1 | Locks and plans deleted for the projects and workspaces modified in this pull request: 2 | 3 | - path: `runatlantis/atlantis-tests/staging` workspace: `default` -------------------------------------------------------------------------------- /server/events/testdata/test-repos/workspace-configured/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">=1.2" 3 | cloud { 4 | organization = "atlantis-test" 5 | workspaces { 6 | name = "test-workspace" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | # https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners 2 | # These owners will be the default owners for everything in the repo. 3 | * @runatlantis/maintainers 4 | -------------------------------------------------------------------------------- /runatlantis.io/.vuepress/theme/index.js: -------------------------------------------------------------------------------- 1 | // introduce custom home with navbar 2 | // https://stackoverflow.com/a/60220684 3 | // https://vuepress.vuejs.org/theme/inheritance.html#usage 4 | module.exports = { 5 | extend: '@vuepress/theme-default' 6 | } 7 | -------------------------------------------------------------------------------- /scripts/go-generate.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -eou pipefail 4 | 5 | pkgs=$(go list ./... | grep -v mocks | grep -v matchers | grep -v e2e | grep -v static) 6 | for pkg in $pkgs; do 7 | echo "go generate $pkg" 8 | go generate $pkg 9 | done 10 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/modules-yaml/exp-output-merge.txt: -------------------------------------------------------------------------------- 1 | Locks and plans deleted for the projects and workspaces modified in this pull request: 2 | 3 | - dir: `production` workspace: `default` 4 | - dir: `staging` workspace: `default` -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/modules/exp-output-merge-all-dirs.txt: -------------------------------------------------------------------------------- 1 | Locks and plans deleted for the projects and workspaces modified in this pull request: 2 | 3 | - dir: `production` workspace: `default` 4 | - dir: `staging` workspace: `default` -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/state-rm-multiple-project/exp-output-merged.txt: -------------------------------------------------------------------------------- 1 | Locks and plans deleted for the projects and workspaces modified in this pull request: 2 | 3 | - dir: `dir1` workspace: `default` 4 | - dir: `dir2` workspace: `default` -------------------------------------------------------------------------------- /server/metrics/common.go: -------------------------------------------------------------------------------- 1 | package metrics 2 | 3 | const ( 4 | ExecutionTimeMetric = "execution_time" 5 | ExecutionSuccessMetric = "execution_success" 6 | ExecutionErrorMetric = "execution_error" 7 | ExecutionFailureMetric = "execution_failure" 8 | ) 9 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/import-multiple-project/exp-output-merge.txt: -------------------------------------------------------------------------------- 1 | Locks and plans deleted for the projects and workspaces modified in this pull request: 2 | 3 | - dir: `dir1` workspace: `default` 4 | - dir: `dir2` workspace: `default` 5 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/import-single-project/main.tf: -------------------------------------------------------------------------------- 1 | resource "random_id" "dummy1" { 2 | keepers = {} 3 | byte_length = 1 4 | } 5 | 6 | resource "random_id" "dummy2" { 7 | keepers = {} 8 | byte_length = 1 9 | } 10 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/modules/modules/null/main.tf: -------------------------------------------------------------------------------- 1 | variable "var" {} 2 | resource "null_resource" "this" { 3 | } 4 | output "var" { 5 | value = var.var 6 | } 7 | 8 | output "workspace" { 9 | value = terraform.workspace 10 | } 11 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-multi-projects/exp-output-merge.txt: -------------------------------------------------------------------------------- 1 | Locks and plans deleted for the projects and workspaces modified in this pull request: 2 | 3 | - dir: `dir1` workspace: `default` 4 | - dir: `dir2` workspace: `default` -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks/repos.yaml: -------------------------------------------------------------------------------- 1 | policies: 2 | owners: 3 | users: 4 | - runatlantis 5 | policy_sets: 6 | - name: test_policy 7 | path: policies/policy.rego 8 | source: local 9 | 10 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/modules-yaml/modules/null/main.tf: -------------------------------------------------------------------------------- 1 | variable "var" {} 2 | resource "null_resource" "this" { 3 | } 4 | output "var" { 5 | value = var.var 6 | } 7 | 8 | output "workspace" { 9 | value = terraform.workspace 10 | } 11 | -------------------------------------------------------------------------------- /server/events/templates/policy_check.tmpl: -------------------------------------------------------------------------------- 1 | {{ define "policyCheck" -}} 2 | {{ $policy_sets := . }} 3 | {{ range $ps, $policy_sets }} 4 | #### Policy Set: `{{ $ps.PolicySetName }}` 5 | ```diff 6 | {{ $ps.ConftestOutput }} 7 | ``` 8 | {{ end }} 9 | {{ end }} 10 | -------------------------------------------------------------------------------- /server/events/testdata/test-repos/cloud-block-without-workspace-name/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">=1.2" 3 | cloud { 4 | organization = "atlantis-test" 5 | workspaces { 6 | tags = ["example", "tag"] 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /runatlantis.io/docs/how-atlantis-works.md: -------------------------------------------------------------------------------- 1 | # How Atlantis Works 2 | This section of docs talks about how Atlantis at deeper level. 3 | 4 | * [Locking](locking.html) 5 | * [Autoplanning](autoplanning.html) 6 | * [Automerging](automerging.html) 7 | * [Security](security.html) 8 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-success-silent/exp-output-apply.txt: -------------------------------------------------------------------------------- 1 | Ran Apply for dir: `.` workspace: `default` 2 | 3 | ```diff 4 | Apply complete! Resources: 0 added, 0 changed, 0 destroyed. 5 | 6 | Outputs: 7 | 8 | workspace = "default" 9 | ``` -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/workspace-parallel-yaml/exp-output-merge.txt: -------------------------------------------------------------------------------- 1 | Locks and plans deleted for the projects and workspaces modified in this pull request: 2 | 3 | - dir: `production` workspace: `production` 4 | - dir: `staging` workspace: `staging` 5 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Reporting a Vulnerability 4 | 5 | We take security issues seriously. Please report a security vulnerability to the maintainers using [private vulnerability reporting](https://github.com/runatlantis/atlantis/security/advisories/new). 6 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-clear-approval/repos.yaml: -------------------------------------------------------------------------------- 1 | policies: 2 | owners: 3 | users: 4 | - runatlantis 5 | policy_sets: 6 | - name: test_policy 7 | path: policies/policy.rego 8 | source: local 9 | 10 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-diff-owner/repos.yaml: -------------------------------------------------------------------------------- 1 | policies: 2 | owners: 3 | users: 4 | - someoneelse 5 | policy_sets: 6 | - name: test_policy 7 | path: policies/policy.rego 8 | source: local 9 | 10 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-disabled-repo/repos.yaml: -------------------------------------------------------------------------------- 1 | policies: 2 | owners: 3 | users: 4 | - runatlantis 5 | policy_sets: 6 | - name: test_policy 7 | path: policies/policy.rego 8 | source: local 9 | 10 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-enabled-repo/repos.yaml: -------------------------------------------------------------------------------- 1 | policies: 2 | owners: 3 | users: 4 | - runatlantis 5 | policy_sets: 6 | - name: test_policy 7 | path: policies/policy.rego 8 | source: local 9 | 10 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/modules-yaml/atlantis.yaml: -------------------------------------------------------------------------------- 1 | version: 3 2 | projects: 3 | - dir: staging 4 | autoplan: 5 | when_modified: ["**/*.tf*", "../modules/null/*"] 6 | - dir: production 7 | autoplan: 8 | when_modified: ["**/*.tf*", "../modules/null/*"] 9 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-multi-projects/repos.yaml: -------------------------------------------------------------------------------- 1 | policies: 2 | owners: 3 | users: 4 | - runatlantis 5 | policy_sets: 6 | - name: test_policy 7 | path: ../policies/policy.rego 8 | source: local 9 | 10 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/repo-config-file/exp-output-merge.txt: -------------------------------------------------------------------------------- 1 | Locks and plans deleted for the projects and workspaces modified in this pull request: 2 | 3 | - dir: `infrastructure/production` workspace: `default` 4 | - dir: `infrastructure/staging` workspace: `default` -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/state-rm-workspace/dir1/main.tf: -------------------------------------------------------------------------------- 1 | resource "random_id" "dummy1" { 2 | count = terraform.workspace == "ops" ? 1 : 0 3 | 4 | keepers = {} 5 | byte_length = 1 6 | } 7 | 8 | output "workspace" { 9 | value = terraform.workspace 10 | } 11 | -------------------------------------------------------------------------------- /server/events/templates/wrapped_err.tmpl: -------------------------------------------------------------------------------- 1 | {{ define "wrappedErr" -}} 2 | **{{ .Command }} Error** 3 |
Show Output 4 | 5 | ``` 6 | {{ .Error }} 7 | ``` 8 | {{- if ne .RenderedContext "" }} 9 | {{ .RenderedContext }} 10 | {{- end }} 11 |
12 | {{ end -}} 13 | -------------------------------------------------------------------------------- /server/events/vcs/bitbucketcloud/bitbucketcloud.go: -------------------------------------------------------------------------------- 1 | // Package bitbucketcloud holds code for Bitbucket Cloud aka (bitbucket.org). 2 | // It is separate from bitbucketserver because Bitbucket Server has different 3 | // APIs. 4 | package bitbucketcloud 5 | 6 | const BaseURL = "https://api.bitbucket.org" 7 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/modules-yaml/exp-output-merge-all-dirs.txt: -------------------------------------------------------------------------------- 1 | Locks and plans deleted for the projects and workspaces modified in this pull request: 2 | 3 | - path: `runatlantis/atlantis-tests/production` workspace: `default` 4 | - path: `runatlantis/atlantis-tests/staging` workspace: `default` -------------------------------------------------------------------------------- /server/events/templates/single_project_plan_unsuccessful.tmpl: -------------------------------------------------------------------------------- 1 | {{ define "singleProjectPlanUnsuccessful" -}} 2 | {{ $result := index .Results 0 -}} 3 | Ran {{ .Command }} for dir: `{{ $result.RepoRelDir }}` workspace: `{{ $result.Workspace }}` 4 | 5 | {{ $result.Rendered }} 6 | {{- template "log" . -}} 7 | {{ end -}} 8 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/simple-yaml/main.tf: -------------------------------------------------------------------------------- 1 | resource "null_resource" "simple" { 2 | count = "1" 3 | } 4 | 5 | variable "var" { 6 | default = "default" 7 | } 8 | 9 | output "var" { 10 | value = var.var 11 | } 12 | 13 | output "workspace" { 14 | value = terraform.workspace 15 | } 16 | -------------------------------------------------------------------------------- /server/events/pull_status_fetcher.go: -------------------------------------------------------------------------------- 1 | package events 2 | 3 | import "github.com/runatlantis/atlantis/server/events/models" 4 | 5 | // PullStatusFetcher fetches our internal model of a pull requests status 6 | type PullStatusFetcher interface { 7 | GetPullStatus(pull models.PullRequest) (*models.PullStatus, error) 8 | } 9 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Set the default behavior, in case people don't have core.autocrlf set. 2 | * text=auto 3 | 4 | # Explicitly declare text files you want to always be normalized and converted 5 | # to native line endings on checkout. 6 | *.go text 7 | *.json text 8 | *.yml text 9 | *.yaml text 10 | *.sh text 11 | *.tf text 12 | -------------------------------------------------------------------------------- /server/logging/log.go: -------------------------------------------------------------------------------- 1 | package logging 2 | 3 | import ( 4 | "io" 5 | "log" 6 | ) 7 | 8 | // SuppressDefaultLogging suppresses the default logging 9 | func SuppressDefaultLogging() { 10 | // Some packages use the default logger, so we need to suppress it. (such as uber-go/tally) 11 | log.SetOutput(io.Discard) 12 | } 13 | -------------------------------------------------------------------------------- /server/utils/slices.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | // SlicesContains reports whether v is present in s. 4 | // https://pkg.go.dev/golang.org/x/exp/slices#Contains 5 | func SlicesContains[E comparable](s []E, v E) bool { 6 | for _, vs := range s { 7 | if v == vs { 8 | return true 9 | } 10 | } 11 | return false 12 | } 13 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-enabled-repo/exp-output-apply.txt: -------------------------------------------------------------------------------- 1 | Ran Apply for dir: `.` workspace: `default` 2 | 3 | ```diff 4 | null_resource.simple: 5 | null_resource.simple: 6 | 7 | Apply complete! Resources: 1 added, 0 changed, 0 destroyed. 8 | 9 | Outputs: 10 | 11 | workspace = "default" 12 | ``` -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-apply-reqs/repos.yaml: -------------------------------------------------------------------------------- 1 | repos: 2 | - id: /.*/ 3 | apply_requirements: [approved] 4 | policies: 5 | owners: 6 | users: 7 | - runatlantis 8 | policy_sets: 9 | - name: test_policy 10 | path: policies/policy.rego 11 | source: local 12 | 13 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-disabled-repo/exp-output-apply.txt: -------------------------------------------------------------------------------- 1 | Ran Apply for dir: `.` workspace: `default` 2 | 3 | ```diff 4 | null_resource.simple: 5 | null_resource.simple: 6 | 7 | Apply complete! Resources: 1 added, 0 changed, 0 destroyed. 8 | 9 | Outputs: 10 | 11 | workspace = "default" 12 | ``` -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks/exp-output-apply.txt: -------------------------------------------------------------------------------- 1 | Ran Apply for dir: `.` workspace: `default` 2 | 3 | ```diff 4 | null_resource.simple: 5 | null_resource.simple: 6 | 7 | Apply complete! Resources: 1 added, 0 changed, 0 destroyed. 8 | 9 | Outputs: 10 | 11 | workspace = "default" 12 | 13 | ``` 14 | 15 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/automerge/exp-output-apply-dir1.txt: -------------------------------------------------------------------------------- 1 | Ran Apply for dir: `dir1` workspace: `default` 2 | 3 | ```diff 4 | null_resource.automerge[0]: Creating... 5 | null_resource.automerge[0]: Creation complete after *s [id=*******************] 6 | 7 | Apply complete! Resources: 1 added, 0 changed, 0 destroyed. 8 | ``` -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/automerge/exp-output-apply-dir2.txt: -------------------------------------------------------------------------------- 1 | Ran Apply for dir: `dir2` workspace: `default` 2 | 3 | ```diff 4 | null_resource.automerge[0]: Creating... 5 | null_resource.automerge[0]: Creation complete after *s [id=*******************] 6 | 7 | Apply complete! Resources: 1 added, 0 changed, 0 destroyed. 8 | ``` -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-success-silent/repos.yaml: -------------------------------------------------------------------------------- 1 | repos: 2 | - id: /.*/ 3 | apply_requirements: [approved] 4 | policies: 5 | owners: 6 | users: 7 | - runatlantis 8 | policy_sets: 9 | - name: test_policy 10 | path: policies/policy.rego 11 | source: local 12 | 13 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/server-side-cfg/exp-output-apply-default-workspace.txt: -------------------------------------------------------------------------------- 1 | Ran Apply for dir: `.` workspace: `default` 2 | 3 | ```diff 4 | null_resource.simple: 5 | null_resource.simple: 6 | 7 | Apply complete! Resources: 1 added, 0 changed, 0 destroyed. 8 | 9 | Outputs: 10 | 11 | workspace = "default" 12 | ``` -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/server-side-cfg/exp-output-apply-staging-workspace.txt: -------------------------------------------------------------------------------- 1 | Ran Apply for dir: `.` workspace: `staging` 2 | 3 | ```diff 4 | null_resource.simple: 5 | null_resource.simple: 6 | 7 | Apply complete! Resources: 1 added, 0 changed, 0 destroyed. 8 | 9 | Outputs: 10 | 11 | workspace = "staging" 12 | ``` -------------------------------------------------------------------------------- /server/events/templates/import_success_unwrapped.tmpl: -------------------------------------------------------------------------------- 1 | {{ define "importSuccessUnwrapped" -}} 2 | ```diff 3 | {{ .Output }} 4 | ``` 5 | 6 | :put_litter_in_its_place: A plan file was discarded. Re-plan would be required before applying. 7 | 8 | * :repeat: To **plan** this project again, comment: 9 | * `{{.RePlanCmd}}` 10 | {{ end -}} 11 | -------------------------------------------------------------------------------- /server/events/templates/state_rm_success_unwrapped.tmpl: -------------------------------------------------------------------------------- 1 | {{ define "stateRmSuccessUnwrapped" -}} 2 | ```diff 3 | {{ .Output }} 4 | ``` 5 | 6 | :put_litter_in_its_place: A plan file was discarded. Re-plan would be required before applying. 7 | 8 | * :repeat: To **plan** this project again, comment: 9 | * `{{.RePlanCmd}}` 10 | {{ end }} 11 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-disabled-previous-match/exp-output-apply.txt: -------------------------------------------------------------------------------- 1 | Ran Apply for dir: `.` workspace: `default` 2 | 3 | ```diff 4 | null_resource.simple: 5 | null_resource.simple: 6 | 7 | Apply complete! Resources: 1 added, 0 changed, 0 destroyed. 8 | 9 | Outputs: 10 | 11 | workspace = "default" 12 | ``` -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-disabled-repo-server-side/exp-output-apply.txt: -------------------------------------------------------------------------------- 1 | Ran Apply for dir: `.` workspace: `default` 2 | 3 | ```diff 4 | null_resource.simple: 5 | null_resource.simple: 6 | 7 | Apply complete! Resources: 1 added, 0 changed, 0 destroyed. 8 | 9 | Outputs: 10 | 11 | workspace = "default" 12 | ``` -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-enabled-repo-server-side/exp-output-apply.txt: -------------------------------------------------------------------------------- 1 | Ran Apply for dir: `.` workspace: `default` 2 | 3 | ```diff 4 | null_resource.simple: 5 | null_resource.simple: 6 | 7 | Apply complete! Resources: 1 added, 0 changed, 0 destroyed. 8 | 9 | Outputs: 10 | 11 | workspace = "default" 12 | ``` -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-enabled-repo-server-side/repos.yaml: -------------------------------------------------------------------------------- 1 | repos: 2 | - id: /.*/ 3 | policy_check: true 4 | 5 | policies: 6 | owners: 7 | users: 8 | - runatlantis 9 | policy_sets: 10 | - name: test_policy 11 | path: policies/policy.rego 12 | source: local 13 | 14 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/workspace-parallel-yaml/exp-output-apply-all-staging.txt: -------------------------------------------------------------------------------- 1 | ```diff 2 | null_resource.this: Creating... 3 | null_resource.this: Creation complete after *s [id=*******************] 4 | 5 | Apply complete! Resources: 1 added, 0 changed, 0 destroyed. 6 | 7 | Outputs: 8 | 9 | workspace = "staging" 10 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-apply-reqs/exp-output-apply.txt: -------------------------------------------------------------------------------- 1 | Ran Apply for dir: `.` workspace: `default` 2 | 3 | ```diff 4 | null_resource.simple: 5 | null_resource.simple: 6 | 7 | Apply complete! Resources: 1 added, 0 changed, 0 destroyed. 8 | 9 | Outputs: 10 | 11 | workspace = "default" 12 | 13 | ``` 14 | 15 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-clear-approval/exp-output-apply.txt: -------------------------------------------------------------------------------- 1 | Ran Apply for dir: `.` workspace: `default` 2 | 3 | ```diff 4 | null_resource.simple: 5 | null_resource.simple: 6 | 7 | Apply complete! Resources: 1 added, 0 changed, 0 destroyed. 8 | 9 | Outputs: 10 | 11 | workspace = "default" 12 | 13 | ``` 14 | 15 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-disabled-repo-server-side/repos.yaml: -------------------------------------------------------------------------------- 1 | repos: 2 | - id: /.*/ 3 | policy_check: false 4 | 5 | policies: 6 | owners: 7 | users: 8 | - runatlantis 9 | policy_sets: 10 | - name: test_policy 11 | path: policies/policy.rego 12 | source: local 13 | 14 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-extra-args/exp-output-apply.txt: -------------------------------------------------------------------------------- 1 | Ran Apply for dir: `.` workspace: `default` 2 | 3 | ```diff 4 | null_resource.simple: 5 | null_resource.simple: 6 | 7 | Apply complete! Resources: 1 added, 0 changed, 0 destroyed. 8 | 9 | Outputs: 10 | 11 | workspace = "default" 12 | 13 | ``` 14 | 15 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/simple-yaml/exp-output-apply-default.txt: -------------------------------------------------------------------------------- 1 | Ran Apply for dir: `.` workspace: `default` 2 | 3 | ```diff 4 | null_resource.simple: 5 | null_resource.simple: 6 | 7 | Apply complete! Resources: 1 added, 0 changed, 0 destroyed. 8 | 9 | Outputs: 10 | 11 | var = "fromconfig" 12 | workspace = "default" 13 | ``` -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/tfvars-yaml/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | backend "local" { 3 | } 4 | } 5 | 6 | resource "null_resource" "simple" { 7 | count = 1 8 | } 9 | 10 | variable "var" { 11 | } 12 | 13 | output "var" { 14 | value = var.var 15 | } 16 | 17 | output "workspace" { 18 | value = terraform.workspace 19 | } 20 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/workspace-parallel-yaml/exp-output-apply-all-production.txt: -------------------------------------------------------------------------------- 1 | ```diff 2 | null_resource.this: Creating... 3 | null_resource.this: Creation complete after *s [id=*******************] 4 | 5 | Apply complete! Resources: 1 added, 0 changed, 0 destroyed. 6 | 7 | Outputs: 8 | 9 | workspace = "production" 10 | ``` -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-custom-run-steps/exp-output-apply.txt: -------------------------------------------------------------------------------- 1 | Ran Apply for dir: `.` workspace: `default` 2 | 3 | ```diff 4 | null_resource.simple: 5 | null_resource.simple: 6 | 7 | Apply complete! Resources: 1 added, 0 changed, 0 destroyed. 8 | 9 | Outputs: 10 | 11 | workspace = "default" 12 | 13 | ``` 14 | 15 | -------------------------------------------------------------------------------- /server/events/templates/multi_project_header.tmpl: -------------------------------------------------------------------------------- 1 | {{ define "multiProjectHeader" -}} 2 | Ran {{.Command}} for {{ len .Results }} projects: 3 | 4 | {{ range $result := .Results -}} 5 | 1. {{ if $result.ProjectName }}project: `{{ $result.ProjectName }}` {{ end }}dir: `{{ $result.RepoRelDir }}` workspace: `{{ $result.Workspace }}` 6 | {{ end -}} 7 | {{ end -}} 8 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/tfvars-yaml-no-autoplan/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | backend "local" { 3 | } 4 | } 5 | 6 | resource "null_resource" "simple" { 7 | count = 1 8 | } 9 | 10 | variable "var" { 11 | } 12 | 13 | output "var" { 14 | value = var.var 15 | } 16 | 17 | output "workspace" { 18 | value = terraform.workspace 19 | } 20 | -------------------------------------------------------------------------------- /server/events/templates/single_project_apply.tmpl: -------------------------------------------------------------------------------- 1 | {{ define "singleProjectApply" -}} 2 | {{ $result := index .Results 0 -}} 3 | Ran {{ .Command }} for {{ if $result.ProjectName }}project: `{{ $result.ProjectName }}` {{ end }}dir: `{{ $result.RepoRelDir }}` workspace: `{{ $result.Workspace }}` 4 | 5 | {{ $result.Rendered }} 6 | {{- template "log" . -}} 7 | {{ end -}} 8 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/tfvars-yaml/exp-output-apply-default.txt: -------------------------------------------------------------------------------- 1 | Ran Apply for project: `default` dir: `.` workspace: `default` 2 | 3 | ```diff 4 | null_resource.simple: 5 | null_resource.simple: 6 | 7 | Apply complete! Resources: 1 added, 0 changed, 0 destroyed. 8 | 9 | Outputs: 10 | 11 | var = "default" 12 | workspace = "default" 13 | ``` -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/tfvars-yaml/exp-output-apply-staging.txt: -------------------------------------------------------------------------------- 1 | Ran Apply for project: `staging` dir: `.` workspace: `default` 2 | 3 | ```diff 4 | null_resource.simple: 5 | null_resource.simple: 6 | 7 | Apply complete! Resources: 1 added, 0 changed, 0 destroyed. 8 | 9 | Outputs: 10 | 11 | var = "staging" 12 | workspace = "default" 13 | ``` -------------------------------------------------------------------------------- /server/events/templates/single_project_import_success.tmpl: -------------------------------------------------------------------------------- 1 | {{ define "singleProjectImport" -}} 2 | {{ $result := index .Results 0 -}} 3 | Ran {{ .Command }} for {{ if $result.ProjectName }}project: `{{ $result.ProjectName }}` {{ end }}dir: `{{ $result.RepoRelDir }}` workspace: `{{ $result.Workspace }}` 4 | 5 | {{ $result.Rendered }} 6 | {{- template "log" . -}} 7 | {{ end -}} 8 | -------------------------------------------------------------------------------- /server/events/templates/single_project_state_rm_success.tmpl: -------------------------------------------------------------------------------- 1 | {{ define "singleProjectStateRm" -}} 2 | {{$result := index .Results 0}}Ran {{.Command}} `{{.SubCommand}}` for {{ if $result.ProjectName }}project: `{{$result.ProjectName}}` {{ end }}dir: `{{$result.RepoRelDir}}` workspace: `{{$result.Workspace}}` 3 | 4 | {{$result.Rendered}} 5 | {{ template "log" . }} 6 | {{ end }} 7 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/tfvars-yaml-no-autoplan/exp-output-apply-default.txt: -------------------------------------------------------------------------------- 1 | Ran Apply for project: `default` dir: `.` workspace: `default` 2 | 3 | ```diff 4 | null_resource.simple: 5 | null_resource.simple: 6 | 7 | Apply complete! Resources: 1 added, 0 changed, 0 destroyed. 8 | 9 | Outputs: 10 | 11 | var = "default" 12 | workspace = "default" 13 | ``` -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/tfvars-yaml-no-autoplan/exp-output-apply-staging.txt: -------------------------------------------------------------------------------- 1 | Ran Apply for project: `staging` dir: `.` workspace: `default` 2 | 3 | ```diff 4 | null_resource.simple: 5 | null_resource.simple: 6 | 7 | Apply complete! Resources: 1 added, 0 changed, 0 destroyed. 8 | 9 | Outputs: 10 | 11 | var = "staging" 12 | workspace = "default" 13 | ``` -------------------------------------------------------------------------------- /.codecov.yml: -------------------------------------------------------------------------------- 1 | coverage: 2 | status: 3 | # This disables the GitHub statuses from CodeCov. I found that many of the 4 | # PRs I wanted to merge failed the status checks because often some code 5 | # isn't testable or testing it isn't the highest priority. The comment with 6 | # the code coverage is all that is needed right now. 7 | project: off 8 | patch: off 9 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/import-single-project-var/main.tf: -------------------------------------------------------------------------------- 1 | resource "random_id" "for_each" { 2 | for_each = toset([var.var]) 3 | keepers = {} 4 | byte_length = 1 5 | } 6 | 7 | resource "random_id" "count" { 8 | count = 1 9 | keepers = {} 10 | byte_length = 1 11 | } 12 | 13 | variable "var" { 14 | default = "default" 15 | } 16 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/workspace-parallel-yaml/atlantis.yaml: -------------------------------------------------------------------------------- 1 | version: 3 2 | parallel_plan: false 3 | parallel_apply: true 4 | projects: 5 | - dir: production 6 | workspace: production 7 | autoplan: 8 | when_modified: ["**/*.tf*"] 9 | - dir: staging 10 | workspace: staging 11 | autoplan: 12 | when_modified: ["**/*.tf*"] 13 | -------------------------------------------------------------------------------- /server/events/templates/approve_all_projects.tmpl: -------------------------------------------------------------------------------- 1 | {{ define "approveAllProjects" -}} 2 | Approved Policies for {{ len .Results }} projects: 3 | 4 | {{ range $result := .Results -}} 5 | 1. {{ if $result.ProjectName }}project: `{{ $result.ProjectName }}` {{ end }}dir: `{{ $result.RepoRelDir }}` workspace: `{{ $result.Workspace }}` 6 | {{ end -}} 7 | {{- template "log" . -}} 8 | {{ end }} 9 | -------------------------------------------------------------------------------- /server/events/templates/single_project_version_success.tmpl: -------------------------------------------------------------------------------- 1 | {{ define "singleProjectVersionSuccess" -}} 2 | {{ $result := index .Results 0 -}} 3 | Ran {{ .Command }} for {{ if $result.ProjectName }}project: `{{ $result.ProjectName }}` {{ end }}dir: `{{ $result.RepoRelDir }}` workspace: `{{ $result.Workspace }}` 4 | 5 | {{ $result.Rendered }} 6 | {{- template "log" . -}} 7 | {{ end -}} 8 | -------------------------------------------------------------------------------- /server/events/terraform/ansi/strip.go: -------------------------------------------------------------------------------- 1 | package ansi 2 | 3 | import ( 4 | "regexp" 5 | ) 6 | 7 | const ansi = "[\u001B\u009B][[\\]()#;?]*(?:(?:(?:[a-zA-Z\\d]*(?:;[a-zA-Z\\d]*)*)?\u0007)|(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PRZcf-ntqry=><~]))" 8 | 9 | var re = regexp.MustCompile(ansi) 10 | 11 | func Strip(str string) string { 12 | return re.ReplaceAllString(str, "") 13 | } 14 | -------------------------------------------------------------------------------- /.golangci.yml: -------------------------------------------------------------------------------- 1 | linters: 2 | enable: 3 | - errcheck 4 | - gochecknoinits 5 | # We don't use goconst because it gives false positives in the tests. 6 | # - goconst 7 | - gofmt 8 | - revive 9 | - gosec 10 | - gosimple 11 | - ineffassign 12 | - staticcheck 13 | - typecheck 14 | - unconvert 15 | - unused 16 | - vet 17 | - vetshadow 18 | run: 19 | timeout: 10m 20 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-disabled-previous-match/repos.yaml: -------------------------------------------------------------------------------- 1 | repos: 2 | - id: "/.*/" 3 | policy_check: false 4 | - id: github.com/runatlantis/atlantis-tests 5 | policies: 6 | owners: 7 | users: 8 | - runatlantis 9 | policy_sets: 10 | - name: test_policy 11 | path: policies/policy.rego 12 | source: local 13 | 14 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/simple/main.tf: -------------------------------------------------------------------------------- 1 | resource "null_resource" "simple" { 2 | count = 1 3 | } 4 | 5 | resource "null_resource" "simple2" {} 6 | resource "null_resource" "simple3" {} 7 | 8 | variable "var" { 9 | default = "default" 10 | } 11 | 12 | output "var" { 13 | value = var.var 14 | } 15 | 16 | output "workspace" { 17 | value = terraform.workspace 18 | } 19 | -------------------------------------------------------------------------------- /server/events/templates/import_success_wrapped.tmpl: -------------------------------------------------------------------------------- 1 | {{ define "importSuccessWrapped" -}} 2 |
Show Output 3 | 4 | ```diff 5 | {{ .Output }} 6 | ``` 7 |
8 | :put_litter_in_its_place: A plan file was discarded. Re-plan would be required before applying. 9 | 10 | * :repeat: To **plan** this project again, comment: 11 | * `{{ .RePlanCmd }}` 12 | {{ end -}} 13 | -------------------------------------------------------------------------------- /server/events/templates/state_rm_success_wrapped.tmpl: -------------------------------------------------------------------------------- 1 | {{ define "stateRmSuccessWrapped" -}} 2 |
Show Output 3 | 4 | ```diff 5 | {{ .Output }} 6 | ``` 7 |
8 | :put_litter_in_its_place: A plan file was discarded. Re-plan would be required before applying. 9 | 10 | * :repeat: To **plan** this project again, comment: 11 | * `{{.RePlanCmd}}` 12 | {{ end }} 13 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/modules/exp-output-apply-staging.txt: -------------------------------------------------------------------------------- 1 | Ran Apply for dir: `staging` workspace: `default` 2 | 3 | ```diff 4 | module.null.null_resource.this: Creating... 5 | module.null.null_resource.this: Creation complete after *s [id=*******************] 6 | 7 | Apply complete! Resources: 1 added, 0 changed, 0 destroyed. 8 | 9 | Outputs: 10 | 11 | var = "staging" 12 | ``` -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/modules-yaml/exp-output-apply-staging.txt: -------------------------------------------------------------------------------- 1 | Ran Apply for dir: `staging` workspace: `default` 2 | 3 | ```diff 4 | module.null.null_resource.this: Creating... 5 | module.null.null_resource.this: Creation complete after *s [id=*******************] 6 | 7 | Apply complete! Resources: 1 added, 0 changed, 0 destroyed. 8 | 9 | Outputs: 10 | 11 | var = "staging" 12 | ``` -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/modules/exp-output-apply-production.txt: -------------------------------------------------------------------------------- 1 | Ran Apply for dir: `production` workspace: `default` 2 | 3 | ```diff 4 | module.null.null_resource.this: Creating... 5 | module.null.null_resource.this: Creation complete after *s [id=*******************] 6 | 7 | Apply complete! Resources: 1 added, 0 changed, 0 destroyed. 8 | 9 | Outputs: 10 | 11 | var = "production" 12 | ``` -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/simple-with-lockfile/main.tf: -------------------------------------------------------------------------------- 1 | resource "null_resource" "simple" { 2 | count = 1 3 | } 4 | 5 | resource "null_resource" "simple2" {} 6 | resource "null_resource" "simple3" {} 7 | 8 | variable "var" { 9 | default = "default" 10 | } 11 | 12 | output "var" { 13 | value = var.var 14 | } 15 | 16 | output "workspace" { 17 | value = terraform.workspace 18 | } 19 | -------------------------------------------------------------------------------- /server/core/runtime/pull_approved_checker.go: -------------------------------------------------------------------------------- 1 | package runtime 2 | 3 | import ( 4 | "github.com/runatlantis/atlantis/server/events/models" 5 | ) 6 | 7 | //go:generate pegomock generate --package mocks -o mocks/mock_pull_approved_checker.go PullApprovedChecker 8 | 9 | type PullApprovedChecker interface { 10 | PullIsApproved(baseRepo models.Repo, pull models.PullRequest) (models.ApprovalStatus, error) 11 | } 12 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/modules-yaml/exp-output-apply-production.txt: -------------------------------------------------------------------------------- 1 | Ran Apply for dir: `production` workspace: `default` 2 | 3 | ```diff 4 | module.null.null_resource.this: Creating... 5 | module.null.null_resource.this: Creation complete after *s [id=*******************] 6 | 7 | Apply complete! Resources: 1 added, 0 changed, 0 destroyed. 8 | 9 | Outputs: 10 | 11 | var = "production" 12 | ``` -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "license": "Apache-2.0", 3 | "devDependencies": { 4 | "@vuepress/plugin-docsearch": "2.0.0-beta.66", 5 | "@vuepress/plugin-google-analytics": "2.0.0-beta.67", 6 | "vuepress": "2.0.0-beta.66" 7 | }, 8 | "scripts": { 9 | "website:dev": "vuepress dev runatlantis.io", 10 | "website:build": "NODE_OPTIONS=--openssl-legacy-provider vuepress build runatlantis.io" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /server/events/templates/multi_project_apply.tmpl: -------------------------------------------------------------------------------- 1 | {{ define "multiProjectApply" -}} 2 | {{ template "multiProjectHeader" . }} 3 | {{ range $i, $result := .Results -}} 4 | ### {{ add $i 1 }}. {{ if $result.ProjectName }}project: `{{ $result.ProjectName }}` {{ end }}dir: `{{ $result.RepoRelDir }}` workspace: `{{ $result.Workspace }}` 5 | {{ $result.Rendered }} 6 | 7 | --- 8 | {{ end -}} 9 | {{- template "log" . -}} 10 | {{ end -}} 11 | -------------------------------------------------------------------------------- /server/events/templates/multi_project_import.tmpl: -------------------------------------------------------------------------------- 1 | {{ define "multiProjectImport" -}} 2 | {{ template "multiProjectHeader" . }} 3 | {{ range $i, $result := .Results -}} 4 | ### {{ add $i 1 }}. {{ if $result.ProjectName }}project: `{{ $result.ProjectName }}` {{ end }}dir: `{{ $result.RepoRelDir }}` workspace: `{{ $result.Workspace }}` 5 | {{ $result.Rendered }} 6 | 7 | --- 8 | {{ end -}} 9 | {{- template "log" . -}} 10 | {{ end -}} 11 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-extra-args/repos.yaml: -------------------------------------------------------------------------------- 1 | policies: 2 | owners: 3 | users: 4 | - runatlantis 5 | policy_sets: 6 | - name: test_policy 7 | path: policies/policy.rego 8 | source: local 9 | workflows: 10 | default: 11 | policy_check: 12 | steps: 13 | - show 14 | - policy_check: 15 | extra_args: ["--all-namespaces"] 16 | 17 | -------------------------------------------------------------------------------- /server/events/templates/multi_project_state_rm.tmpl: -------------------------------------------------------------------------------- 1 | {{ define "multiProjectStateRm" -}} 2 | {{ template "multiProjectHeader" . }} 3 | {{ range $i, $result := .Results -}} 4 | ### {{ add $i 1 }}. {{ if $result.ProjectName }}project: `{{ $result.ProjectName }}` {{ end }}dir: `{{ $result.RepoRelDir }}` workspace: `{{ $result.Workspace }}` 5 | {{ $result.Rendered}} 6 | 7 | --- 8 | {{ end -}} 9 | {{- template "log" . -}} 10 | {{ end -}} 11 | -------------------------------------------------------------------------------- /server/events/templates/multi_project_version.tmpl: -------------------------------------------------------------------------------- 1 | {{ define "multiProjectVersion" -}} 2 | {{ template "multiProjectHeader" . }} 3 | {{ range $i, $result := .Results -}} 4 | ### {{ add $i 1 }}. {{ if $result.ProjectName }}project: `{{ $result.ProjectName }}` {{ end }}dir: `{{ $result.RepoRelDir }}` workspace: `{{ $result.Workspace }}` 5 | {{ $result.Rendered}} 6 | 7 | --- 8 | {{ end -}} 9 | {{- template "log" . -}} 10 | {{ end -}} 11 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/import-workspace/dir1/main.tf: -------------------------------------------------------------------------------- 1 | resource "random_id" "dummy1" { 2 | count = terraform.workspace == "ops" ? 1 : 0 3 | 4 | keepers = {} 5 | byte_length = 1 6 | } 7 | 8 | resource "random_id" "dummy2" { 9 | count = terraform.workspace == "ops" ? 1 : 0 10 | 11 | keepers = {} 12 | byte_length = 1 13 | } 14 | 15 | output "workspace" { 16 | value = terraform.workspace 17 | } 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | ./atlantis 3 | *.iml 4 | .vscode 5 | atlantis.db 6 | output 7 | .DS_Store 8 | .cover 9 | .terraform/ 10 | node_modules/ 11 | **/.vuepress/* 12 | helm/test-values.yaml 13 | *.swp 14 | golangci-lint 15 | atlantis 16 | .devcontainer 17 | atlantis.env 18 | *.act 19 | package-lock.json 20 | Dockerfile.local 21 | 22 | # gitreleaser 23 | dist/ 24 | tmp-CHANGELOG.md 25 | 26 | .envrc 27 | 28 | # IDE files 29 | *.code-workspace 30 | -------------------------------------------------------------------------------- /.github/workflows/pr-lint.yml: -------------------------------------------------------------------------------- 1 | name: "Lint PR" 2 | 3 | on: 4 | pull_request_target: 5 | types: 6 | - opened 7 | - edited 8 | - synchronize 9 | 10 | permissions: 11 | pull-requests: read 12 | 13 | jobs: 14 | main: 15 | name: Validate PR title 16 | runs-on: ubuntu-latest 17 | steps: 18 | - uses: amannn/action-semantic-pull-request@v5 19 | env: 20 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 21 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/simple-yaml/exp-output-apply-staging.txt: -------------------------------------------------------------------------------- 1 | Ran Apply for dir: `.` workspace: `staging` 2 | 3 |
Show Output 4 | 5 | ```diff 6 | preapply 7 | 8 | null_resource.simple: 9 | null_resource.simple: 10 | 11 | Apply complete! Resources: 1 added, 0 changed, 0 destroyed. 12 | 13 | Outputs: 14 | 15 | var = "fromfile" 16 | workspace = "staging" 17 | 18 | postapply 19 | ``` 20 | 21 |
-------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/state-rm-single-project/exp-output-state-rm-foreach.txt: -------------------------------------------------------------------------------- 1 | Ran State `rm` for dir: `.` workspace: `default` 2 | 3 | ```diff 4 | Removed random_id.for_each["overridden"] 5 | Successfully removed 1 resource instance(s). 6 | ``` 7 | 8 | :put_litter_in_its_place: A plan file was discarded. Re-plan would be required before applying. 9 | 10 | * :repeat: To **plan** this project again, comment: 11 | * `atlantis plan -d .` -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/state-rm-workspace/exp-output-state-rm-dummy1.txt: -------------------------------------------------------------------------------- 1 | Ran State `rm` for project: `dir1-ops` dir: `dir1` workspace: `ops` 2 | 3 | ```diff 4 | Removed random_id.dummy1[0] 5 | Successfully removed 1 resource instance(s). 6 | ``` 7 | 8 | :put_litter_in_its_place: A plan file was discarded. Re-plan would be required before applying. 9 | 10 | * :repeat: To **plan** this project again, comment: 11 | * `atlantis plan -p dir1-ops` -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/state-rm-single-project/main.tf: -------------------------------------------------------------------------------- 1 | resource "random_id" "simple" { 2 | keepers = {} 3 | byte_length = 1 4 | } 5 | 6 | resource "random_id" "for_each" { 7 | for_each = toset([var.var]) 8 | keepers = {} 9 | byte_length = 1 10 | } 11 | 12 | resource "random_id" "count" { 13 | count = 1 14 | keepers = {} 15 | byte_length = 1 16 | } 17 | 18 | variable "var" { 19 | default = "default" 20 | } 21 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/state-rm-single-project/exp-output-state-rm-multiple.txt: -------------------------------------------------------------------------------- 1 | Ran State `rm` for dir: `.` workspace: `default` 2 | 3 | ```diff 4 | Removed random_id.count[0] 5 | Removed random_id.simple 6 | Successfully removed 2 resource instance(s). 7 | ``` 8 | 9 | :put_litter_in_its_place: A plan file was discarded. Re-plan would be required before applying. 10 | 11 | * :repeat: To **plan** this project again, comment: 12 | * `atlantis plan -d .` -------------------------------------------------------------------------------- /server/metrics/counter_test.go: -------------------------------------------------------------------------------- 1 | package metrics 2 | 3 | import ( 4 | "testing" 5 | 6 | tally "github.com/uber-go/tally/v4" 7 | ) 8 | 9 | func TestInitCounter(t *testing.T) { 10 | scope := tally.NewTestScope("test", nil) 11 | 12 | InitCounter(scope, "counter") 13 | 14 | counter, ok := scope.Snapshot().Counters()["test.counter+"] 15 | if !ok { 16 | t.Errorf("Counter not found") 17 | } 18 | if counter.Value() != 0 { 19 | t.Errorf("Counter is not initialized") 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /server/scheduled/runtime_stats_test.go: -------------------------------------------------------------------------------- 1 | package scheduled 2 | 3 | import ( 4 | "testing" 5 | 6 | tally "github.com/uber-go/tally/v4" 7 | ) 8 | 9 | func TestRuntimeStatCollector_Run(t *testing.T) { 10 | scope := tally.NewTestScope("test", nil) 11 | r := NewRuntimeStats(scope) 12 | r.Run() 13 | 14 | expGaugeCount := 25 15 | if len(scope.Snapshot().Gauges()) != expGaugeCount { 16 | t.Errorf("Expected %d gauges but got %d", expGaugeCount, len(scope.Snapshot().Gauges())) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /.github/workflows/renovate-config.yml: -------------------------------------------------------------------------------- 1 | name: renovate-config 2 | 3 | on: 4 | push: 5 | paths: 6 | - '.github/renovate.json5' 7 | branches: 8 | - main 9 | pull_request: 10 | paths: 11 | - '.github/renovate.json5' 12 | workflow_dispatch: 13 | 14 | jobs: 15 | validate: 16 | runs-on: ubuntu-latest 17 | steps: 18 | - uses: actions/checkout@v3 19 | - uses: actions/setup-node@v3 20 | - run: npx --package renovate -c 'renovate-config-validator' 21 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/simple/exp-output-apply.txt: -------------------------------------------------------------------------------- 1 | Ran Apply for dir: `.` workspace: `default` 2 | 3 |
Show Output 4 | 5 | ```diff 6 | null_resource.simple: 7 | null_resource.simple: 8 | null_resource.simple: 9 | null_resource.simple: 10 | null_resource.simple: 11 | null_resource.simple: 12 | 13 | Apply complete! Resources: 3 added, 0 changed, 0 destroyed. 14 | 15 | Outputs: 16 | 17 | var = "default" 18 | workspace = "default" 19 | ``` 20 | 21 |
-------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/simple/exp-output-apply-var.txt: -------------------------------------------------------------------------------- 1 | Ran Apply for dir: `.` workspace: `default` 2 | 3 |
Show Output 4 | 5 | ```diff 6 | null_resource.simple: 7 | null_resource.simple: 8 | null_resource.simple: 9 | null_resource.simple: 10 | null_resource.simple: 11 | null_resource.simple: 12 | 13 | Apply complete! Resources: 3 added, 0 changed, 0 destroyed. 14 | 15 | Outputs: 16 | 17 | var = "overridden" 18 | workspace = "default" 19 | ``` 20 | 21 |
-------------------------------------------------------------------------------- /server/events/vcs/testdata/azuredevops-policyevaluations.json: -------------------------------------------------------------------------------- 1 | { 2 | "value": [ 3 | { 4 | "configuration": { 5 | "isDeleted": false, 6 | "isEnabled": true, 7 | "isBlocking": true, 8 | "settings": { 9 | "statusGenre": "Atlantis Bot/atlantis", 10 | "statusName": "plan" 11 | } 12 | }, 13 | "status": "approved" 14 | } 15 | ], 16 | "count": 1 17 | } -------------------------------------------------------------------------------- /e2e/Makefile: -------------------------------------------------------------------------------- 1 | WORKSPACE := $(shell pwd) 2 | 3 | .PHONY: test 4 | 5 | .DEFAULT_GOAL := help 6 | help: ## List targets & descriptions 7 | @cat Makefile* | grep -E '^[a-zA-Z_-]+:.*?## .*$$' | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' 8 | 9 | debug: ## Output internal make variables 10 | @echo WORKSPACE = $(WORKSPACE) 11 | 12 | build: ## Build the main Go service 13 | rm -f atlantis-tests 14 | go build -v -o atlantis-tests . 15 | 16 | run: ## Run e2e tests 17 | ./atlantis-tests 18 | -------------------------------------------------------------------------------- /server/core/config/raw/raw_test.go: -------------------------------------------------------------------------------- 1 | package raw_test 2 | 3 | // Bool is a helper routine that allocates a new bool value 4 | // to store v and returns a pointer to it. 5 | func Bool(v bool) *bool { return &v } 6 | 7 | // Int is a helper routine that allocates a new int value 8 | // to store v and returns a pointer to it. 9 | func Int(v int) *int { return &v } 10 | 11 | // String is a helper routine that allocates a new string value 12 | // to store v and returns a pointer to it. 13 | func String(v string) *string { return &v } 14 | -------------------------------------------------------------------------------- /server/events/models/commit_status_test.go: -------------------------------------------------------------------------------- 1 | package models_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/runatlantis/atlantis/server/events/models" 7 | . "github.com/runatlantis/atlantis/testing" 8 | ) 9 | 10 | func TestStatus_String(t *testing.T) { 11 | cases := map[models.CommitStatus]string{ 12 | models.PendingCommitStatus: "pending", 13 | models.SuccessCommitStatus: "success", 14 | models.FailedCommitStatus: "failed", 15 | } 16 | for k, v := range cases { 17 | Equals(t, v, k.String()) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /server/events/vcs/testdata/github-branch-protection-no-required-checks.json: -------------------------------------------------------------------------------- 1 | { 2 | "url": "https://api.github.com/repos/octocat/repo/branches/master/protection", 3 | "required_pull_request_reviews": { 4 | "url": "https://api.github.com/repos/octocat/repo/branches/master/protection/required_pull_request_reviews", 5 | "dismiss_stale_reviews": false, 6 | "require_code_owner_reviews": false, 7 | "require_last_push_approval": false, 8 | "required_approving_review_count": 1 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/simple/exp-output-apply-var-default-workspace.txt: -------------------------------------------------------------------------------- 1 | Ran Apply for dir: `.` workspace: `default` 2 | 3 |
Show Output 4 | 5 | ```diff 6 | null_resource.simple: 7 | null_resource.simple: 8 | null_resource.simple: 9 | null_resource.simple: 10 | null_resource.simple: 11 | null_resource.simple: 12 | 13 | Apply complete! Resources: 3 added, 0 changed, 0 destroyed. 14 | 15 | Outputs: 16 | 17 | var = "default_workspace" 18 | workspace = "default" 19 | ``` 20 | 21 |
-------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-custom-run-steps/repos.yaml: -------------------------------------------------------------------------------- 1 | policies: 2 | owners: 3 | users: 4 | - runatlantis 5 | policy_sets: 6 | - name: test_policy 7 | path: policies/policy.rego 8 | source: local 9 | 10 | workflows: 11 | default: 12 | policy_check: 13 | steps: 14 | - show 15 | - run: "echo 'pre-conftest output'" 16 | - policy_check: 17 | extra_args: 18 | - --no-fail 19 | - run: "echo 'post-conftest output'" -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/simple/exp-output-apply-var-new-workspace.txt: -------------------------------------------------------------------------------- 1 | Ran Apply for dir: `.` workspace: `new_workspace` 2 | 3 |
Show Output 4 | 5 | ```diff 6 | null_resource.simple: 7 | null_resource.simple: 8 | null_resource.simple: 9 | null_resource.simple: 10 | null_resource.simple: 11 | null_resource.simple: 12 | 13 | Apply complete! Resources: 3 added, 0 changed, 0 destroyed. 14 | 15 | Outputs: 16 | 17 | var = "new_workspace" 18 | workspace = "new_workspace" 19 | ``` 20 | 21 |
-------------------------------------------------------------------------------- /testing/http.go: -------------------------------------------------------------------------------- 1 | package testing 2 | 3 | import ( 4 | "io" 5 | "net/http/httptest" 6 | "strings" 7 | "testing" 8 | ) 9 | 10 | func ResponseContains(t *testing.T, r *httptest.ResponseRecorder, status int, bodySubstr string) { 11 | t.Helper() 12 | body, err := io.ReadAll(r.Result().Body) 13 | Ok(t, err) 14 | Assert(t, status == r.Result().StatusCode, "exp %d got %d, body: %s", status, r.Result().StatusCode, string(body)) 15 | Assert(t, strings.Contains(string(body), bodySubstr), "exp %q to be contained in %q", bodySubstr, string(body)) 16 | } 17 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/server-side-cfg/repos.yaml: -------------------------------------------------------------------------------- 1 | repos: 2 | - id: /.*/ 3 | pre_workflow_hooks: 4 | - run: echo "hello" 5 | workflow: custom 6 | post_workflow_hooks: 7 | - run: echo "hello" 8 | allowed_overrides: [workflow] 9 | workflows: 10 | custom: 11 | plan: 12 | steps: 13 | - run: echo preinit custom 14 | - init 15 | - plan 16 | - run: echo postplan custom 17 | staging: 18 | plan: 19 | steps: 20 | - run: echo preinit staging 21 | - init 22 | - plan 23 | -------------------------------------------------------------------------------- /server/utils/spellcheck.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "github.com/agext/levenshtein" 5 | ) 6 | 7 | // IsSimilarWord calculates "The Levenshtein Distance" between two strings which 8 | // represents the minimum total cost of edits that would convert the first string 9 | // into the second. If the distance is less than 3, the word is considered misspelled. 10 | func IsSimilarWord(given string, suggestion string) bool { 11 | dist := levenshtein.Distance(given, suggestion, nil) 12 | if dist > 0 && dist < 3 { 13 | return true 14 | } 15 | 16 | return false 17 | } 18 | -------------------------------------------------------------------------------- /.github/workflows/labeler.yml: -------------------------------------------------------------------------------- 1 | name: "Pull Request Labeler" 2 | 3 | on: 4 | pull_request_target: 5 | types: 6 | - opened 7 | - reopened 8 | - synchronize 9 | - ready_for_review 10 | 11 | jobs: 12 | triage: 13 | permissions: 14 | contents: read 15 | pull-requests: write 16 | if: github.event.pull_request.draft == false 17 | runs-on: ubuntu-22.04 18 | steps: 19 | - uses: actions/labeler@v4 20 | with: 21 | repo-token: "${{ secrets.GITHUB_TOKEN }}" 22 | configuration-path: .github/labeler.yml 23 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-multi-projects/exp-output-apply.txt: -------------------------------------------------------------------------------- 1 | Ran Apply for 2 projects: 2 | 3 | 1. dir: `dir1` workspace: `default` 4 | 1. dir: `dir2` workspace: `default` 5 | 6 | ### 1. dir: `dir1` workspace: `default` 7 | ```diff 8 | null_resource.simple: 9 | null_resource.simple: 10 | 11 | Apply complete! Resources: 1 added, 0 changed, 0 destroyed. 12 | 13 | Outputs: 14 | 15 | workspace = "default" 16 | ``` 17 | 18 | --- 19 | ### 2. dir: `dir2` workspace: `default` 20 | **Apply Failed**: All policies must pass for project before running apply. 21 | 22 | --- -------------------------------------------------------------------------------- /server/core/config/raw/stage.go: -------------------------------------------------------------------------------- 1 | package raw 2 | 3 | import ( 4 | validation "github.com/go-ozzo/ozzo-validation" 5 | "github.com/runatlantis/atlantis/server/core/config/valid" 6 | ) 7 | 8 | type Stage struct { 9 | Steps []Step `yaml:"steps,omitempty" json:"steps,omitempty"` 10 | } 11 | 12 | func (s Stage) Validate() error { 13 | return validation.ValidateStruct(&s, 14 | validation.Field(&s.Steps), 15 | ) 16 | } 17 | 18 | func (s Stage) ToValid() valid.Stage { 19 | var validSteps []valid.Step 20 | for _, s := range s.Steps { 21 | validSteps = append(validSteps, s.ToValid()) 22 | } 23 | return valid.Stage{ 24 | Steps: validSteps, 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /server/events/terraform/ansi/strip_test.go: -------------------------------------------------------------------------------- 1 | package ansi 2 | 3 | import "testing" 4 | 5 | func TestStrip(t *testing.T) { 6 | tests := []struct { 7 | name string 8 | str string 9 | want string 10 | }{ 11 | { 12 | name: "strip ansi", 13 | str: ` 14 | + create 15 | Plan: 3 to add, 0 to change, 0 to destroy. 16 | `, 17 | want: ` 18 | + create 19 | Plan: 3 to add, 0 to change, 0 to destroy. 20 | `, 21 | }, 22 | } 23 | for _, tt := range tests { 24 | t.Run(tt.name, func(t *testing.T) { 25 | if got := Strip(tt.str); got != tt.want { 26 | t.Errorf("Strip() = %v, want %v", got, tt.want) 27 | } 28 | }) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/simple/exp-output-auto-policy-check.txt: -------------------------------------------------------------------------------- 1 | Ran Policy Check for dir: `.` workspace: `default` 2 | 3 | ```diff 4 | 5 | ``` 6 | 7 | * :arrow_forward: To **apply** this plan, comment: 8 | * `atlantis apply -d .` 9 | * :put_litter_in_its_place: To **delete** this plan click [here](lock-url) 10 | * :repeat: To re-run policies **plan** this project again by commenting: 11 | * `atlantis plan -d .` 12 | 13 | --- 14 | * :fast_forward: To **apply** all unapplied plans from this pull request, comment: 15 | * `atlantis apply` 16 | * :put_litter_in_its_place: To delete all plans and locks for the PR, comment: 17 | * `atlantis unlock` 18 | -------------------------------------------------------------------------------- /server/events/templates/single_project_plan_success.tmpl: -------------------------------------------------------------------------------- 1 | {{ define "singleProjectPlanSuccess" -}} 2 | {{ $result := index .Results 0 -}} 3 | Ran {{ .Command }} for {{ if $result.ProjectName }}project: `{{ $result.ProjectName }}` {{ end }}dir: `{{ $result.RepoRelDir }}` workspace: `{{ $result.Workspace }}` 4 | 5 | {{ $result.Rendered }} 6 | {{ if ne .DisableApplyAll true }} 7 | --- 8 | * :fast_forward: To **apply** all unapplied plans from this pull request, comment: 9 | * `{{ .ExecutableName }} apply` 10 | * :put_litter_in_its_place: To delete all plans and locks for the PR, comment: 11 | * `{{ .ExecutableName }} unlock` 12 | {{ end -}} 13 | {{- template "log" . -}} 14 | {{ end -}} 15 | -------------------------------------------------------------------------------- /server/events/command/lock.go: -------------------------------------------------------------------------------- 1 | package command 2 | 3 | import ( 4 | "time" 5 | ) 6 | 7 | // LockMetadata contains additional data provided to the lock 8 | type LockMetadata struct { 9 | UnixTime int64 10 | } 11 | 12 | // Lock represents a global lock for an atlantis command (plan, apply, policy_check). 13 | // It is used to prevent commands from being executed 14 | type Lock struct { 15 | // Time is the time at which the lock was first created. 16 | LockMetadata LockMetadata 17 | CommandName Name 18 | } 19 | 20 | func (l *Lock) LockTime() time.Time { 21 | return time.Unix(l.LockMetadata.UnixTime, 0) 22 | } 23 | 24 | func (l *Lock) IsLocked() bool { 25 | return !l.LockTime().IsZero() 26 | } 27 | -------------------------------------------------------------------------------- /.github/labeler.yml: -------------------------------------------------------------------------------- 1 | build: 2 | - 'Dockerfile*' 3 | 4 | dependencies: 5 | - 'yarn.lock' 6 | - 'go.*' 7 | 8 | docs: 9 | - 'runatlantis.io/**/*.md' 10 | - 'README.md' 11 | 12 | github-actions: 13 | - '.github/**' 14 | 15 | go: 16 | - '**/*.go' 17 | 18 | provider/azuredevops: 19 | - 'server/**/*azuredevops*.go' 20 | 21 | provider/bitbucket: 22 | - 'server/**/*bitbucket*.go' 23 | - 'server/events/vcs/bitbucketcloud/*.go' 24 | - 'server/events/vcs/bitbucketserver/*.go' 25 | 26 | provider/github: 27 | - 'server/**/*github*.go' 28 | 29 | provider/gitlab: 30 | - 'server/**/*gitlab*.go' 31 | 32 | website: 33 | - 'runatlantis.io/.vuepress/**/*' 34 | - 'package.json' 35 | - 'yarn.lock' 36 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/import-single-project/exp-output-import-dummy1.txt: -------------------------------------------------------------------------------- 1 | Ran Import for dir: `.` workspace: `default` 2 | 3 | ```diff 4 | random_id.dummy1: Importing from ID "AA"... 5 | random_id.dummy1: Import prepared! 6 | Prepared random_id for import 7 | random_id.dummy1: Refreshing state... [id=AA] 8 | 9 | Import successful! 10 | 11 | The resources that were imported are shown above. These resources are now in 12 | your Terraform state and will henceforth be managed by Terraform. 13 | ``` 14 | 15 | :put_litter_in_its_place: A plan file was discarded. Re-plan would be required before applying. 16 | 17 | * :repeat: To **plan** this project again, comment: 18 | * `atlantis plan -d .` -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/import-single-project/exp-output-import-dummy2.txt: -------------------------------------------------------------------------------- 1 | Ran Import for dir: `.` workspace: `default` 2 | 3 | ```diff 4 | random_id.dummy2: Importing from ID "BB"... 5 | random_id.dummy2: Import prepared! 6 | Prepared random_id for import 7 | random_id.dummy2: Refreshing state... [id=BB] 8 | 9 | Import successful! 10 | 11 | The resources that were imported are shown above. These resources are now in 12 | your Terraform state and will henceforth be managed by Terraform. 13 | ``` 14 | 15 | :put_litter_in_its_place: A plan file was discarded. Re-plan would be required before applying. 16 | 17 | * :repeat: To **plan** this project again, comment: 18 | * `atlantis plan -d .` -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/state-rm-single-project/exp-output-import-simple.txt: -------------------------------------------------------------------------------- 1 | Ran Import for dir: `.` workspace: `default` 2 | 3 | ```diff 4 | random_id.simple: Importing from ID "AA"... 5 | random_id.simple: Import prepared! 6 | Prepared random_id for import 7 | random_id.simple: Refreshing state... [id=AA] 8 | 9 | Import successful! 10 | 11 | The resources that were imported are shown above. These resources are now in 12 | your Terraform state and will henceforth be managed by Terraform. 13 | ``` 14 | 15 | :put_litter_in_its_place: A plan file was discarded. Re-plan would be required before applying. 16 | 17 | * :repeat: To **plan** this project again, comment: 18 | * `atlantis plan -d .` -------------------------------------------------------------------------------- /.github/release.yml: -------------------------------------------------------------------------------- 1 | changelog: 2 | exclude: 3 | labels: 4 | - ignore-for-release 5 | - docs 6 | - github-actions 7 | authors: 8 | - octocat 9 | categories: 10 | - title: Breaking Changes 🛠 11 | labels: 12 | - Semver-Major 13 | - breaking-change 14 | - title: Exciting New Features 🎉 15 | labels: 16 | - Semver-Minor 17 | - enhancement 18 | - feature 19 | - title: Bug fixes 20 | labels: 21 | - bug 22 | - title: Other Changes 23 | labels: 24 | - "*" 25 | - title: Dependencies 26 | labels: 27 | - dependencies 28 | - title: Build 29 | labels: 30 | - build 31 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/import-multiple-project/exp-output-import-dummy1.txt: -------------------------------------------------------------------------------- 1 | Ran Import for dir: `dir1` workspace: `default` 2 | 3 | ```diff 4 | random_id.dummy1: Importing from ID "AA"... 5 | random_id.dummy1: Import prepared! 6 | Prepared random_id for import 7 | random_id.dummy1: Refreshing state... [id=AA] 8 | 9 | Import successful! 10 | 11 | The resources that were imported are shown above. These resources are now in 12 | your Terraform state and will henceforth be managed by Terraform. 13 | ``` 14 | 15 | :put_litter_in_its_place: A plan file was discarded. Re-plan would be required before applying. 16 | 17 | * :repeat: To **plan** this project again, comment: 18 | * `atlantis plan -d dir1` -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/state-rm-multiple-project/exp-output-import-dummy1.txt: -------------------------------------------------------------------------------- 1 | Ran Import for dir: `dir1` workspace: `default` 2 | 3 | ```diff 4 | random_id.dummy: Importing from ID "AA"... 5 | random_id.dummy: Import prepared! 6 | Prepared random_id for import 7 | random_id.dummy: Refreshing state... [id=AA] 8 | 9 | Import successful! 10 | 11 | The resources that were imported are shown above. These resources are now in 12 | your Terraform state and will henceforth be managed by Terraform. 13 | ``` 14 | 15 | :put_litter_in_its_place: A plan file was discarded. Re-plan would be required before applying. 16 | 17 | * :repeat: To **plan** this project again, comment: 18 | * `atlantis plan -d dir1` -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/state-rm-multiple-project/exp-output-import-dummy2.txt: -------------------------------------------------------------------------------- 1 | Ran Import for dir: `dir2` workspace: `default` 2 | 3 | ```diff 4 | random_id.dummy: Importing from ID "BB"... 5 | random_id.dummy: Import prepared! 6 | Prepared random_id for import 7 | random_id.dummy: Refreshing state... [id=BB] 8 | 9 | Import successful! 10 | 11 | The resources that were imported are shown above. These resources are now in 12 | your Terraform state and will henceforth be managed by Terraform. 13 | ``` 14 | 15 | :put_litter_in_its_place: A plan file was discarded. Re-plan would be required before applying. 16 | 17 | * :repeat: To **plan** this project again, comment: 18 | * `atlantis plan -d dir2` -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/state-rm-single-project/exp-output-import-count.txt: -------------------------------------------------------------------------------- 1 | Ran Import for dir: `.` workspace: `default` 2 | 3 | ```diff 4 | random_id.count[0]: Importing from ID "BB"... 5 | random_id.count[0]: Import prepared! 6 | Prepared random_id for import 7 | random_id.count[0]: Refreshing state... [id=BB] 8 | 9 | Import successful! 10 | 11 | The resources that were imported are shown above. These resources are now in 12 | your Terraform state and will henceforth be managed by Terraform. 13 | ``` 14 | 15 | :put_litter_in_its_place: A plan file was discarded. Re-plan would be required before applying. 16 | 17 | * :repeat: To **plan** this project again, comment: 18 | * `atlantis plan -d .` -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/import-single-project-var/exp-output-import-count.txt: -------------------------------------------------------------------------------- 1 | Ran Import for dir: `.` workspace: `default` 2 | 3 | ```diff 4 | random_id.count[0]: Importing from ID "BB"... 5 | random_id.count[0]: Import prepared! 6 | Prepared random_id for import 7 | random_id.count[0]: Refreshing state... [id=BB] 8 | 9 | Import successful! 10 | 11 | The resources that were imported are shown above. These resources are now in 12 | your Terraform state and will henceforth be managed by Terraform. 13 | ``` 14 | 15 | :put_litter_in_its_place: A plan file was discarded. Re-plan would be required before applying. 16 | 17 | * :repeat: To **plan** this project again, comment: 18 | * `atlantis plan -d .` -------------------------------------------------------------------------------- /runatlantis.io/.vuepress/public/checkmark.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/state-rm-workspace/exp-output-import-dummy1.txt: -------------------------------------------------------------------------------- 1 | Ran Import for project: `dir1-ops` dir: `dir1` workspace: `ops` 2 | 3 | ```diff 4 | random_id.dummy1[0]: Importing from ID "AA"... 5 | random_id.dummy1[0]: Import prepared! 6 | Prepared random_id for import 7 | random_id.dummy1[0]: Refreshing state... [id=AA] 8 | 9 | Import successful! 10 | 11 | The resources that were imported are shown above. These resources are now in 12 | your Terraform state and will henceforth be managed by Terraform. 13 | ``` 14 | 15 | :put_litter_in_its_place: A plan file was discarded. Re-plan would be required before applying. 16 | 17 | * :repeat: To **plan** this project again, comment: 18 | * `atlantis plan -p dir1-ops` -------------------------------------------------------------------------------- /server/events/command_type.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 HootSuite Media Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the License); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // Unless required by applicable law or agreed to in writing, software 8 | // distributed under the License is distributed on an AS IS BASIS, 9 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | // See the License for the specific language governing permissions and 11 | // limitations under the License. 12 | // Modified hereafter by contributors to runatlantis/atlantis. 13 | 14 | package events 15 | -------------------------------------------------------------------------------- /server/events/vcs/testdata/github-branch-protection-required-checks.json: -------------------------------------------------------------------------------- 1 | { 2 | "url": "https://api.github.com/repos/octocat/Hello-World/branches/master/protection", 3 | "required_status_checks": { 4 | "url": "https://api.github.com/repos/octocat/Hello-World/branches/master/protection/required_status_checks", 5 | "strict": true, 6 | "contexts": [ 7 | "atlantis/apply" 8 | ], 9 | "contexts_url": "https://api.github.com/repos/octocat/Hello-World/branches/master/protection/required_status_checks/contexts", 10 | "checks": [ 11 | { 12 | "context": "atlantis/apply", 13 | "app_id": 123456 14 | } 15 | ] 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/simple-yaml/atlantis.yaml: -------------------------------------------------------------------------------- 1 | version: 3 2 | projects: 3 | - dir: . 4 | workspace: default 5 | workflow: default 6 | - dir: . 7 | workspace: staging 8 | workflow: staging 9 | workflows: 10 | default: 11 | # Only specify plan so should use default apply workflow. 12 | plan: 13 | steps: 14 | - run: echo preinit 15 | - init 16 | - plan: 17 | extra_args: [-var, var=fromconfig] 18 | - run: echo postplan 19 | staging: 20 | plan: 21 | steps: 22 | - init 23 | - plan: 24 | extra_args: [-var-file, staging.tfvars] 25 | apply: 26 | steps: 27 | - run: echo preapply 28 | - apply 29 | - run: echo postapply 30 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/tfvars-yaml/atlantis.yaml: -------------------------------------------------------------------------------- 1 | version: 3 2 | projects: 3 | - dir: . 4 | name: default 5 | workflow: default 6 | - dir: . 7 | workflow: staging 8 | name: staging 9 | workflows: 10 | default: 11 | plan: 12 | steps: 13 | - run: rm -rf .terraform 14 | - init: 15 | extra_args: [-backend-config=default.backend.tfvars] 16 | - plan: 17 | extra_args: [-var-file=default.tfvars] 18 | - run: echo workspace=$WORKSPACE 19 | staging: 20 | plan: 21 | steps: 22 | - run: rm -rf .terraform 23 | - init: 24 | extra_args: [-backend-config=staging.backend.tfvars] 25 | - plan: 26 | extra_args: [-var-file, staging.tfvars] 27 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/import-workspace/exp-output-import-dir1-ops-dummy1.txt: -------------------------------------------------------------------------------- 1 | Ran Import for project: `dir1-ops` dir: `dir1` workspace: `ops` 2 | 3 | ```diff 4 | random_id.dummy1[0]: Importing from ID "AA"... 5 | random_id.dummy1[0]: Import prepared! 6 | Prepared random_id for import 7 | random_id.dummy1[0]: Refreshing state... [id=AA] 8 | 9 | Import successful! 10 | 11 | The resources that were imported are shown above. These resources are now in 12 | your Terraform state and will henceforth be managed by Terraform. 13 | ``` 14 | 15 | :put_litter_in_its_place: A plan file was discarded. Re-plan would be required before applying. 16 | 17 | * :repeat: To **plan** this project again, comment: 18 | * `atlantis plan -p dir1-ops` 19 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/import-workspace/exp-output-import-dir1-ops-dummy2.txt: -------------------------------------------------------------------------------- 1 | Ran Import for project: `dir1-ops` dir: `dir1` workspace: `ops` 2 | 3 | ```diff 4 | random_id.dummy2[0]: Importing from ID "BB"... 5 | random_id.dummy2[0]: Import prepared! 6 | Prepared random_id for import 7 | random_id.dummy2[0]: Refreshing state... [id=BB] 8 | 9 | Import successful! 10 | 11 | The resources that were imported are shown above. These resources are now in 12 | your Terraform state and will henceforth be managed by Terraform. 13 | ``` 14 | 15 | :put_litter_in_its_place: A plan file was discarded. Re-plan would be required before applying. 16 | 17 | * :repeat: To **plan** this project again, comment: 18 | * `atlantis plan -p dir1-ops` 19 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/import-single-project-var/exp-output-import-foreach.txt: -------------------------------------------------------------------------------- 1 | Ran Import for dir: `.` workspace: `default` 2 | 3 | ```diff 4 | random_id.for_each["overridden"]: Importing from ID "AA"... 5 | random_id.for_each["overridden"]: Import prepared! 6 | Prepared random_id for import 7 | random_id.for_each["overridden"]: Refreshing state... [id=AA] 8 | 9 | Import successful! 10 | 11 | The resources that were imported are shown above. These resources are now in 12 | your Terraform state and will henceforth be managed by Terraform. 13 | ``` 14 | 15 | :put_litter_in_its_place: A plan file was discarded. Re-plan would be required before applying. 16 | 17 | * :repeat: To **plan** this project again, comment: 18 | * `atlantis plan -d .` -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/state-rm-single-project/exp-output-import-foreach.txt: -------------------------------------------------------------------------------- 1 | Ran Import for dir: `.` workspace: `default` 2 | 3 | ```diff 4 | random_id.for_each["overridden"]: Importing from ID "BB"... 5 | random_id.for_each["overridden"]: Import prepared! 6 | Prepared random_id for import 7 | random_id.for_each["overridden"]: Refreshing state... [id=BB] 8 | 9 | Import successful! 10 | 11 | The resources that were imported are shown above. These resources are now in 12 | your Terraform state and will henceforth be managed by Terraform. 13 | ``` 14 | 15 | :put_litter_in_its_place: A plan file was discarded. Re-plan would be required before applying. 16 | 17 | * :repeat: To **plan** this project again, comment: 18 | * `atlantis plan -d .` -------------------------------------------------------------------------------- /server/core/config/raw/raw.go: -------------------------------------------------------------------------------- 1 | // Package raw contains the golang representations of the YAML elements 2 | // supported in atlantis.yaml. The structs here represent the exact data that 3 | // comes from the file before it is parsed/validated further. 4 | package raw 5 | 6 | import ( 7 | version "github.com/hashicorp/go-version" 8 | "github.com/pkg/errors" 9 | ) 10 | 11 | // VersionValidator helper function to validate binary version. 12 | // Function implements ozzo-validation::Rule.Validate interface. 13 | func VersionValidator(value interface{}) error { 14 | strPtr := value.(*string) 15 | if strPtr == nil { 16 | return nil 17 | } 18 | _, err := version.NewVersion(*strPtr) 19 | return errors.Wrapf(err, "version %q could not be parsed", *strPtr) 20 | } 21 | -------------------------------------------------------------------------------- /e2e/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/runatlantis/atlantis/e2e 2 | 3 | go 1.21 4 | 5 | require ( 6 | github.com/google/go-github/v54 v54.0.0 7 | github.com/hashicorp/go-multierror v1.1.1 8 | ) 9 | 10 | require ( 11 | github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8 // indirect 12 | github.com/cloudflare/circl v1.3.3 // indirect 13 | github.com/golang/protobuf v1.5.3 // indirect 14 | github.com/google/go-querystring v1.1.0 // indirect 15 | github.com/hashicorp/errwrap v1.1.0 // indirect 16 | golang.org/x/crypto v0.12.0 // indirect 17 | golang.org/x/net v0.14.0 // indirect 18 | golang.org/x/oauth2 v0.11.0 // indirect 19 | golang.org/x/sys v0.11.0 // indirect 20 | google.golang.org/appengine v1.6.7 // indirect 21 | google.golang.org/protobuf v1.31.0 // indirect 22 | ) 23 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/tfvars-yaml-no-autoplan/atlantis.yaml: -------------------------------------------------------------------------------- 1 | version: 3 2 | projects: 3 | - dir: . 4 | name: default 5 | workflow: default 6 | autoplan: 7 | enabled: false 8 | - dir: . 9 | workflow: staging 10 | name: staging 11 | autoplan: 12 | enabled: false 13 | workflows: 14 | default: 15 | plan: 16 | steps: 17 | - run: rm -rf .terraform 18 | - init: 19 | extra_args: [-backend-config=default.backend.tfvars] 20 | - plan: 21 | extra_args: [-var-file=default.tfvars] 22 | staging: 23 | plan: 24 | steps: 25 | - run: rm -rf .terraform 26 | - init: 27 | extra_args: [-backend-config=staging.backend.tfvars] 28 | - plan: 29 | extra_args: [-var-file, staging.tfvars] 30 | -------------------------------------------------------------------------------- /server/events/templates/plan_success_unwrapped.tmpl: -------------------------------------------------------------------------------- 1 | {{ define "planSuccessUnwrapped" -}} 2 | ```diff 3 | {{ if .EnableDiffMarkdownFormat }}{{ .DiffMarkdownFormattedTerraformOutput }}{{ else }}{{ .TerraformOutput }}{{ end }} 4 | ``` 5 | 6 | {{ if .PlanWasDeleted -}} 7 | This plan was not saved because one or more projects failed and automerge requires all plans pass. 8 | {{ else -}} 9 | {{ if not .DisableApply -}} 10 | * :arrow_forward: To **apply** this plan, comment: 11 | * `{{ .ApplyCmd }}` 12 | {{ end -}} 13 | {{ if not .DisableRepoLocking -}} 14 | * :put_litter_in_its_place: To **delete** this plan click [here]({{ .LockURL }}) 15 | {{ end -}} 16 | * :repeat: To **plan** this project again, comment: 17 | * `{{ .RePlanCmd }}` 18 | {{ end -}} 19 | {{ template "diverged" . }} 20 | {{ end -}} 21 | -------------------------------------------------------------------------------- /server/events/vcs/client_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 HootSuite Media Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the License); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // Unless required by applicable law or agreed to in writing, software 8 | // distributed under the License is distributed on an AS IS BASIS, 9 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | // See the License for the specific language governing permissions and 11 | // limitations under the License. 12 | // Modified hereafter by contributors to runatlantis/atlantis. 13 | 14 | package vcs 15 | 16 | // purposefully empty to trigger coverage report 17 | -------------------------------------------------------------------------------- /runatlantis.io/.vuepress/public/powerful.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## what 2 | 3 | 7 | 8 | 9 | ## why 10 | 11 | 16 | 17 | ## tests 18 | 19 | 22 | 23 | ## references 24 | 25 | 29 | 30 | -------------------------------------------------------------------------------- /.github/workflows/lint.yml: -------------------------------------------------------------------------------- 1 | name: linter 2 | 3 | on: 4 | pull_request: 5 | types: 6 | - opened 7 | - reopened 8 | - synchronize 9 | - ready_for_review 10 | branches: 11 | - "main" 12 | paths: 13 | - '**.go' 14 | - 'go.*' 15 | - '.github/workflows/lint.yml' 16 | - '.golangci.yml' 17 | 18 | concurrency: 19 | group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} 20 | cancel-in-progress: true 21 | 22 | jobs: 23 | golangci-lint: 24 | if: github.event.pull_request.draft == false 25 | name: runner / golangci-lint 26 | runs-on: ubuntu-22.04 27 | steps: 28 | - uses: actions/checkout@v3 29 | - name: golangci-lint 30 | uses: reviewdog/action-golangci-lint@v2 31 | with: 32 | tool_name: golangci-lint 33 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-multi-projects/policies/policy.rego: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import input as tfplan 4 | 5 | deny[reason] { 6 | num_creates[_] > 0 7 | reason := "WARNING: Forbidden Resource creation is prohibited." 8 | } 9 | 10 | resource_names = {"forbidden"} 11 | 12 | resources[resource_name] = all { 13 | some resource_name 14 | resource_names[resource_name] 15 | all := [res | 16 | res := tfplan.resource_changes[_] 17 | res.name == resource_name 18 | ] 19 | } 20 | 21 | # number of creations of resources of a given name 22 | num_creates[resource_name] = num { 23 | some resource_name 24 | resource_names[resource_name] 25 | all := resources[resource_name] 26 | creations := [res | res := all[_]; res.change.actions[_] == "create"] 27 | num := count(creations) 28 | } 29 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks/policies/policy.rego: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import input as tfplan 4 | 5 | deny[reason] { 6 | num_deletes.null_resource > 0 7 | reason := "WARNING: Null Resource creation is prohibited." 8 | } 9 | 10 | resource_types = {"null_resource"} 11 | 12 | resources[resource_type] = all { 13 | some resource_type 14 | resource_types[resource_type] 15 | all := [name | 16 | name := tfplan.resource_changes[_] 17 | name.type == resource_type 18 | ] 19 | } 20 | 21 | # number of deletions of resources of a given type 22 | num_deletes[resource_type] = num { 23 | some resource_type 24 | resource_types[resource_type] 25 | all := resources[resource_type] 26 | deletions := [res | res := all[_]; res.change.actions[_] == "create"] 27 | num := count(deletions) 28 | } 29 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/repo-config-file/exp-output-apply.txt: -------------------------------------------------------------------------------- 1 | Ran Apply for 2 projects: 2 | 3 | 1. dir: `infrastructure/production` workspace: `default` 4 | 1. dir: `infrastructure/staging` workspace: `default` 5 | 6 | ### 1. dir: `infrastructure/production` workspace: `default` 7 | ```diff 8 | null_resource.production[0]: Creating... 9 | null_resource.production[0]: Creation complete after *s [id=*******************] 10 | 11 | Apply complete! Resources: 1 added, 0 changed, 0 destroyed. 12 | ``` 13 | 14 | --- 15 | ### 2. dir: `infrastructure/staging` workspace: `default` 16 | ```diff 17 | null_resource.staging[0]: Creating... 18 | null_resource.staging[0]: Creation complete after *s [id=*******************] 19 | 20 | Apply complete! Resources: 1 added, 0 changed, 0 destroyed. 21 | ``` 22 | 23 | --- -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-apply-reqs/policies/policy.rego: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import input as tfplan 4 | 5 | deny[reason] { 6 | num_deletes.null_resource > 0 7 | reason := "WARNING: Null Resource creation is prohibited." 8 | } 9 | 10 | resource_types = {"null_resource"} 11 | 12 | resources[resource_type] = all { 13 | some resource_type 14 | resource_types[resource_type] 15 | all := [name | 16 | name := tfplan.resource_changes[_] 17 | name.type == resource_type 18 | ] 19 | } 20 | 21 | # number of deletions of resources of a given type 22 | num_deletes[resource_type] = num { 23 | some resource_type 24 | resource_types[resource_type] 25 | all := resources[resource_type] 26 | deletions := [res | res := all[_]; res.change.actions[_] == "create"] 27 | num := count(deletions) 28 | } 29 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-diff-owner/policies/policy.rego: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import input as tfplan 4 | 5 | deny[reason] { 6 | num_deletes.null_resource > 0 7 | reason := "WARNING: Null Resource creation is prohibited." 8 | } 9 | 10 | resource_types = {"null_resource"} 11 | 12 | resources[resource_type] = all { 13 | some resource_type 14 | resource_types[resource_type] 15 | all := [name | 16 | name := tfplan.resource_changes[_] 17 | name.type == resource_type 18 | ] 19 | } 20 | 21 | # number of deletions of resources of a given type 22 | num_deletes[resource_type] = num { 23 | some resource_type 24 | resource_types[resource_type] 25 | all := resources[resource_type] 26 | deletions := [res | res := all[_]; res.change.actions[_] == "create"] 27 | num := count(deletions) 28 | } 29 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-disabled-repo/policies/policy.rego: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import input as tfplan 4 | 5 | deny[reason] { 6 | num_deletes.null_resource > 0 7 | reason := "WARNING: Null Resource creation is prohibited." 8 | } 9 | 10 | resource_types = {"null_resource"} 11 | 12 | resources[resource_type] = all { 13 | some resource_type 14 | resource_types[resource_type] 15 | all := [name | 16 | name := tfplan.resource_changes[_] 17 | name.type == resource_type 18 | ] 19 | } 20 | 21 | # number of deletions of resources of a given type 22 | num_deletes[resource_type] = num { 23 | some resource_type 24 | resource_types[resource_type] 25 | all := resources[resource_type] 26 | deletions := [res | res := all[_]; res.change.actions[_] == "create"] 27 | num := count(deletions) 28 | } 29 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-enabled-repo/policies/policy.rego: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import input as tfplan 4 | 5 | deny[reason] { 6 | num_deletes.null_resource > 0 7 | reason := "WARNING: Null Resource creation is prohibited." 8 | } 9 | 10 | resource_types = {"null_resource"} 11 | 12 | resources[resource_type] = all { 13 | some resource_type 14 | resource_types[resource_type] 15 | all := [name | 16 | name := tfplan.resource_changes[_] 17 | name.type == resource_type 18 | ] 19 | } 20 | 21 | # number of deletions of resources of a given type 22 | num_deletes[resource_type] = num { 23 | some resource_type 24 | resource_types[resource_type] 25 | all := resources[resource_type] 26 | deletions := [res | res := all[_]; res.change.actions[_] == "create"] 27 | num := count(deletions) 28 | } 29 | -------------------------------------------------------------------------------- /server/events/command/result.go: -------------------------------------------------------------------------------- 1 | package command 2 | 3 | // Result is the result of running a Command. 4 | type Result struct { 5 | Error error 6 | Failure string 7 | ProjectResults []ProjectResult 8 | // PlansDeleted is true if all plans created during this command were 9 | // deleted. This happens if automerging is enabled and one project has an 10 | // error since automerging requires all plans to succeed. 11 | PlansDeleted bool 12 | } 13 | 14 | // HasErrors returns true if there were any errors during the execution, 15 | // even if it was only in one project. 16 | func (c Result) HasErrors() bool { 17 | if c.Error != nil || c.Failure != "" { 18 | return true 19 | } 20 | for _, r := range c.ProjectResults { 21 | if !r.IsSuccessful() { 22 | return true 23 | } 24 | } 25 | return false 26 | } 27 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-clear-approval/policies/policy.rego: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import input as tfplan 4 | 5 | deny[reason] { 6 | num_deletes.null_resource > 0 7 | reason := "WARNING: Null Resource creation is prohibited." 8 | } 9 | 10 | resource_types = {"null_resource"} 11 | 12 | resources[resource_type] = all { 13 | some resource_type 14 | resource_types[resource_type] 15 | all := [name | 16 | name := tfplan.resource_changes[_] 17 | name.type == resource_type 18 | ] 19 | } 20 | 21 | # number of deletions of resources of a given type 22 | num_deletes[resource_type] = num { 23 | some resource_type 24 | resource_types[resource_type] 25 | all := resources[resource_type] 26 | deletions := [res | res := all[_]; res.change.actions[_] == "create"] 27 | num := count(deletions) 28 | } 29 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-custom-run-steps/policies/policy.rego: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import input as tfplan 4 | 5 | deny[reason] { 6 | num_deletes.null_resource > 0 7 | reason := "WARNING: Null Resource creation is prohibited." 8 | } 9 | 10 | resource_types = {"null_resource"} 11 | 12 | resources[resource_type] = all { 13 | some resource_type 14 | resource_types[resource_type] 15 | all := [name | 16 | name := tfplan.resource_changes[_] 17 | name.type == resource_type 18 | ] 19 | } 20 | 21 | # number of deletions of resources of a given type 22 | num_deletes[resource_type] = num { 23 | some resource_type 24 | resource_types[resource_type] 25 | all := resources[resource_type] 26 | deletions := [res | res := all[_]; res.change.actions[_] == "create"] 27 | num := count(deletions) 28 | } 29 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-success-silent/policies/policy.rego: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import input as tfplan 4 | 5 | deny[reason] { 6 | num_deletes.null_resource > 0 7 | reason := "WARNING: Null Resource creation is prohibited." 8 | } 9 | 10 | resource_types = {"null_resource"} 11 | 12 | resources[resource_type] = all { 13 | some resource_type 14 | resource_types[resource_type] 15 | all := [name | 16 | name := tfplan.resource_changes[_] 17 | name.type == resource_type 18 | ] 19 | } 20 | 21 | # number of deletions of resources of a given type 22 | num_deletes[resource_type] = num { 23 | some resource_type 24 | resource_types[resource_type] 25 | all := resources[resource_type] 26 | deletions := [res | res := all[_]; res.change.actions[_] == "create"] 27 | num := count(deletions) 28 | } 29 | -------------------------------------------------------------------------------- /server/events/templates/single_project_policy_unsuccessful.tmpl: -------------------------------------------------------------------------------- 1 | {{ define "singleProjectPolicyUnsuccessful" -}} 2 | {{ $result := index .Results 0 -}} 3 | Ran {{ .Command }} for {{ if $result.ProjectName }}project: `{{ $result.ProjectName }}` {{ end }}dir: `{{ $result.RepoRelDir }}` workspace: `{{ $result.Workspace }}` 4 | 5 | {{ $result.Rendered }} 6 | {{ if ne .DisableApplyAll true }} 7 | --- 8 | * :heavy_check_mark: To **approve** all unapplied plans from this pull request, comment: 9 | * `{{ .ExecutableName }} approve_policies` 10 | * :put_litter_in_its_place: To delete all plans and locks for the PR, comment: 11 | * `{{ .ExecutableName }} unlock` 12 | * :repeat: To re-run policies **plan** this project again by commenting: 13 | * `{{ .ExecutableName }} plan` 14 | {{ end -}} 15 | {{- template "log" . -}} 16 | {{ end -}} 17 | -------------------------------------------------------------------------------- /runatlantis.io/docs/README.md: -------------------------------------------------------------------------------- 1 | # Atlantis Documentation 2 | 3 | These docs are for users that are ready to get Atlantis installed and start using it. 4 | 5 | :::tip Looking to get started? 6 | If you're new here, check out the [Guide](/guide/) 7 | where you can try our [Test Drive](/guide/test-drive.html) or [Run Atlantis Locally](/guide/testing-locally.html). 8 | ::: 9 | 10 | ### Next Steps 11 | * [Installing Atlantis](/docs/installation-guide.html)  –  Get Atlantis up and running 12 | * [Configuring Atlantis](configuring-atlantis.html)  –  Configure how Atlantis works for your specific use-cases 13 | * [Using Atlantis](using-atlantis.html)  –  How do you use Atlantis? 14 | * [How Atlantis Works](how-atlantis-works.html)  –  Internals of what Atlantis is doing 15 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-disabled-previous-match/policies/policy.rego: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import input as tfplan 4 | 5 | deny[reason] { 6 | num_deletes.null_resource > 0 7 | reason := "WARNING: Null Resource creation is prohibited." 8 | } 9 | 10 | resource_types = {"null_resource"} 11 | 12 | resources[resource_type] = all { 13 | some resource_type 14 | resource_types[resource_type] 15 | all := [name | 16 | name := tfplan.resource_changes[_] 17 | name.type == resource_type 18 | ] 19 | } 20 | 21 | # number of deletions of resources of a given type 22 | num_deletes[resource_type] = num { 23 | some resource_type 24 | resource_types[resource_type] 25 | all := resources[resource_type] 26 | deletions := [res | res := all[_]; res.change.actions[_] == "create"] 27 | num := count(deletions) 28 | } 29 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-disabled-repo-server-side/policies/policy.rego: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import input as tfplan 4 | 5 | deny[reason] { 6 | num_deletes.null_resource > 0 7 | reason := "WARNING: Null Resource creation is prohibited." 8 | } 9 | 10 | resource_types = {"null_resource"} 11 | 12 | resources[resource_type] = all { 13 | some resource_type 14 | resource_types[resource_type] 15 | all := [name | 16 | name := tfplan.resource_changes[_] 17 | name.type == resource_type 18 | ] 19 | } 20 | 21 | # number of deletions of resources of a given type 22 | num_deletes[resource_type] = num { 23 | some resource_type 24 | resource_types[resource_type] 25 | all := resources[resource_type] 26 | deletions := [res | res := all[_]; res.change.actions[_] == "create"] 27 | num := count(deletions) 28 | } 29 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-enabled-repo-server-side/policies/policy.rego: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import input as tfplan 4 | 5 | deny[reason] { 6 | num_deletes.null_resource > 0 7 | reason := "WARNING: Null Resource creation is prohibited." 8 | } 9 | 10 | resource_types = {"null_resource"} 11 | 12 | resources[resource_type] = all { 13 | some resource_type 14 | resource_types[resource_type] 15 | all := [name | 16 | name := tfplan.resource_changes[_] 17 | name.type == resource_type 18 | ] 19 | } 20 | 21 | # number of deletions of resources of a given type 22 | num_deletes[resource_type] = num { 23 | some resource_type 24 | resource_types[resource_type] 25 | all := resources[resource_type] 26 | deletions := [res | res := all[_]; res.change.actions[_] == "create"] 27 | num := count(deletions) 28 | } 29 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-extra-args/policies/policy.rego: -------------------------------------------------------------------------------- 1 | package null_resource_policy 2 | 3 | import input as tfplan 4 | 5 | deny[reason] { 6 | num_deletes.null_resource > 0 7 | reason := "WARNING: Null Resource creation is prohibited." 8 | } 9 | 10 | resource_types = {"null_resource"} 11 | 12 | resources[resource_type] = all { 13 | some resource_type 14 | resource_types[resource_type] 15 | all := [name | 16 | name := tfplan.resource_changes[_] 17 | name.type == resource_type 18 | ] 19 | } 20 | 21 | # number of deletions of resources of a given type 22 | num_deletes[resource_type] = num { 23 | some resource_type 24 | resource_types[resource_type] 25 | all := resources[resource_type] 26 | deletions := [res | res := all[_]; res.change.actions[_] == "create"] 27 | num := count(deletions) 28 | } 29 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-success-silent/exp-output-autoplan.txt: -------------------------------------------------------------------------------- 1 | Ran Plan for dir: `.` workspace: `default` 2 | 3 | ```diff 4 | Changes to Outputs: 5 | + workspace = "default" 6 | 7 | You can apply this plan to save these new output values to the Terraform 8 | state, without changing any real infrastructure. 9 | ``` 10 | 11 | * :arrow_forward: To **apply** this plan, comment: 12 | * `atlantis apply -d .` 13 | * :put_litter_in_its_place: To **delete** this plan click [here](lock-url) 14 | * :repeat: To **plan** this project again, comment: 15 | * `atlantis plan -d .` 16 | 17 | --- 18 | * :fast_forward: To **apply** all unapplied plans from this pull request, comment: 19 | * `atlantis apply` 20 | * :put_litter_in_its_place: To delete all plans and locks for the PR, comment: 21 | * `atlantis unlock` -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/simple-yaml/exp-output-apply-all.txt: -------------------------------------------------------------------------------- 1 | Ran Apply for 2 projects: 2 | 3 | 1. dir: `.` workspace: `default` 4 | 1. dir: `.` workspace: `staging` 5 | 6 | ### 1. dir: `.` workspace: `default` 7 | ```diff 8 | null_resource.simple: 9 | null_resource.simple: 10 | 11 | Apply complete! Resources: 1 added, 0 changed, 0 destroyed. 12 | 13 | Outputs: 14 | 15 | var = "fromconfig" 16 | workspace = "default" 17 | ``` 18 | 19 | --- 20 | ### 2. dir: `.` workspace: `staging` 21 |
Show Output 22 | 23 | ```diff 24 | preapply 25 | 26 | null_resource.simple: 27 | null_resource.simple: 28 | 29 | Apply complete! Resources: 1 added, 0 changed, 0 destroyed. 30 | 31 | Outputs: 32 | 33 | var = "fromfile" 34 | workspace = "staging" 35 | 36 | postapply 37 | ``` 38 | 39 |
40 | 41 | --- -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/import-single-project/exp-output-plan-again.txt: -------------------------------------------------------------------------------- 1 | Ran Plan for dir: `.` workspace: `default` 2 | 3 | ```diff 4 | No changes. Your infrastructure matches the configuration. 5 | 6 | Terraform has compared your real infrastructure against your configuration 7 | and found no differences, so no changes are needed. 8 | ``` 9 | 10 | * :arrow_forward: To **apply** this plan, comment: 11 | * `atlantis apply -d .` 12 | * :put_litter_in_its_place: To **delete** this plan click [here](lock-url) 13 | * :repeat: To **plan** this project again, comment: 14 | * `atlantis plan -d .` 15 | 16 | --- 17 | * :fast_forward: To **apply** all unapplied plans from this pull request, comment: 18 | * `atlantis apply` 19 | * :put_litter_in_its_place: To delete all plans and locks for the PR, comment: 20 | * `atlantis unlock` -------------------------------------------------------------------------------- /cmd/cmd.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 HootSuite Media Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the License); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // Unless required by applicable law or agreed to in writing, software 8 | // distributed under the License is distributed on an AS IS BASIS, 9 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | // See the License for the specific language governing permissions and 11 | // limitations under the License. 12 | // Modified hereafter by contributors to runatlantis/atlantis. 13 | 14 | // Package cmd provides all CLI commands. 15 | // NOTE: These are different from the commands that get run via pull request 16 | // comments. 17 | package cmd 18 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/state-rm-single-project/exp-output-plan.txt: -------------------------------------------------------------------------------- 1 | Ran Plan for dir: `.` workspace: `default` 2 | 3 | ```diff 4 | No changes. Your infrastructure matches the configuration. 5 | 6 | Terraform has compared your real infrastructure against your configuration 7 | and found no differences, so no changes are needed. 8 | ``` 9 | 10 | * :arrow_forward: To **apply** this plan, comment: 11 | * `atlantis apply -d .` 12 | * :put_litter_in_its_place: To **delete** this plan click [here](lock-url) 13 | * :repeat: To **plan** this project again, comment: 14 | * `atlantis plan -d . -- -var var=overridden` 15 | 16 | --- 17 | * :fast_forward: To **apply** all unapplied plans from this pull request, comment: 18 | * `atlantis apply` 19 | * :put_litter_in_its_place: To delete all plans and locks for the PR, comment: 20 | * `atlantis unlock` -------------------------------------------------------------------------------- /server/metrics/scope_test.go: -------------------------------------------------------------------------------- 1 | package metrics_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/runatlantis/atlantis/server/core/config/valid" 7 | "github.com/runatlantis/atlantis/server/metrics" 8 | ) 9 | 10 | var ( 11 | prometheusConfig = valid.Metrics{ 12 | Prometheus: &valid.Prometheus{ 13 | Endpoint: "/metrics", 14 | }, 15 | } 16 | ) 17 | 18 | func TestNewScope_PrometheusTaggingCapabilities(t *testing.T) { 19 | scope, _, _, err := metrics.NewScope(prometheusConfig, nil, "test") 20 | if err != nil { 21 | t.Fatalf("got an error: %s", err.Error()) 22 | } 23 | 24 | scope.Tagged(map[string]string{ 25 | "base_repo": "runatlantis/atlantis", 26 | "pr_number": "2687", 27 | }) 28 | 29 | want := true 30 | got := scope.Capabilities().Tagging() 31 | if want != got { 32 | t.Errorf("Scope does not have Capability to do Tagging") 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/import-single-project-var/exp-output-plan-again.txt: -------------------------------------------------------------------------------- 1 | Ran Plan for dir: `.` workspace: `default` 2 | 3 | ```diff 4 | No changes. Your infrastructure matches the configuration. 5 | 6 | Terraform has compared your real infrastructure against your configuration 7 | and found no differences, so no changes are needed. 8 | ``` 9 | 10 | * :arrow_forward: To **apply** this plan, comment: 11 | * `atlantis apply -d .` 12 | * :put_litter_in_its_place: To **delete** this plan click [here](lock-url) 13 | * :repeat: To **plan** this project again, comment: 14 | * `atlantis plan -d . -- -var var=overridden` 15 | 16 | --- 17 | * :fast_forward: To **apply** all unapplied plans from this pull request, comment: 18 | * `atlantis apply` 19 | * :put_litter_in_its_place: To delete all plans and locks for the PR, comment: 20 | * `atlantis unlock` -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/import-workspace/exp-output-plan.txt: -------------------------------------------------------------------------------- 1 | Ran Plan for project: `dir1-ops` dir: `dir1` workspace: `ops` 2 | 3 | ```diff 4 | No changes. Your infrastructure matches the configuration. 5 | 6 | Terraform has compared your real infrastructure against your configuration 7 | and found no differences, so no changes are needed. 8 | ``` 9 | 10 | * :arrow_forward: To **apply** this plan, comment: 11 | * `atlantis apply -p dir1-ops` 12 | * :put_litter_in_its_place: To **delete** this plan click [here](lock-url) 13 | * :repeat: To **plan** this project again, comment: 14 | * `atlantis plan -p dir1-ops` 15 | 16 | --- 17 | * :fast_forward: To **apply** all unapplied plans from this pull request, comment: 18 | * `atlantis apply` 19 | * :put_litter_in_its_place: To delete all plans and locks for the PR, comment: 20 | * `atlantis unlock` 21 | -------------------------------------------------------------------------------- /.github/workflows/stale.yml: -------------------------------------------------------------------------------- 1 | name: Close Stale PRs 2 | on: 3 | schedule: 4 | - cron: '30 1 * * *' 5 | jobs: 6 | stale: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - uses: actions/stale@v8 10 | with: 11 | stale-pr-message: 'This issue is stale because it has been open for 1 month with no activity. Remove stale label or comment or this will be closed in 1 month.' 12 | stale-issue-message: This issue is stale because it has been open for 1 month with no activity. Remove stale label or comment or this will be closed in 1 month.' 13 | remove-stale-when-updated: true 14 | exempt-pr-labels: "never-stale" 15 | exempt-issue-labels: "never-stale" 16 | # 1 month 17 | days-before-stale: 31 18 | # 1 month 19 | days-before-close: 31 20 | only-labels: 'waiting-on-response' 21 | -------------------------------------------------------------------------------- /server/events/templates/plan_success_wrapped.tmpl: -------------------------------------------------------------------------------- 1 | {{ define "planSuccessWrapped" -}} 2 |
Show Output 3 | 4 | ```diff 5 | {{ if .EnableDiffMarkdownFormat }}{{ .DiffMarkdownFormattedTerraformOutput }}{{ else }}{{ .TerraformOutput }}{{ end }} 6 | ``` 7 | 8 | {{ if .PlanWasDeleted -}} 9 | This plan was not saved because one or more projects failed and automerge requires all plans pass. 10 | {{ else -}} 11 | {{ if not .DisableApply -}} 12 | * :arrow_forward: To **apply** this plan, comment: 13 | * `{{ .ApplyCmd }}` 14 | {{ end -}} 15 | {{ if not .DisableRepoLocking -}} 16 | * :put_litter_in_its_place: To **delete** this plan click [here]({{ .LockURL }}) 17 | {{ end -}} 18 | * :repeat: To **plan** this project again, comment: 19 | * `{{ .RePlanCmd }}` 20 | {{ end -}} 21 |
22 | {{ .PlanSummary -}} 23 | {{ template "diverged" . -}} 24 | {{ end -}} 25 | -------------------------------------------------------------------------------- /.github/workflows/atlantis-image-required.yml: -------------------------------------------------------------------------------- 1 | # For required checks when path filtering doesn't trigger the other job 2 | # https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/defining-the-mergeability-of-pull-requests/troubleshooting-required-status-checks#handling-skipped-but-required-checks 3 | 4 | name: atlantis-image 5 | 6 | on: 7 | pull_request: 8 | paths-ignore: 9 | - 'Dockerfile' 10 | - 'docker-entrypoint.sh' 11 | - '.github/workflows/atlantis-image.yml' 12 | - '**.go' 13 | - 'go.*' 14 | 15 | concurrency: 16 | group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} 17 | cancel-in-progress: true 18 | 19 | jobs: 20 | build: 21 | strategy: 22 | matrix: 23 | image_type: [alpine, debian] 24 | runs-on: ubuntu-latest 25 | steps: 26 | - run: 'echo "No build required"' 27 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: tester 2 | 3 | on: 4 | push: 5 | branches: 6 | - "main" 7 | paths: 8 | - '**.go' 9 | - 'go.*' 10 | - '.github/workflows/test.yml' 11 | pull_request: 12 | types: 13 | - opened 14 | - reopened 15 | - synchronize 16 | - ready_for_review 17 | branches: 18 | - "main" 19 | paths: 20 | - '**.go' 21 | - 'go.*' 22 | - '.github/workflows/test.yml' 23 | 24 | concurrency: 25 | group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} 26 | cancel-in-progress: true 27 | 28 | jobs: 29 | test: 30 | if: github.event.pull_request.draft == false 31 | name: runner / gotest 32 | runs-on: ubuntu-22.04 33 | container: ghcr.io/runatlantis/testing-env:latest 34 | steps: 35 | - uses: actions/checkout@v3 36 | - run: make test-all 37 | - run: make check-fmt 38 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/state-rm-multiple-project/exp-output-state-rm-multiple-projects.txt: -------------------------------------------------------------------------------- 1 | Ran State for 2 projects: 2 | 3 | 1. dir: `dir1` workspace: `default` 4 | 1. dir: `dir2` workspace: `default` 5 | 6 | ### 1. dir: `dir1` workspace: `default` 7 | ```diff 8 | Removed random_id.dummy 9 | Successfully removed 1 resource instance(s). 10 | ``` 11 | 12 | :put_litter_in_its_place: A plan file was discarded. Re-plan would be required before applying. 13 | 14 | * :repeat: To **plan** this project again, comment: 15 | * `atlantis plan -d dir1` 16 | 17 | --- 18 | ### 2. dir: `dir2` workspace: `default` 19 | ```diff 20 | Removed random_id.dummy 21 | Successfully removed 1 resource instance(s). 22 | ``` 23 | 24 | :put_litter_in_its_place: A plan file was discarded. Re-plan would be required before applying. 25 | 26 | * :repeat: To **plan** this project again, comment: 27 | * `atlantis plan -d dir2` 28 | 29 | --- -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/state-rm-workspace/exp-output-plan.txt: -------------------------------------------------------------------------------- 1 | Ran Plan for project: `dir1-ops` dir: `dir1` workspace: `ops` 2 | 3 | ```diff 4 | random_id.dummy1[0]: Refreshing state... [id=AA] 5 | 6 | No changes. Your infrastructure matches the configuration. 7 | 8 | Terraform has compared your real infrastructure against your configuration 9 | and found no differences, so no changes are needed. 10 | ``` 11 | 12 | * :arrow_forward: To **apply** this plan, comment: 13 | * `atlantis apply -p dir1-ops` 14 | * :put_litter_in_its_place: To **delete** this plan click [here](lock-url) 15 | * :repeat: To **plan** this project again, comment: 16 | * `atlantis plan -p dir1-ops` 17 | 18 | --- 19 | * :fast_forward: To **apply** all unapplied plans from this pull request, comment: 20 | * `atlantis apply` 21 | * :put_litter_in_its_place: To delete all plans and locks for the PR, comment: 22 | * `atlantis unlock` -------------------------------------------------------------------------------- /e2e/github.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 HootSuite Media Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the License); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // Unless required by applicable law or agreed to in writing, software 8 | // distributed under the License is distributed on an AS IS BASIS, 9 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | // See the License for the specific language governing permissions and 11 | // limitations under the License. 12 | // Modified hereafter by contributors to runatlantis/atlantis. 13 | 14 | package main 15 | 16 | import ( 17 | "context" 18 | 19 | "github.com/google/go-github/v54/github" 20 | ) 21 | 22 | type GithubClient struct { 23 | client *github.Client 24 | ctx context.Context 25 | username string 26 | } 27 | -------------------------------------------------------------------------------- /docs/adr/0001-record-architecture-decisions.md: -------------------------------------------------------------------------------- 1 | # 1. Record architecture decisions 2 | 3 | Date: 2023-05-09 4 | 5 | ## Status 6 | 7 | Accepted 8 | 9 | ## Context 10 | 11 | We need to record the architectural decisions made for Atlantis. The project is a very decentralized project. It suffers from frequent one-timer contributors and an ever-changing team of maintainers. 12 | By utilizing the ADR process, we can improve who decisions are made and bring transparency to past decisions to assist future contributors and maintainers to confidently steer the project. 13 | 14 | ## Decision 15 | 16 | We will use Architecture Decision Records, as [described by Michael Nygard](http://thinkrelevance.com/blog/2011/11/15/documenting-architecture-decisions). 17 | 18 | ## Consequences 19 | 20 | See Michael Nygard's article, linked above. For a lightweight ADR toolset, see Nat Pryce's [adr-tools](https://github.com/npryce/adr-tools) before submitting a new ADR. 21 | -------------------------------------------------------------------------------- /runatlantis.io/guide/test-drive.md: -------------------------------------------------------------------------------- 1 | # Test Drive 2 | To test drive Atlantis on an example repo, download the latest release: 3 | [https://github.com/runatlantis/atlantis/releases](https://github.com/runatlantis/atlantis/releases) 4 | 5 | Once you've extracted the archive, run: 6 | ```bash 7 | ./atlantis testdrive 8 | ``` 9 | 10 | This mode sets up Atlantis on a test repo so you can try it out. It will 11 | - Fork an example Terraform project into your GitHub account 12 | - Install Terraform (if not already in your PATH) 13 | - Install [ngrok](https://ngrok.com/) so we can expose Atlantis to GitHub 14 | - Start Atlantis so you can execute commands on the pull request 15 | 16 | ## Next Steps 17 | * If you're ready to test out running Atlantis on **your repos** then read [Testing Locally](testing-locally.html). 18 | * If you're ready to properly install Atlantis on real infrastructure then head over to the [Installation Guide](/docs/installation-guide.html). 19 | -------------------------------------------------------------------------------- /server/events/templates/policy_check_results_unwrapped.tmpl: -------------------------------------------------------------------------------- 1 | {{ define "policyCheckResultsUnwrapped" -}} 2 | {{- if eq .Command "Policy Check" }} 3 | {{- if ne .PreConftestOutput "" }} 4 | ```diff 5 | {{ .PreConftestOutput }} 6 | ``` 7 | {{- end -}} 8 | {{ template "policyCheck" .PolicySetResults }} 9 | {{- if ne .PostConftestOutput "" }} 10 | ```diff 11 | {{ .PostConftestOutput }} 12 | ``` 13 | {{ end -}} 14 | {{- end }} 15 | {{- if .PolicyCleared }} 16 | * :arrow_forward: To **apply** this plan, comment: 17 | * `{{ .ApplyCmd }}` 18 | {{- else }} 19 | #### Policy Approval Status: 20 | ``` 21 | {{ .PolicyApprovalSummary }} 22 | ``` 23 | * :heavy_check_mark: To **approve** this project, comment: 24 | * `{{ .ApprovePoliciesCmd }}` 25 | {{- end }} 26 | * :put_litter_in_its_place: To **delete** this plan click [here]({{ .LockURL }}) 27 | * :repeat: To re-run policies **plan** this project again by commenting: 28 | * `{{ .RePlanCmd }}` 29 | {{ end -}} 30 | -------------------------------------------------------------------------------- /server/core/runtime/version_step_runner.go: -------------------------------------------------------------------------------- 1 | package runtime 2 | 3 | import ( 4 | "path/filepath" 5 | 6 | "github.com/hashicorp/go-version" 7 | "github.com/runatlantis/atlantis/server/events/command" 8 | ) 9 | 10 | // VersionStepRunner runs a version command given a ctx 11 | type VersionStepRunner struct { 12 | TerraformExecutor TerraformExec 13 | DefaultTFVersion *version.Version 14 | } 15 | 16 | // Run ensures a given version for the executable, builds the args from the project context and then runs executable returning the result 17 | func (v *VersionStepRunner) Run(ctx command.ProjectContext, extraArgs []string, path string, envs map[string]string) (string, error) { 18 | tfVersion := v.DefaultTFVersion 19 | if ctx.TerraformVersion != nil { 20 | tfVersion = ctx.TerraformVersion 21 | } 22 | 23 | versionCmd := []string{"version"} 24 | return v.TerraformExecutor.RunCommandWithVersion(ctx, filepath.Clean(path), versionCmd, envs, tfVersion, ctx.Workspace) 25 | } 26 | -------------------------------------------------------------------------------- /runatlantis.io/.vuepress/public/hightower-super-dope.svg: -------------------------------------------------------------------------------- 1 | HightowerHightowerextra dopeextra dope -------------------------------------------------------------------------------- /server/events/command/scope_tags.go: -------------------------------------------------------------------------------- 1 | package command 2 | 3 | import ( 4 | "reflect" 5 | "regexp" 6 | "strings" 7 | ) 8 | 9 | type ProjectScopeTags struct { 10 | BaseRepo string 11 | PrNumber string 12 | Project string 13 | ProjectPath string 14 | TerraformVersion string 15 | Workspace string 16 | } 17 | 18 | func (s ProjectScopeTags) Loadtags() map[string]string { 19 | tags := make(map[string]string) 20 | 21 | v := reflect.ValueOf(s) 22 | t := v.Type() 23 | 24 | for i := 0; i < v.NumField(); i++ { 25 | tags[toSnakeCase(t.Field(i).Name)] = v.Field(i).String() 26 | } 27 | 28 | return tags 29 | } 30 | 31 | func toSnakeCase(str string) string { 32 | var matchFirstCap = regexp.MustCompile("(.)([A-Z][a-z]+)") 33 | var matchAllCap = regexp.MustCompile("([a-z0-9])([A-Z])") 34 | 35 | snake := matchFirstCap.ReplaceAllString(str, "${1}_${2}") 36 | snake = matchAllCap.ReplaceAllString(snake, "${1}_${2}") 37 | return strings.ToLower(snake) 38 | } 39 | -------------------------------------------------------------------------------- /scripts/coverage.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Taken and modified from https://github.com/mlafeldt/chef-runner/blob/v0.7.0/script/coverage 3 | # Generate test coverage statistics for Go packages. 4 | # 5 | # Works around the fact that `go test -coverprofile` currently does not work 6 | # with multiple packages, see https://code.google.com/p/go/issues/detail?id=6909 7 | # 8 | # Usage: coverage.sh packages... 9 | # Example: coverage.sh github.com/runatlantis/atlantis github.com/runatlantis/atlantis/testdrive 10 | # 11 | 12 | set -e 13 | 14 | workdir=.cover 15 | profile="$workdir/cover.out" 16 | mode=count 17 | 18 | generate_cover_data() { 19 | rm -rf "$workdir" 20 | mkdir "$workdir" 21 | 22 | pkgs=$@ 23 | for pkg in $pkgs; do 24 | f="$workdir/$(echo $pkg | tr / -).cover" 25 | go test -covermode="$mode" -coverprofile="$f" "$pkg" 26 | done 27 | 28 | echo "mode: $mode" >"$profile" 29 | grep -h -v "^mode:" "$workdir"/*.cover >>"$profile" 30 | } 31 | 32 | generate_cover_data $@ 33 | -------------------------------------------------------------------------------- /runatlantis.io/docs/streaming-logs.md: -------------------------------------------------------------------------------- 1 | # Real-time logs 2 | 3 | Atlantis supports streaming terraform logs in real time by default. Currently, only two commands are supported 4 | 5 | * atlantis plan 6 | * atlantis apply 7 | 8 | ::: warning 9 | As of now, not all custom workflow outputs and other terraform commands are not supported. Support for terragrunt has been added, see examples in [Custom Workflows](./custom-workflows.md#terragrunt). 10 | ::: 11 | 12 | In order to view real-time terraform logs, a user can navigate through the *details* section of a given project's plan or apply status check. 13 | 14 | ![Plan Command](./images/plan.png) 15 | 16 | This will link to the atlantis UI which provides real-time logging in addition to native terraform syntax highlighting. 17 | 18 | ![Plan Output](./images/plan_output.png) 19 | 20 | ::: warning 21 | As of now the logs are currently stored in memory and cleared when a given pull request is closed, so this link shouldn't be persisted anywhere. 22 | ::: 23 | 24 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/modules-yaml/exp-output-plan-staging.txt: -------------------------------------------------------------------------------- 1 | Ran Plan for dir: `staging` workspace: `default` 2 | ```diff 3 | Refreshing Terraform state in-memory prior to plan... 4 | The refreshed state will be used to calculate this plan, but will not be 5 | persisted to local or remote state storage. 6 | 7 | 8 | ------------------------------------------------------------------------ 9 | 10 | An execution plan has been generated and is shown below. 11 | Resource actions are indicated with the following symbols: 12 | + create 13 | 14 | Terraform will perform the following actions: 15 | 16 | + module.null.null_resource.this 17 | id: 18 | Plan: 1 to add, 0 to change, 0 to destroy. 19 | 20 | ``` 21 | 22 | * :arrow_forward: To **apply** this plan, comment: 23 | * `atlantis apply -d staging` 24 | * :put_litter_in_its_place: To **delete** this plan click [here](lock-url) 25 | * :repeat: To **plan** this project again, comment: 26 | * `atlantis plan -d staging` 27 | 28 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/modules-yaml/exp-output-plan-production.txt: -------------------------------------------------------------------------------- 1 | Ran Plan for dir: `production` workspace: `default` 2 | ```diff 3 | Refreshing Terraform state in-memory prior to plan... 4 | The refreshed state will be used to calculate this plan, but will not be 5 | persisted to local or remote state storage. 6 | 7 | 8 | ------------------------------------------------------------------------ 9 | 10 | An execution plan has been generated and is shown below. 11 | Resource actions are indicated with the following symbols: 12 | + create 13 | 14 | Terraform will perform the following actions: 15 | 16 | + module.null.null_resource.this 17 | id: 18 | Plan: 1 to add, 0 to change, 0 to destroy. 19 | 20 | ``` 21 | 22 | * :arrow_forward: To **apply** this plan, comment: 23 | * `atlantis apply -d production` 24 | * :put_litter_in_its_place: To **delete** this plan click [here](lock-url) 25 | * :repeat: To **plan** this project again, comment: 26 | * `atlantis plan -d production` 27 | 28 | -------------------------------------------------------------------------------- /server/events/templates/multi_project_plan.tmpl: -------------------------------------------------------------------------------- 1 | {{ define "multiProjectPlan" -}} 2 | {{ template "multiProjectHeader" . }} 3 | {{ $disableApplyAll := .DisableApplyAll -}} 4 | {{ $hideUnchangedPlans := .HideUnchangedPlanComments -}} 5 | {{ range $i, $result := .Results -}} 6 | {{ if (and $hideUnchangedPlans $result.NoChanges) }}{{continue}}{{end -}} 7 | ### {{ add $i 1 }}. {{ if $result.ProjectName }}project: `{{ $result.ProjectName }}` {{ end }}dir: `{{ $result.RepoRelDir }}` workspace: `{{ $result.Workspace }}` 8 | {{ $result.Rendered }} 9 | 10 | {{ if ne $disableApplyAll true -}} 11 | --- 12 | {{ end -}} 13 | {{ end -}} 14 | {{ if ne .DisableApplyAll true -}} 15 | {{ if and (gt (len .Results) 0) (not .PlansDeleted) -}} 16 | * :fast_forward: To **apply** all unapplied plans from this pull request, comment: 17 | * `{{ .ExecutableName }} apply` 18 | * :put_litter_in_its_place: To delete all plans and locks for the PR, comment: 19 | * `{{ .ExecutableName }} unlock` 20 | {{ end -}} 21 | {{ end -}} 22 | {{- template "log" . -}} 23 | {{ end -}} 24 | -------------------------------------------------------------------------------- /.github/workflows/lint-required.yml: -------------------------------------------------------------------------------- 1 | # For required checks when path filtering doesn;'t trigger the other job 2 | # https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/defining-the-mergeability-of-pull-requests/troubleshooting-required-status-checks#handling-skipped-but-required-checks 3 | 4 | name: linter 5 | 6 | on: 7 | pull_request: 8 | types: 9 | - opened 10 | - reopened 11 | - synchronize 12 | - ready_for_review 13 | branches: 14 | - "main" 15 | paths-ignore: 16 | - '**.go' 17 | - 'go.*' 18 | - '.github/workflows/lint.yml' 19 | - '.github/workflows/lint-required.yml' 20 | - '.golangci.yml' 21 | 22 | concurrency: 23 | group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} 24 | cancel-in-progress: true 25 | 26 | jobs: 27 | golangci-lint: 28 | if: github.event.pull_request.draft == false 29 | name: runner / golangci-lint 30 | runs-on: ubuntu-22.04 31 | steps: 32 | - run: 'echo "No build required"' 33 | -------------------------------------------------------------------------------- /server/core/runtime/models/filepath.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "os" 5 | "path/filepath" 6 | ) 7 | 8 | //go:generate pegomock generate --package mocks -o mocks/mock_filepath.go FilePath 9 | 10 | type FilePath interface { 11 | NotExists() bool 12 | Join(elem ...string) FilePath 13 | Symlink(newname string) (FilePath, error) 14 | Resolve() string 15 | } 16 | 17 | type LocalFilePath string 18 | 19 | func (fp LocalFilePath) NotExists() bool { 20 | _, err := os.Stat(string(fp)) 21 | 22 | return os.IsNotExist(err) 23 | } 24 | 25 | func (fp LocalFilePath) Join(elem ...string) FilePath { 26 | pathComponents := []string{} 27 | 28 | pathComponents = append(pathComponents, string(fp)) 29 | pathComponents = append(pathComponents, elem...) 30 | 31 | return LocalFilePath(filepath.Join(pathComponents...)) 32 | } 33 | 34 | func (fp LocalFilePath) Symlink(newname string) (FilePath, error) { 35 | return LocalFilePath(newname), os.Symlink(fp.Resolve(), newname) 36 | } 37 | 38 | func (fp LocalFilePath) Resolve() string { 39 | return string(fp) 40 | } 41 | -------------------------------------------------------------------------------- /testing/README.md: -------------------------------------------------------------------------------- 1 | ## Test Docker Image 2 | 3 | The Docker image used by the tests is `runatlantis/testing-env`. It's built by the Dockerfie 4 | in this directory. 5 | 6 | The image is automatically built by Docker Hub on merges to `main`. 7 | 8 | To update the image, create a pull request that updates the Dockerfile and get it merged to `main`. 9 | 10 | Wait until the build at https://hub.docker.com/repository/docker/runatlantis/testing-env/builds finishes 11 | and then scroll to the bottom to find output like: 12 | 13 | ``` 14 | 01216b26cd75183360909a50217a39d55a9265e7: digest: sha256:9c26943a576bf8aaa7a3790f3f8677c68747114e027cfbc361717f49b958e2d1 size: 4741 15 | Build finished 16 | ``` 17 | 18 | The sha `01216b26cd75183360909a50217a39d55a9265e7` is the tag of the latest image. 19 | 20 | In `.circleci/config.yml`, update the image to reference the new tag: 21 | 22 | ```diff 23 | jobs: 24 | test: 25 | docker: 26 | - - image: runatlantis/testing-env: 27 | + - image: runatlantis/testing-env: 28 | ``` 29 | 30 | And open up a PR. 31 | -------------------------------------------------------------------------------- /scripts/e2e-deps.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Exit immediately if a command returns a non-zero code 4 | set -e 5 | 6 | echo "Preparing to run e2e tests" 7 | if [ ! -f atlantis ]; then 8 | echo "atlantis binary not found. exiting...." 9 | exit 1 10 | fi 11 | cp atlantis ${CIRCLE_WORKING_DIRECTORY}/e2e/ 12 | 13 | # cd into e2e folder 14 | cd e2e/ 15 | # Download terraform 16 | curl -LOk https://releases.hashicorp.com/terraform/${TERRAFORM_VERSION}/terraform_${TERRAFORM_VERSION}_linux_amd64.zip 17 | unzip terraform_${TERRAFORM_VERSION}_linux_amd64.zip 18 | chmod +x terraform 19 | cp terraform /home/circleci/go/bin 20 | # Download ngrok to create a tunnel to expose atlantis server 21 | wget https://bin.equinox.io/c/bNyj1mQVY4c/ngrok-v2-stable-linux-amd64.zip -O ngrok-stable-linux-amd64.zip 22 | unzip ngrok-stable-linux-amd64.zip 23 | chmod +x ngrok 24 | # Download jq 25 | wget -O jq https://github.com/jqlang/jq/releases/download/jq-1.6/jq-linux64 26 | chmod +x jq 27 | # Copy github config file - replace with circleci user later 28 | cp .gitconfig ~/.gitconfig 29 | -------------------------------------------------------------------------------- /server/events/templates/multi_project_policy_unsuccessful.tmpl: -------------------------------------------------------------------------------- 1 | {{ define "multiProjectPolicyUnsuccessful" -}} 2 | {{ template "multiProjectHeader" . }} 3 | {{ $disableApplyAll := .DisableApplyAll -}} 4 | {{ range $i, $result := .Results -}} 5 | ### {{ add $i 1 }}. {{ if $result.ProjectName }}project: `{{ $result.ProjectName }}` {{ end }}dir: `{{ $result.RepoRelDir }}` workspace: `{{ $result.Workspace }}` 6 | {{ $result.Rendered }} 7 | 8 | {{ if ne $disableApplyAll true -}} 9 | --- 10 | {{ end -}} 11 | {{ end -}} 12 | {{ if ne .DisableApplyAll true -}} 13 | {{ if and (gt (len .Results) 0) (not .PlansDeleted) -}} 14 | * :heavy_check_mark: To **approve** all unapplied plans from this pull request, comment: 15 | * `{{ .ExecutableName }} approve_policies` 16 | * :put_litter_in_its_place: To delete all plans and locks for the PR, comment: 17 | * `{{ .ExecutableName }} unlock` 18 | * :repeat: To re-run policies **plan** this project again by commenting: 19 | * `{{ .ExecutableName }} plan` 20 | {{ end -}} 21 | {{ end -}} 22 | {{- template "log" . -}} 23 | {{ end -}} 24 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-clear-approval/exp-output-approve-policies-clear.txt: -------------------------------------------------------------------------------- 1 | Ran Approve Policies for 1 projects: 2 | 3 | 1. dir: `.` workspace: `default` 4 | 5 | ### 1. dir: `.` workspace: `default` 6 | **Approve Policies Failed**: One or more policy sets require additional approval. 7 | #### Policy Approval Status: 8 | ``` 9 | policy set: test_policy: requires: 1 approval(s), have: 0. 10 | ``` 11 | * :heavy_check_mark: To **approve** this project, comment: 12 | * `atlantis approve_policies -d .` 13 | * :put_litter_in_its_place: To **delete** this plan click [here](lock-url) 14 | * :repeat: To re-run policies **plan** this project again by commenting: 15 | * `atlantis plan -d .` 16 | 17 | --- 18 | * :heavy_check_mark: To **approve** all unapplied plans from this pull request, comment: 19 | * `atlantis approve_policies` 20 | * :put_litter_in_its_place: To delete all plans and locks for the PR, comment: 21 | * `atlantis unlock` 22 | * :repeat: To re-run policies **plan** this project again by commenting: 23 | * `atlantis plan` -------------------------------------------------------------------------------- /server/core/runtime/executor.go: -------------------------------------------------------------------------------- 1 | package runtime 2 | 3 | import ( 4 | version "github.com/hashicorp/go-version" 5 | "github.com/runatlantis/atlantis/server/events/command" 6 | "github.com/runatlantis/atlantis/server/logging" 7 | ) 8 | 9 | //go:generate pegomock generate --package mocks -o mocks/mock_versionedexecutorworkflow.go VersionedExecutorWorkflow 10 | 11 | // VersionedExecutorWorkflow defines a versioned execution for a given project context 12 | type VersionedExecutorWorkflow interface { 13 | ExecutorVersionEnsurer 14 | Executor 15 | } 16 | 17 | // Executor runs an executable with provided environment variables and arguments and returns stdout 18 | type Executor interface { 19 | Run(ctx command.ProjectContext, executablePath string, envs map[string]string, workdir string, extraArgs []string) (string, error) 20 | } 21 | 22 | // ExecutorVersionEnsurer ensures a given version exists and outputs a path to the executable 23 | type ExecutorVersionEnsurer interface { 24 | EnsureExecutorVersion(log logging.SimpleLogging, v *version.Version) (string, error) 25 | } 26 | -------------------------------------------------------------------------------- /.github/workflows/website-required.yml: -------------------------------------------------------------------------------- 1 | name: website 2 | 3 | on: 4 | push: 5 | branches: 6 | - "main" 7 | paths-ignore: 8 | - '**.js' 9 | - 'yarn.lock' 10 | - 'package.json' 11 | - '.github/workflows/website.yml' 12 | pull_request: 13 | types: 14 | - opened 15 | - reopened 16 | - synchronize 17 | - ready_for_review 18 | branches: 19 | - "main" 20 | paths-ignore: 21 | - '**.js' 22 | - 'yarn.lock' 23 | - 'package.json' 24 | - '.github/workflows/website.yml' 25 | 26 | concurrency: 27 | group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} 28 | cancel-in-progress: true 29 | 30 | jobs: 31 | # Check that there's no missing links for the website. 32 | # This job builds the website, starts a server to serve it, and then uses 33 | # muffet (https://github.com/raviqqe/muffet) to perform the link check. 34 | link_check: 35 | if: github.event.pull_request.draft == false 36 | runs-on: ubuntu-22.04 37 | steps: 38 | - run: 'echo "No testing required"' 39 | -------------------------------------------------------------------------------- /.github/workflows/test-required.yml: -------------------------------------------------------------------------------- 1 | # For required checks when path filtering doesn;'t trigger the other job 2 | # https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/defining-the-mergeability-of-pull-requests/troubleshooting-required-status-checks#handling-skipped-but-required-checks 3 | 4 | name: tester 5 | 6 | on: 7 | push: 8 | branches: 9 | - "main" 10 | paths-ignore: 11 | - '**.go' 12 | - 'go.*' 13 | - '.github/workflows/test.yml' 14 | pull_request: 15 | types: 16 | - opened 17 | - reopened 18 | - synchronize 19 | - ready_for_review 20 | branches: 21 | - "main" 22 | paths-ignore: 23 | - '**.go' 24 | - 'go.*' 25 | - '.github/workflows/test.yml' 26 | 27 | concurrency: 28 | group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} 29 | cancel-in-progress: true 30 | 31 | jobs: 32 | test: 33 | if: github.event.pull_request.draft == false 34 | name: runner / gotest 35 | runs-on: ubuntu-22.04 36 | steps: 37 | - run: 'echo "No build required"' 38 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/simple/exp-output-apply-var-all.txt: -------------------------------------------------------------------------------- 1 | Ran Apply for 2 projects: 2 | 3 | 1. dir: `.` workspace: `default` 4 | 1. dir: `.` workspace: `new_workspace` 5 | 6 | ### 1. dir: `.` workspace: `default` 7 |
Show Output 8 | 9 | ```diff 10 | null_resource.simple: 11 | null_resource.simple: 12 | null_resource.simple: 13 | null_resource.simple: 14 | null_resource.simple: 15 | null_resource.simple: 16 | 17 | Apply complete! Resources: 3 added, 0 changed, 0 destroyed. 18 | 19 | Outputs: 20 | 21 | var = "default_workspace" 22 | workspace = "default" 23 | ``` 24 | 25 |
26 | 27 | --- 28 | ### 2. dir: `.` workspace: `new_workspace` 29 |
Show Output 30 | 31 | ```diff 32 | null_resource.simple: 33 | null_resource.simple: 34 | null_resource.simple: 35 | null_resource.simple: 36 | null_resource.simple: 37 | null_resource.simple: 38 | 39 | Apply complete! Resources: 3 added, 0 changed, 0 destroyed. 40 | 41 | Outputs: 42 | 43 | var = "new_workspace" 44 | workspace = "new_workspace" 45 | ``` 46 | 47 |
48 | 49 | --- -------------------------------------------------------------------------------- /server/events/templates/policy_check_results_wrapped.tmpl: -------------------------------------------------------------------------------- 1 | {{ define "policyCheckResultsWrapped" -}} 2 |
Show Output 3 | {{- if eq .Command "Policy Check" }} 4 | {{- if ne .PreConftestOutput "" }} 5 | ```diff 6 | {{ .PreConftestOutput }} 7 | ``` 8 | {{- end -}} 9 | {{ template "policyCheck" .PolicySetResults }} 10 | {{- if ne .PostConftestOutput "" }} 11 | ```diff 12 | {{ .PostConftestOutput }} 13 | ``` 14 | {{ end -}} 15 | {{- end }} 16 | {{- if .PolicyCleared }} 17 | * :arrow_forward: To **apply** this plan, comment: 18 | * `{{ .ApplyCmd }}` 19 | {{- else }} 20 | #### Policy Approval Status: 21 | ``` 22 | {{ .PolicyApprovalSummary }} 23 | ``` 24 | * :heavy_check_mark: To **approve** this project, comment: 25 | * `{{ .ApprovePoliciesCmd }}` 26 | {{- end }} 27 | * :put_litter_in_its_place: To **delete** this plan click [here]({{ .LockURL }}) 28 | * :repeat: To re-run policies **plan** this project again by commenting: 29 | * `{{ .RePlanCmd }}` 30 |
31 | {{- if eq .Command "Policy Check" }} 32 | 33 | ``` 34 | {{ .PolicyCheckSummary }} 35 | ``` 36 | {{- end }} 37 | {{ end -}} -------------------------------------------------------------------------------- /cmd/root.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 HootSuite Media Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the License); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // Unless required by applicable law or agreed to in writing, software 8 | // distributed under the License is distributed on an AS IS BASIS, 9 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | // See the License for the specific language governing permissions and 11 | // limitations under the License. 12 | // Modified hereafter by contributors to runatlantis/atlantis. 13 | 14 | package cmd 15 | 16 | import ( 17 | "os" 18 | 19 | "github.com/spf13/cobra" 20 | ) 21 | 22 | // RootCmd is the base command onto which all other commands are added. 23 | var RootCmd = &cobra.Command{ 24 | Use: "atlantis", 25 | Short: "Terraform Pull Request Automation", 26 | } 27 | 28 | // Execute starts RootCmd. 29 | func Execute() { 30 | if err := RootCmd.Execute(); err != nil { 31 | os.Exit(1) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /server/events/db_updater.go: -------------------------------------------------------------------------------- 1 | package events 2 | 3 | import ( 4 | "github.com/runatlantis/atlantis/server/core/locking" 5 | "github.com/runatlantis/atlantis/server/events/command" 6 | "github.com/runatlantis/atlantis/server/events/models" 7 | ) 8 | 9 | type DBUpdater struct { 10 | Backend locking.Backend 11 | } 12 | 13 | func (c *DBUpdater) updateDB(ctx *command.Context, pull models.PullRequest, results []command.ProjectResult) (models.PullStatus, error) { 14 | // Filter out results that errored due to the directory not existing. We 15 | // don't store these in the database because they would never be "apply-able" 16 | // and so the pull request would always have errors. 17 | var filtered []command.ProjectResult 18 | for _, r := range results { 19 | if _, ok := r.Error.(DirNotExistErr); ok { 20 | ctx.Log.Debug("ignoring error result from project at dir %q workspace %q because it is dir not exist error", r.RepoRelDir, r.Workspace) 21 | continue 22 | } 23 | filtered = append(filtered, r) 24 | } 25 | ctx.Log.Debug("updating DB with pull results") 26 | return c.Backend.UpdatePullWithResults(pull, filtered) 27 | } 28 | -------------------------------------------------------------------------------- /runatlantis.io/docs/configuring-atlantis.md: -------------------------------------------------------------------------------- 1 | # Configuring Atlantis 2 | 3 | There are three methods for configuring Atlantis: 4 | 1. Passing flags to the `atlantis server` command 5 | 1. Creating a server-side repo config file and using the `--repo-config` flag 6 | 1. Placing an `atlantis.yaml` file at the root of your Terraform repositories 7 | 8 | ## Flags 9 | Flags to `atlantis server` are used to configure the global operation of 10 | Atlantis, for example setting credentials for your Git Host 11 | or configuring SSL certs. 12 | 13 | See [Server Configuration](server-configuration.html) for more details. 14 | 15 | ## Server-Side Repo Config 16 | A Server-Side Repo Config file is used to control per-repo behaviour 17 | and what users can do in repo-level `atlantis.yaml` files. 18 | 19 | See [Server-Side Repo Config](server-side-repo-config.html) for more details. 20 | 21 | ## Repo-Level `atlantis.yaml` Files 22 | `atlantis.yaml` files placed at the root of your Terraform repos can be used to 23 | change the default Atlantis behaviour for each repo. 24 | 25 | See [Repo-Level atlantis.yaml Files](repo-level-atlantis-yaml.html) for more details. 26 | -------------------------------------------------------------------------------- /runatlantis.io/docs/installation-guide.md: -------------------------------------------------------------------------------- 1 | # Installation Guide 2 | This guide is for installing a **production-ready** instance of Atlantis onto your 3 | infrastructure: 4 | 1. First, ensure your Terraform setup meets the Atlantis **requirements** 5 | * See [Requirements](requirements.html) 6 | 1. Create **access credentials** for your Git host (GitHub, GitLab, Bitbucket, Azure DevOps) 7 | * See [Generating Git Host Access Credentials](access-credentials.html) 8 | 1. Create a **webhook secret** so Atlantis can validate webhooks 9 | * See [Creating a Webhook Secret](webhook-secrets.html) 10 | 1. **Deploy** Atlantis into your infrastructure 11 | * See [Deployment](deployment.html) 12 | 1. Configure **Webhooks** on your Git host so Atlantis can respond to your pull requests 13 | * See [Configuring Webhooks](configuring-webhooks.html) 14 | 1. Configure **provider credentials** so Atlantis can actually run Terraform commands 15 | * See [Provider Credentials](provider-credentials.html) 16 | 17 | :::tip 18 | If you want to test out Atlantis first, check out [Test Drive](../guide/test-drive.html) 19 | and [Testing Locally](../guide/testing-locally.html). 20 | ::: 21 | -------------------------------------------------------------------------------- /server/scheduled/executor_service_test.go: -------------------------------------------------------------------------------- 1 | package scheduled 2 | 3 | import ( 4 | "testing" 5 | "time" 6 | 7 | pegomock "github.com/petergtz/pegomock/v4" 8 | "github.com/runatlantis/atlantis/server/logging" 9 | "github.com/runatlantis/atlantis/server/scheduled/mocks" 10 | ) 11 | 12 | func TestExecutorService_Run(t *testing.T) { 13 | pegomock.RegisterMockTestingT(t) 14 | mockJob := mocks.NewMockJob() 15 | type fields struct { 16 | log logging.SimpleLogging 17 | jobs []JobDefinition 18 | } 19 | tests := []struct { 20 | name string 21 | fields fields 22 | }{ 23 | { 24 | name: "test", 25 | fields: fields{ 26 | log: logging.NewNoopLogger(t), 27 | jobs: []JobDefinition{ 28 | { 29 | Job: mockJob, 30 | Period: 1 * time.Second, 31 | }, 32 | }, 33 | }, 34 | }, 35 | } 36 | for _, tt := range tests { 37 | t.Run(tt.name, func(t *testing.T) { 38 | s := &ExecutorService{ 39 | log: tt.fields.log, 40 | jobs: make([]JobDefinition, 0), 41 | } 42 | s.AddJob(tt.fields.jobs[0]) 43 | go s.Run() 44 | time.Sleep(1050 * time.Millisecond) 45 | mockJob.VerifyWasCalledOnce().Run() 46 | }) 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /.github/workflows/codeql-required.yml: -------------------------------------------------------------------------------- 1 | # For required checks when path filtering doesn;'t trigger the other job 2 | # https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/defining-the-mergeability-of-pull-requests/troubleshooting-required-status-checks#handling-skipped-but-required-checks 3 | 4 | name: "CodeQL" 5 | 6 | on: 7 | push: 8 | branches: [ "main" ] 9 | paths-ignore: 10 | - '**.go' 11 | - '**.js' 12 | pull_request: 13 | # The branches below must be a subset of the branches above 14 | types: 15 | - opened 16 | - reopened 17 | - synchronize 18 | - ready_for_review 19 | branches: [ "main" ] 20 | paths-ignore: 21 | - '**.go' 22 | - '**.js' 23 | 24 | jobs: 25 | analyze: 26 | name: Analyze 27 | if: github.event.pull_request.draft == false 28 | runs-on: ubuntu-latest 29 | permissions: 30 | actions: read 31 | contents: read 32 | security-events: write 33 | 34 | strategy: 35 | fail-fast: false 36 | matrix: 37 | language: [ 'go', 'javascript' ] 38 | 39 | steps: 40 | - run: 'echo "No build required"' 41 | -------------------------------------------------------------------------------- /runatlantis.io/.vuepress/public/coding.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | jobs: 3 | e2e: 4 | docker: 5 | - image: cimg/go:1.21 # If you update this, update it in the Makefile too 6 | environment: 7 | # This version of TF will be downloaded before Atlantis is started. 8 | # We do this instead of setting --default-tf-version because setting 9 | # that flag starts the download asynchronously so we'd have a race 10 | # condition. 11 | # renovate: datasource=github-releases depName=hashicorp/terraform versioning=hashicorp 12 | TERRAFORM_VERSION: 1.5.6 13 | steps: 14 | - checkout 15 | - run: make build-service 16 | # We don't run e2e tests on fork PRs because they don't have access to the secret env vars. 17 | - run: if [ -z "${CIRCLE_PR_REPONAME}" ]; then ./scripts/e2e.sh; fi 18 | 19 | workflows: 20 | version: 2 21 | branch: 22 | jobs: 23 | - e2e: 24 | context: 25 | - atlantis-e2e-tests 26 | filters: 27 | branches: 28 | # Ignore fork PRs since they don't have access to 29 | # the atlantis-e2e-tests context (and also doc PRs). 30 | ignore: /(pull\/\d+)|(docs\/.*)/ 31 | -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks/exp-output-auto-policy-check.txt: -------------------------------------------------------------------------------- 1 | Ran Policy Check for dir: `.` workspace: `default` 2 | 3 | **Policy Check Failed**: Some policy sets did not pass. 4 | #### Policy Set: `test_policy` 5 | ```diff 6 | FAIL - - main - WARNING: Null Resource creation is prohibited. 7 | 8 | 1 test, 0 passed, 0 warnings, 1 failure, 0 exceptions 9 | 10 | ``` 11 | 12 | 13 | #### Policy Approval Status: 14 | ``` 15 | policy set: test_policy: requires: 1 approval(s), have: 0. 16 | ``` 17 | * :heavy_check_mark: To **approve** this project, comment: 18 | * `atlantis approve_policies -d .` 19 | * :put_litter_in_its_place: To **delete** this plan click [here](lock-url) 20 | * :repeat: To re-run policies **plan** this project again by commenting: 21 | * `atlantis plan -d .` 22 | 23 | --- 24 | * :heavy_check_mark: To **approve** all unapplied plans from this pull request, comment: 25 | * `atlantis approve_policies` 26 | * :put_litter_in_its_place: To delete all plans and locks for the PR, comment: 27 | * `atlantis unlock` 28 | * :repeat: To re-run policies **plan** this project again by commenting: 29 | * `atlantis plan` -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-diff-owner/exp-output-approve-policies.txt: -------------------------------------------------------------------------------- 1 | Ran Approve Policies for 1 projects: 2 | 3 | 1. dir: `.` workspace: `default` 4 | 5 | ### 1. dir: `.` workspace: `default` 6 | **Approve Policies Error** 7 | ``` 8 | 1 error occurred: 9 | * policy set: test_policy user runatlantis is not a policy owner - please contact policy owners to approve failing policies 10 | 11 | 12 | ``` 13 | #### Policy Approval Status: 14 | ``` 15 | policy set: test_policy: requires: 1 approval(s), have: 0. 16 | ``` 17 | * :heavy_check_mark: To **approve** this project, comment: 18 | * `atlantis approve_policies -d .` 19 | * :put_litter_in_its_place: To **delete** this plan click [here](lock-url) 20 | * :repeat: To re-run policies **plan** this project again by commenting: 21 | * `atlantis plan -d .` 22 | 23 | --- 24 | * :heavy_check_mark: To **approve** all unapplied plans from this pull request, comment: 25 | * `atlantis approve_policies` 26 | * :put_litter_in_its_place: To delete all plans and locks for the PR, comment: 27 | * `atlantis unlock` 28 | * :repeat: To re-run policies **plan** this project again by commenting: 29 | * `atlantis plan` -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-apply-reqs/exp-output-auto-policy-check.txt: -------------------------------------------------------------------------------- 1 | Ran Policy Check for dir: `.` workspace: `default` 2 | 3 | **Policy Check Failed**: Some policy sets did not pass. 4 | #### Policy Set: `test_policy` 5 | ```diff 6 | FAIL - - main - WARNING: Null Resource creation is prohibited. 7 | 8 | 1 test, 0 passed, 0 warnings, 1 failure, 0 exceptions 9 | 10 | ``` 11 | 12 | 13 | #### Policy Approval Status: 14 | ``` 15 | policy set: test_policy: requires: 1 approval(s), have: 0. 16 | ``` 17 | * :heavy_check_mark: To **approve** this project, comment: 18 | * `atlantis approve_policies -d .` 19 | * :put_litter_in_its_place: To **delete** this plan click [here](lock-url) 20 | * :repeat: To re-run policies **plan** this project again by commenting: 21 | * `atlantis plan -d .` 22 | 23 | --- 24 | * :heavy_check_mark: To **approve** all unapplied plans from this pull request, comment: 25 | * `atlantis approve_policies` 26 | * :put_litter_in_its_place: To delete all plans and locks for the PR, comment: 27 | * `atlantis unlock` 28 | * :repeat: To re-run policies **plan** this project again by commenting: 29 | * `atlantis plan` -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-diff-owner/exp-output-auto-policy-check.txt: -------------------------------------------------------------------------------- 1 | Ran Policy Check for dir: `.` workspace: `default` 2 | 3 | **Policy Check Failed**: Some policy sets did not pass. 4 | #### Policy Set: `test_policy` 5 | ```diff 6 | FAIL - - main - WARNING: Null Resource creation is prohibited. 7 | 8 | 1 test, 0 passed, 0 warnings, 1 failure, 0 exceptions 9 | 10 | ``` 11 | 12 | 13 | #### Policy Approval Status: 14 | ``` 15 | policy set: test_policy: requires: 1 approval(s), have: 0. 16 | ``` 17 | * :heavy_check_mark: To **approve** this project, comment: 18 | * `atlantis approve_policies -d .` 19 | * :put_litter_in_its_place: To **delete** this plan click [here](lock-url) 20 | * :repeat: To re-run policies **plan** this project again by commenting: 21 | * `atlantis plan -d .` 22 | 23 | --- 24 | * :heavy_check_mark: To **approve** all unapplied plans from this pull request, comment: 25 | * `atlantis approve_policies` 26 | * :put_litter_in_its_place: To delete all plans and locks for the PR, comment: 27 | * `atlantis unlock` 28 | * :repeat: To re-run policies **plan** this project again by commenting: 29 | * `atlantis plan` -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-enabled-repo/exp-output-auto-policy-check.txt: -------------------------------------------------------------------------------- 1 | Ran Policy Check for dir: `.` workspace: `default` 2 | 3 | **Policy Check Failed**: Some policy sets did not pass. 4 | #### Policy Set: `test_policy` 5 | ```diff 6 | FAIL - - main - WARNING: Null Resource creation is prohibited. 7 | 8 | 1 test, 0 passed, 0 warnings, 1 failure, 0 exceptions 9 | 10 | ``` 11 | 12 | 13 | #### Policy Approval Status: 14 | ``` 15 | policy set: test_policy: requires: 1 approval(s), have: 0. 16 | ``` 17 | * :heavy_check_mark: To **approve** this project, comment: 18 | * `atlantis approve_policies -d .` 19 | * :put_litter_in_its_place: To **delete** this plan click [here](lock-url) 20 | * :repeat: To re-run policies **plan** this project again by commenting: 21 | * `atlantis plan -d .` 22 | 23 | --- 24 | * :heavy_check_mark: To **approve** all unapplied plans from this pull request, comment: 25 | * `atlantis approve_policies` 26 | * :put_litter_in_its_place: To delete all plans and locks for the PR, comment: 27 | * `atlantis unlock` 28 | * :repeat: To re-run policies **plan** this project again by commenting: 29 | * `atlantis plan` -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-clear-approval/exp-output-auto-policy-check.txt: -------------------------------------------------------------------------------- 1 | Ran Policy Check for dir: `.` workspace: `default` 2 | 3 | **Policy Check Failed**: Some policy sets did not pass. 4 | #### Policy Set: `test_policy` 5 | ```diff 6 | FAIL - - main - WARNING: Null Resource creation is prohibited. 7 | 8 | 1 test, 0 passed, 0 warnings, 1 failure, 0 exceptions 9 | 10 | ``` 11 | 12 | 13 | #### Policy Approval Status: 14 | ``` 15 | policy set: test_policy: requires: 1 approval(s), have: 0. 16 | ``` 17 | * :heavy_check_mark: To **approve** this project, comment: 18 | * `atlantis approve_policies -d .` 19 | * :put_litter_in_its_place: To **delete** this plan click [here](lock-url) 20 | * :repeat: To re-run policies **plan** this project again by commenting: 21 | * `atlantis plan -d .` 22 | 23 | --- 24 | * :heavy_check_mark: To **approve** all unapplied plans from this pull request, comment: 25 | * `atlantis approve_policies` 26 | * :put_litter_in_its_place: To delete all plans and locks for the PR, comment: 27 | * `atlantis unlock` 28 | * :repeat: To re-run policies **plan** this project again by commenting: 29 | * `atlantis plan` -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-disabled-repo/exp-output-auto-policy-check.txt: -------------------------------------------------------------------------------- 1 | Ran Policy Check for dir: `.` workspace: `default` 2 | 3 | **Policy Check Failed**: Some policy sets did not pass. 4 | #### Policy Set: `test_policy` 5 | ```diff 6 | FAIL - - main - WARNING: Null Resource creation is prohibited. 7 | 8 | 1 test, 0 passed, 0 warnings, 1 failure, 0 exceptions 9 | 10 | ``` 11 | 12 | 13 | #### Policy Approval Status: 14 | ``` 15 | policy set: test_policy: requires: 1 approval(s), have: 0. 16 | ``` 17 | * :heavy_check_mark: To **approve** this project, comment: 18 | * `atlantis approve_policies -d .` 19 | * :put_litter_in_its_place: To **delete** this plan click [here](lock-url) 20 | * :repeat: To re-run policies **plan** this project again by commenting: 21 | * `atlantis plan -d .` 22 | 23 | --- 24 | * :heavy_check_mark: To **approve** all unapplied plans from this pull request, comment: 25 | * `atlantis approve_policies` 26 | * :put_litter_in_its_place: To delete all plans and locks for the PR, comment: 27 | * `atlantis unlock` 28 | * :repeat: To re-run policies **plan** this project again by commenting: 29 | * `atlantis plan` -------------------------------------------------------------------------------- /server/controllers/events/testdata/test-repos/policy-checks-disabled-previous-match/exp-output-auto-policy-check.txt: -------------------------------------------------------------------------------- 1 | Ran Policy Check for dir: `.` workspace: `default` 2 | 3 | **Policy Check Failed**: Some policy sets did not pass. 4 | #### Policy Set: `test_policy` 5 | ```diff 6 | FAIL - - main - WARNING: Null Resource creation is prohibited. 7 | 8 | 1 test, 0 passed, 0 warnings, 1 failure, 0 exceptions 9 | 10 | ``` 11 | 12 | 13 | #### Policy Approval Status: 14 | ``` 15 | policy set: test_policy: requires: 1 approval(s), have: 0. 16 | ``` 17 | * :heavy_check_mark: To **approve** this project, comment: 18 | * `atlantis approve_policies -d .` 19 | * :put_litter_in_its_place: To **delete** this plan click [here](lock-url) 20 | * :repeat: To re-run policies **plan** this project again by commenting: 21 | * `atlantis plan -d .` 22 | 23 | --- 24 | * :heavy_check_mark: To **approve** all unapplied plans from this pull request, comment: 25 | * `atlantis approve_policies` 26 | * :put_litter_in_its_place: To delete all plans and locks for the PR, comment: 27 | * `atlantis unlock` 28 | * :repeat: To re-run policies **plan** this project again by commenting: 29 | * `atlantis plan` --------------------------------------------------------------------------------