chore: defaults

This commit is contained in:
2025-11-01 23:32:29 +01:00
parent 4ab78f9af9
commit a281039ae7
9 changed files with 550 additions and 10 deletions

6
.gitignore vendored Normal file
View File

@@ -0,0 +1,6 @@
.terraform/
*.tfstate
*.tfstate.backup
.terraform.lock.hcl
.vscode/
.DS_Store

View File

@@ -1 +1,73 @@
# terraform module ## Requirements
| Name | Version |
|------|---------|
| <a name="requirement_gitlab"></a> [gitlab](#requirement\_gitlab) | 18.0.0 |
## Providers
| Name | Version |
|------|---------|
| <a name="provider_gitlab"></a> [gitlab](#provider\_gitlab) | 18.0.0 |
## Modules
No modules.
## Resources
| Name | Type |
|------|------|
| [gitlab_branch_protection.protected_branches](https://registry.terraform.io/providers/gitlabhq/gitlab/18.0.0/docs/resources/branch_protection) | resource |
| [gitlab_project.project](https://registry.terraform.io/providers/gitlabhq/gitlab/18.0.0/docs/resources/project) | resource |
| [gitlab_project_custom_attribute.custom_attributes](https://registry.terraform.io/providers/gitlabhq/gitlab/18.0.0/docs/resources/project_custom_attribute) | resource |
| [gitlab_project_environment.environments](https://registry.terraform.io/providers/gitlabhq/gitlab/18.0.0/docs/resources/project_environment) | resource |
| [gitlab_project_job_token_scopes.ci_token_scope](https://registry.terraform.io/providers/gitlabhq/gitlab/18.0.0/docs/resources/project_job_token_scopes) | resource |
| [gitlab_project_push_rules.push_rule](https://registry.terraform.io/providers/gitlabhq/gitlab/18.0.0/docs/resources/project_push_rules) | resource |
| [gitlab_project_variable.scoped_variables](https://registry.terraform.io/providers/gitlabhq/gitlab/18.0.0/docs/resources/project_variable) | resource |
| [gitlab_project_variable.variable](https://registry.terraform.io/providers/gitlabhq/gitlab/18.0.0/docs/resources/project_variable) | resource |
| [gitlab_tag_protection.protected_tags](https://registry.terraform.io/providers/gitlabhq/gitlab/18.0.0/docs/resources/tag_protection) | resource |
| [gitlab_group.parent](https://registry.terraform.io/providers/gitlabhq/gitlab/18.0.0/docs/data-sources/group) | data source |
| [gitlab_group.token_scope_groups](https://registry.terraform.io/providers/gitlabhq/gitlab/18.0.0/docs/data-sources/group) | data source |
| [gitlab_project.token_scope_projects](https://registry.terraform.io/providers/gitlabhq/gitlab/18.0.0/docs/data-sources/project) | data source |
## Inputs
| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| <a name="input_allow_merge_on_skipped_pipeline"></a> [allow\_merge\_on\_skipped\_pipeline](#input\_allow\_merge\_on\_skipped\_pipeline) | Set to true if you want to treat skipped pipelines as if they finished with success. | `bool` | `true` | no |
| <a name="input_allowed_avatar_types_json"></a> [allowed\_avatar\_types\_json](#input\_allowed\_avatar\_types\_json) | Path to allowed avatar types json | `string` | `""` | no |
| <a name="input_allowed_project_types_json"></a> [allowed\_project\_types\_json](#input\_allowed\_project\_types\_json) | Path to allowed project types json | `string` | `""` | no |
| <a name="input_archived"></a> [archived](#input\_archived) | Archived project | `bool` | `false` | no |
| <a name="input_attributes"></a> [attributes](#input\_attributes) | custom attributes to be set for the project | `map(string)` | `{}` | no |
| <a name="input_auto_cancel_pending_pipelines"></a> [auto\_cancel\_pending\_pipelines](#input\_auto\_cancel\_pending\_pipelines) | Auto-cancel pending pipelines. This isnt a boolean, but enabled/disabled. | `string` | `"enabled"` | no |
| <a name="input_avatar"></a> [avatar](#input\_avatar) | Type of the avatar for the group (default: from type) | `string` | `""` | no |
| <a name="input_avatars_dir"></a> [avatars\_dir](#input\_avatars\_dir) | Avatars directory png files | `string` | `""` | no |
| <a name="input_build_git_strategy"></a> [build\_git\_strategy](#input\_build\_git\_strategy) | The Git strategy. Defaults to fetch. | `string` | `"clone"` | no |
| <a name="input_build_timeout"></a> [build\_timeout](#input\_build\_timeout) | The maximum amount of time, in seconds, that a job can run. | `number` | `3600` | no |
| <a name="input_ci_config_path"></a> [ci\_config\_path](#input\_ci\_config\_path) | CI PATH | `string` | `null` | no |
| <a name="input_ci_variables"></a> [ci\_variables](#input\_ci\_variables) | CI variables to be set for the group | <pre>map(object({<br/> value = string<br/> description = optional(string)<br/> protected = optional(bool)<br/> masked = optional(bool)<br/> environment_scope = optional(string)<br/> }))</pre> | `null` | no |
| <a name="input_default_branch"></a> [default\_branch](#input\_default\_branch) | Default branch | `string` | `"master"` | no |
| <a name="input_description"></a> [description](#input\_description) | Repository Description | `string` | n/a | yes |
| <a name="input_environments"></a> [environments](#input\_environments) | Project environments | `map(string)` | `{}` | no |
| <a name="input_forked_from_project_id"></a> [forked\_from\_project\_id](#input\_forked\_from\_project\_id) | Forked from | `number` | `0` | no |
| <a name="input_group_runners_enabled"></a> [group\_runners\_enabled](#input\_group\_runners\_enabled) | Enable group runners for this project. | `bool` | `true` | no |
| <a name="input_is_enable_conventional_commits_push_rule"></a> [is\_enable\_conventional\_commits\_push\_rule](#input\_is\_enable\_conventional\_commits\_push\_rule) | Enable conventional commits push rule | `bool` | `false` | no |
| <a name="input_is_enabled_checkmarx"></a> [is\_enabled\_checkmarx](#input\_is\_enabled\_checkmarx) | Enable checkmarx | `bool` | `true` | no |
| <a name="input_is_enabled_sonarqube"></a> [is\_enabled\_sonarqube](#input\_is\_enabled\_sonarqube) | Enable sonarqube | `bool` | `true` | no |
| <a name="input_name"></a> [name](#input\_name) | Repository Name | `string` | n/a | yes |
| <a name="input_only_allow_merge_if_pipeline_succeeds"></a> [only\_allow\_merge\_if\_pipeline\_succeeds](#input\_only\_allow\_merge\_if\_pipeline\_succeeds) | Set to true if you want allow merges only if a pipeline succeeds. | `bool` | `false` | no |
| <a name="input_parent_group"></a> [parent\_group](#input\_parent\_group) | Parent Group | `string` | n/a | yes |
| <a name="input_project_type"></a> [project\_type](#input\_project\_type) | Project type | `string` | `""` | no |
| <a name="input_protected_branches"></a> [protected\_branches](#input\_protected\_branches) | Protected branches | <pre>map(object({<br/> push_access_level = string<br/> merge_access_level = string<br/> }))</pre> | <pre>{<br/> "master": {<br/> "merge_access_level": "developer",<br/> "push_access_level": "maintainer"<br/> }<br/>}</pre> | no |
| <a name="input_protected_tags"></a> [protected\_tags](#input\_protected\_tags) | Protected tags | <pre>map(object({<br/> create_access_level = string<br/> }))</pre> | <pre>{<br/> "v*": {<br/> "create_access_level": "maintainer"<br/> }<br/>}</pre> | no |
| <a name="input_scoped_variables"></a> [scoped\_variables](#input\_scoped\_variables) | {<br/> "VARIABLE\_NAME" = {<br/> description = "opis"<br/> protected = optional(bool, false)<br/> masked = optional(bool, false)<br/> values = {<br/> "environment\_name" = "value"<br/> "environment\_2" = "value2"<br/> }<br/> }<br/>} | <pre>map(object({<br/> description = optional(string, "")<br/> protected = optional(bool, false)<br/> masked = optional(bool, false)<br/> values = map(string)<br/> }))</pre> | `{}` | no |
| <a name="input_shared_runners_enabled"></a> [shared\_runners\_enabled](#input\_shared\_runners\_enabled) | Enable shared runners for this project. | `bool` | `true` | no |
| <a name="input_sib_aplikacja"></a> [sib\_aplikacja](#input\_sib\_aplikacja) | [UPW] ID Aplikacja w zasobach SIB | `string` | `""` | no |
| <a name="input_tags"></a> [tags](#input\_tags) | Tags | `list(string)` | `[]` | no |
| <a name="input_token_scope_groups"></a> [token\_scope\_groups](#input\_token\_scope\_groups) | CI\_JOB\_TOKEN group allowlist | `list(string)` | `[]` | no |
| <a name="input_token_scope_repositories"></a> [token\_scope\_repositories](#input\_token\_scope\_repositories) | CI\_JOB\_TOKEN repositories allowlist | `list(string)` | `[]` | no |
## Outputs
No outputs.

13
data.tf
View File

@@ -1 +1,12 @@
//Data data "gitlab_group" "parent" {
full_path = var.parent_group
}
data "gitlab_group" "token_scope_groups" {
for_each = toset(var.token_scope_groups)
full_path = each.key
}
data "gitlab_project" "token_scope_projects" {
for_each = toset(var.token_scope_repositories)
path_with_namespace = each.key
}

View File

@@ -0,0 +1,52 @@
{
"": {
"icon_type" : "",
"ci_config_path": ".gitlab-ci.yml",
"tags" : [],
"variables": {},
"scoped_variables": {},
"environments": {}
},
"python-poetry": {
"icon_type" : "python",
"ci_config_path": "application/python-poetry.yml@fabryka_ofert/fo.devops/gitlab/gitlab-ci",
"tags" : ["vagrant", "devops"],
"variables": {},
"scoped_variables": {},
"environments": {}
},
"container": {
"icon_type" : "container",
"ci_config_path": "containers/docker.yml",
"tags" : ["docker"],
"variables": {},
"scoped_variables": {},
"environments": {}
},
"packer": {
"icon_type" : "packer",
"ci_config_path": "infrastructure/packer.yml",
"tags" : ["packer"],
"variables": {},
"scoped_variables": {},
"environments": {}
},
"terraform": {
"icon_type" : "terraform",
"ci_config_path": "infrastructure/terraform.yml@fabryka_ofert/fo.devops/gitlab/gitlab-ci",
"tags" : ["terraform"],
"variables": {},
"scoped_variables": {},
"environments": {}
},
"terraform-module": {
"icon_type" : "terraform",
"ci_config_path": "infrastructure/terraform-module.yml@fabryka_ofert/fo.devops/gitlab/gitlab-ci",
"tags" : ["terraform", "terraform-module"],
"variables": {},
"scoped_variables": {},
"environments": {}
}
}

View File

@@ -1,3 +1,77 @@
//Locals
locals { locals {
avatars_dir = var.avatars_dir == "" ? "${path.root}/images" : var.avatars_dir
allowed_avatar_types_json = var.allowed_avatar_types_json == "" ? "${path.root}/data/allowed_avatar_project_types.json" : var.allowed_avatar_types_json
allowed_avatar_types = jsondecode(file("${local.allowed_avatar_types_json}"))
allowed_project_types_json = var.allowed_avatar_types_json == "" ? "${path.root}/data/allowed_project_types.json" : var.allowed_project_types_json
allowed_project_types = jsondecode(try(file("${local.allowed_project_types_json}"), null) == null ? file("${path.module}/data/allowed_project_types.json") : file(local.allowed_project_types_json))
# Define the allowed project types as a map
avatar_project = local.allowed_project_types[var.project_type].avatar == "" ? null : "${local.avatars_dir}/${local.allowed_project_types[var.project_type].avatar}.png"
avatar_path = var.avatar == "" ? local.avatar_project : "${local.avatars_dir}/${var.avatar}.png"
avatar = try(file("${local.avatar_path}"), null) == null ? "${local.avatar_path}" : null
token_scope_group_ids = [for g in values(data.gitlab_group.token_scope_groups) : g.id]
token_scope_project_ids = [for p in values(data.gitlab_project.token_scope_projects) : p.id]
merged_scope_variables = merge(
local.allowed_project_types[var.project_type].scoped_variables,
var.scoped_variables
)
merged_environments = merge(
local.allowed_project_types[var.project_type].environments,
var.environments
)
merged_project_variables = merge(
local.allowed_project_types[var.project_type].variables,
{
PROJECT_TYPE = {
description = "Project Type"
value = var.project_type
protected = "false"
masked = "false"
},
IS_ENABLED_CHECKMARX = {
description = "Enabled CheckMarx scan"
value = var.is_enabled_checkmarx == true ? "true" : "false"
protected = "false"
masked = "false"
},
IS_ENABLED_SONARQUBE = {
description = "Enabled SonarQube scan"
value = var.is_enabled_sonarqube == true ? "true" : "false"
protected = "false"
masked = "false"
},
SIB_APLIKACJA = {
description = "[UPW] ID Aplikacji zasobów SIB"
value = var.sib_aplikacja
protected = "false"
masked = "false"
}
},
var.ci_variables
)
scoped_variable_map = {
for pair in flatten([
for var_name, cfg in local.merged_scope_variables : [
for env_scope, v in cfg.values : {
id = "${var_name}::${env_scope}"
data = {
key = var_name
environment_scope = env_scope != "" ? env_scope : "*"
value = v
protected = cfg.protected
masked = cfg.masked
description = cfg.description
}
}
]
]) : pair.id => pair.data
}
} }

99
main.tf
View File

@@ -1 +1,98 @@
//Main resources resource "gitlab_project" "project" {
name = var.name
description = var.description
namespace_id = data.gitlab_group.parent.id
initialize_with_readme = var.forked_from_project_id == 0 ? true : null
default_branch = var.default_branch
tags = toset(concat(local.allowed_project_types[var.project_type].tags, var.tags))
ci_config_path = var.ci_config_path == null ? local.allowed_project_types[var.project_type].ci_config_path : var.ci_config_path
build_git_strategy = var.build_git_strategy
avatar = local.avatar == null ? null : "${local.avatar}"
avatar_hash = local.avatar == null ? null : filesha256("${local.avatar}")
archive_on_destroy = true
archived = var.archived
only_allow_merge_if_all_discussions_are_resolved = true
only_allow_merge_if_pipeline_succeeds = var.only_allow_merge_if_pipeline_succeeds
merge_pipelines_enabled = true
allow_merge_on_skipped_pipeline = var.allow_merge_on_skipped_pipeline
group_runners_enabled = var.group_runners_enabled
build_timeout = var.build_timeout
auto_cancel_pending_pipelines = var.auto_cancel_pending_pipelines
shared_runners_enabled = var.shared_runners_enabled
forked_from_project_id = var.forked_from_project_id == 0 ? null : var.forked_from_project_id
lifecycle {
prevent_destroy = true
}
}
resource "gitlab_project_push_rules" "push_rule" {
project = gitlab_project.project.id
commit_message_regex = var.is_enable_conventional_commits_push_rule == true ? "^((build|chore|ci|docs|feat|fix|perf|refactor|revert|style|test)(\\([-a-zA-Z0-9_]+\\))?(!)?(: (.*\\s*)*))|(Merge (.*\\s*)*)|(Initial commit$)" : ""
}
resource "gitlab_branch_protection" "protected_branches" {
for_each = var.protected_branches
project = gitlab_project.project.id
branch = each.key
push_access_level = each.value.push_access_level
merge_access_level = each.value.merge_access_level
allow_force_push = true
}
resource "gitlab_tag_protection" "protected_tags" {
for_each = var.protected_tags
project = gitlab_project.project.id
tag = each.key
create_access_level = each.value.create_access_level
}
resource "gitlab_project_variable" "variable" {
for_each = local.merged_project_variables
project = gitlab_project.project.id
key = each.key
value = each.value.value
description = each.value.description
protected = lookup(each.value, "protected", false)
masked = lookup(each.value, "masked", false)
environment_scope = lookup(each.value, "environment_scope", "*")
}
resource "gitlab_project_variable" "scoped_variables" {
for_each = local.scoped_variable_map
project = gitlab_project.project.id
key = each.value.key
value = each.value.value
environment_scope = each.value.environment_scope
protected = each.value.protected
masked = each.value.masked
description = each.value.description
}
resource "gitlab_project_environment" "environments" {
for_each = local.merged_environments
project = gitlab_project.project.id
name = each.key
external_url = each.value
stop_before_destroy = true
}
resource "gitlab_project_custom_attribute" "custom_attributes" {
for_each = var.attributes
project = gitlab_project.project.id
key = each.key
value = each.value
}
resource "gitlab_project_job_token_scopes" "ci_token_scope" {
project = gitlab_project.project.id
enabled = true
target_group_ids = local.token_scope_group_ids
target_project_ids = local.token_scope_project_ids
}

View File

@@ -1,3 +0,0 @@
output "example" {
//value = some_resource.example
}

View File

@@ -1,5 +1,8 @@
terraform { terraform {
required_providers { required_providers {
//Provider name gitlab = {
source = "gitlabhq/gitlab"
version = "18.0.0"
}
} }
} }

View File

@@ -1,9 +1,237 @@
variable "name" { variable "name" {
type = string type = string
description = "name" description = "Repository Name"
}
variable "forked_from_project_id" {
type = number
description = "Forked from"
default = 0
} }
variable "description" { variable "description" {
type = string type = string
description = "description" description = "Repository Description"
} }
variable "parent_group" {
type = string
description = "Parent Group"
}
variable "default_branch" {
type = string
description = "Default branch"
default = "master"
}
variable "ci_config_path" {
type = string
description = "CI PATH"
default = null
}
variable "tags" {
type = list(string)
description = "Tags"
default = []
}
variable "build_git_strategy" {
type = string
default = "clone"
description = "The Git strategy. Defaults to fetch."
}
variable "archived" {
type = bool
default = false
description = "Archived project"
}
variable "allowed_project_types_json" {
type = string
default = ""
description = "Path to allowed project types json"
}
variable "project_type" {
type = string
description = "Project type"
default = ""
validation {
condition = contains(keys(local.allowed_project_types), var.project_type)
error_message = "Unsupported project project_type"
}
}
variable "allowed_avatar_types_json" {
type = string
default = ""
description = "Path to allowed avatar types json"
}
variable "avatar" {
type = string
description = "Type of the avatar for the group (default: from type)"
default = ""
validation {
condition = contains(local.allowed_avatar_types, var.avatar)
error_message = "Unsupported group type"
}
}
variable "is_enable_conventional_commits_push_rule" {
type = bool
default = false
description = "Enable conventional commits push rule"
}
variable "protected_branches" {
type = map(object({
push_access_level = string
merge_access_level = string
}))
description = "Protected branches"
default = {
"master" = {
push_access_level = "maintainer"
merge_access_level = "developer"
}
}
}
variable "protected_tags" {
type = map(object({
create_access_level = string
}))
description = "Protected tags"
default = {
"v*" = {
create_access_level = "maintainer"
}
}
}
variable "is_enabled_checkmarx" {
type = bool
default = true
description = "Enable checkmarx"
}
variable "is_enabled_sonarqube" {
type = bool
default = true
description = "Enable sonarqube"
}
variable "sib_aplikacja" {
type = string
description = "[UPW] ID Aplikacja w zasobach SIB"
default = ""
}
variable "ci_variables" {
type = map(object({
value = string
description = optional(string)
protected = optional(bool)
masked = optional(bool)
environment_scope = optional(string)
}))
description = "CI variables to be set for the group"
default = null
}
variable "scoped_variables" {
description = <<-EOT
{
"VARIABLE_NAME" = {
description = "opis"
protected = optional(bool, false)
masked = optional(bool, false)
values = {
"environment_name" = "value"
"environment_2" = "value2"
}
}
}
EOT
type = map(object({
description = optional(string, "")
protected = optional(bool, false)
masked = optional(bool, false)
values = map(string)
}))
default = {}
}
variable "environments" {
type = map(string)
description = "Project environments"
default = {}
}
variable "attributes" {
type = map(string)
default = {}
description = "custom attributes to be set for the project"
}
variable "avatars_dir" {
description = "Avatars directory png files"
type = string
default = ""
}
variable "only_allow_merge_if_pipeline_succeeds" {
description = "Set to true if you want allow merges only if a pipeline succeeds."
type = bool
default = false
}
variable "allow_merge_on_skipped_pipeline" {
description = "Set to true if you want to treat skipped pipelines as if they finished with success."
type = bool
default = true
}
variable "group_runners_enabled" {
description = "Enable group runners for this project."
type = bool
default = true
}
variable "shared_runners_enabled" {
description = "Enable shared runners for this project."
type = bool
default = true
}
variable "build_timeout" {
description = "The maximum amount of time, in seconds, that a job can run."
type = number
default = 3600
}
variable "auto_cancel_pending_pipelines" {
description = "Auto-cancel pending pipelines. This isnt a boolean, but enabled/disabled."
type = string
default = "enabled"
}
variable "token_scope_groups" {
description = "CI_JOB_TOKEN group allowlist"
type = list(string)
default = []
}
variable "token_scope_repositories" {
description = "CI_JOB_TOKEN repositories allowlist"
type = list(string)
default = []
}