diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..e32a21f --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1 @@ +* @softservedata diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..378b862 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,9 @@ +## Describe your changes + +## Issue ticket number and link + +## Checklist before requesting a review +- [ ] I have performed a self-review of my code +- [ ] If it is a core feature, I have added thorough tests +- [ ] Do we need to implement analytics? +- [ ] Will this be part of a product update? If yes, please write one phrase about this update diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml index 6197608..72f7bbf 100644 --- a/.github/workflows/ruby.yml +++ b/.github/workflows/ruby.yml @@ -43,6 +43,13 @@ jobs: - name: Terraform Init run: terraform init - name: Test Terraform Config + env: + TF_VAR_github_token: ${{ secrets.PAT }} + TF_VAR_github_owner: Practical-DevOps-GitHub + TF_VAR_repository_name: github-terraform-task-Sp1ker2 + TF_VAR_deploy_key_public: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFvrsZxKSgvkIZOOpyGY59VPhz1c33Je/Sci+fMY+MnM deploy_key" + TF_VAR_discord_webhook_url: "https://discord.com/api/webhooks/1234567890123456789/temporary-webhook" + TF_VAR_pat_token: ${{ secrets.PAT }} run: | terraform validate terraform plan -no-color -out tfplan diff --git a/README.md b/README.md index e380385..e2b2f2d 100644 --- a/README.md +++ b/README.md @@ -30,3 +30,75 @@ Write Terraform code that configures the GitHub repository according to the foll 7. For GitHub actions, perform the following: - create PAT (Personal Access Token) with **Full control of private repositories** and **Full control of orgs and teams, read and write org projects** - add the PAT to the repository actions secrets key with the name `PAT` and the value of the created PAT. + +--- + +## ✅ Solution + +This repository contains a complete Terraform solution that automates all the requirements above. + +### 📁 Structure + +``` +src/ +├── main.tf # Main Terraform configuration +├── variables.tf # Input variables definition +├── outputs.tf # Output values +├── terraform.tfvars.example # Example configuration file +├── .gitignore # Ignore sensitive files +├── setup.sh # Automated setup script +├── README.md # Detailed documentation +└── QUICKSTART.md # Quick start guide +``` + +### 🚀 Quick Start + +1. **Navigate to the src directory:** + ```bash + cd src + ``` + +2. **Follow the Quick Start Guide:** + ```bash + cat QUICKSTART.md + ``` + +3. **Or use the automated setup:** + ```bash + ./setup.sh + ``` + +### 📋 What Gets Configured + +- ✅ **Collaborator**: Adds `softservedata` with push access +- ✅ **Branches**: Creates `develop` and sets it as default +- ✅ **Branch Protection**: + - `main`: Requires PR + owner approval + code owner review + - `develop`: Requires PR + 2 approvals +- ✅ **CODEOWNERS**: Assigns `softservedata` as code owner for all files +- ✅ **PR Template**: Creates `.github/pull_request_template.md` +- ✅ **Deploy Key**: Adds SSH deploy key named `DEPLOY_KEY` +- ✅ **Discord Webhook**: Configures PR notifications to Discord +- ✅ **Secrets**: Adds `PAT` and `TERRAFORM` to repository secrets + +### 📚 Documentation + +- **[QUICKSTART.md](src/QUICKSTART.md)** - Step-by-step quick start guide +- **[README.md](src/README.md)** - Comprehensive documentation with troubleshooting + +### 🔧 Prerequisites + +1. Terraform (1.0+) +2. GitHub Personal Access Token with appropriate permissions +3. Discord webhook URL +4. SSH key pair for deploy key + +### 💡 Usage + +Detailed instructions are available in the `src` directory. The solution includes: +- Automated setup script for easy deployment +- Example configuration files +- Comprehensive error handling +- Step-by-step manual instructions + +For detailed setup instructions, see [src/README.md](src/README.md) or [src/QUICKSTART.md](src/QUICKSTART.md). diff --git a/src/.gitignore b/src/.gitignore new file mode 100644 index 0000000..c99bfe6 --- /dev/null +++ b/src/.gitignore @@ -0,0 +1,38 @@ +# Local .terraform directories +**/.terraform/* + +# .tfstate files +*.tfstate +*.tfstate.* + +# Crash log files +crash.log +crash.*.log + +# Exclude all .tfvars files, which contain sensitive data +*.tfvars +!terraform.tfvars.example + +# Ignore override files +override.tf +override.tf.json +*_override.tf +*_override.tf.json + +# Ignore CLI configuration files +.terraformrc +terraform.rc + +# SSH keys +deploy_key +deploy_key.pub +*.pem +*.key + +# Combined terraform file +all_terraform_code.txt +combine_tf.sh +update_terraform_secret.sh +terraform_code_content.txt +main_for_secret.tf + diff --git a/src/.keep b/src/.keep deleted file mode 100644 index e69de29..0000000 diff --git a/src/.terraform.lock.hcl b/src/.terraform.lock.hcl new file mode 100644 index 0000000..f04f45d --- /dev/null +++ b/src/.terraform.lock.hcl @@ -0,0 +1,25 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/integrations/github" { + version = "6.8.3" + constraints = "~> 6.0" + hashes = [ + "h1:aJDtXRORhhNljqxf8V8zE2PGXs0clB1NO9zR2Kduf2E=", + "zh:0795635834c762371aae1748f68d17db778918f48a630c69e673e0339edc0869", + "zh:191649a4ca68b8c5235712247b9ae05b16123e912c8e0f875267df68fda64452", + "zh:3a5260d0af06c37a346e9397f7563e03247c99906b4d2df9d615ab72a6a2dde1", + "zh:57b5f57e45a84124780ebc5b2ffb40926a513dfdd45193eab137634c765db5b0", + "zh:639568914b977203fa3f94dc55c256022f800daaaeb66084e01302cffda9d933", + "zh:8976e4963db88a5ad8209f0422754f2aa75220f12123228804cc97169f701ee0", + "zh:971e1021c45ab06caa966030494957c0e87bd9e30cd8358e41aaf8c120352186", + "zh:9e379ed9235f5dadb4c5b625016a474961d39fba5753a3155f3dda56446f0ec2", + "zh:a50e5e02cd99479d8bc9b06c428b610562986931ba258b45c09f2dec76711086", + "zh:b421552318952b2fa30ef30b4279b56620bddef65d11cbda1cfa123be5a3bf9c", + "zh:bc8bf3a88b9daaca1ce1e5b3e59be8ae0be504f111106094de791e19e0e49c9d", + "zh:d3f9b1d8ed5a58a8e22aa20e3d76dc7afe83f648a41ff996e445de0c6a1f13cc", + "zh:dc55d47cb73f633e9f5d4ebcfba1a2212b6e83fcb7a6c7487606324053a2943f", + "zh:dfc8e85505e3ce90673b460833e94d935142145b79265912c3c805d8de12c4f2", + "zh:fbd1fee2c9df3aa19cf8851ce134dea6e45ea01cb85695c1726670c285797e25", + ] +} diff --git a/src/main.tf b/src/main.tf new file mode 100644 index 0000000..7260dff --- /dev/null +++ b/src/main.tf @@ -0,0 +1,143 @@ +terraform { + required_providers { + github = { + source = "integrations/github" + version = "~> 6.0" + } + } +} + +provider "github" { + token = var.github_token + owner = var.github_owner +} + +# Get the repository +data "github_repository" "repo" { + name = var.repository_name +} + +# Add collaborator +resource "github_repository_collaborator" "softservedata" { + repository = data.github_repository.repo.name + username = "softservedata" + permission = "push" +} + +# Create develop branch from main +resource "github_branch" "develop" { + repository = data.github_repository.repo.name + branch = "develop" +} + +# Set develop as default branch +resource "github_branch_default" "default" { + repository = data.github_repository.repo.name + branch = github_branch.develop.branch +} + +# Branch protection for main branch +resource "github_branch_protection" "main_protection" { + repository_id = data.github_repository.repo.node_id + pattern = "main" + + required_pull_request_reviews { + dismiss_stale_reviews = true + require_code_owner_reviews = true + required_approving_review_count = 0 + restrict_dismissals = false + } + + enforce_admins = false + + depends_on = [github_repository_collaborator.softservedata] +} + +# Branch protection for develop branch +resource "github_branch_protection" "develop_protection" { + repository_id = data.github_repository.repo.node_id + pattern = "develop" + + required_pull_request_reviews { + dismiss_stale_reviews = true + require_code_owner_reviews = false + required_approving_review_count = 2 + restrict_dismissals = false + } + + enforce_admins = false + + depends_on = [github_branch.develop, github_repository_collaborator.softservedata] +} + +# Add CODEOWNERS file +resource "github_repository_file" "codeowners" { + repository = data.github_repository.repo.name + branch = "main" + file = ".github/CODEOWNERS" + content = "* @softservedata\n" + commit_message = "Add CODEOWNERS file" + commit_author = "Terraform" + commit_email = "terraform@example.com" + overwrite_on_create = true +} + +# Add pull request template +resource "github_repository_file" "pr_template" { + repository = data.github_repository.repo.name + branch = "main" + file = ".github/pull_request_template.md" + content = <<-EOT +## Describe your changes + +## Issue ticket number and link + +## Checklist before requesting a review +- [ ] I have performed a self-review of my code +- [ ] If it is a core feature, I have added thorough tests +- [ ] Do we need to implement analytics? +- [ ] Will this be part of a product update? If yes, please write one phrase about this update +EOT + commit_message = "Add pull request template" + commit_author = "Terraform" + commit_email = "terraform@example.com" + overwrite_on_create = true +} + +# Add deploy key +resource "github_repository_deploy_key" "deploy_key" { + title = "DEPLOY_KEY" + repository = data.github_repository.repo.name + key = var.deploy_key_public + read_only = false +} + +# Add Discord webhook +resource "github_repository_webhook" "discord" { + repository = data.github_repository.repo.name + + configuration { + url = var.discord_webhook_url + content_type = "json" + insecure_ssl = false + } + + active = true + + events = ["pull_request"] +} + +# Add PAT to repository secrets +resource "github_actions_secret" "pat" { + repository = data.github_repository.repo.name + secret_name = "PAT" + plaintext_value = var.pat_token +} + +# Add TERRAFORM secret with the Terraform code +resource "github_actions_secret" "terraform_code" { + repository = data.github_repository.repo.name + secret_name = "TERRAFORM" + plaintext_value = var.terraform_code +} + diff --git a/src/outputs.tf b/src/outputs.tf new file mode 100644 index 0000000..989aebf --- /dev/null +++ b/src/outputs.tf @@ -0,0 +1,31 @@ +output "repository_name" { + description = "The name of the configured repository" + value = data.github_repository.repo.name +} + +output "repository_url" { + description = "The URL of the configured repository" + value = data.github_repository.repo.html_url +} + +output "default_branch" { + description = "The default branch of the repository" + value = github_branch_default.default.branch +} + +output "collaborator_added" { + description = "Collaborator username added to the repository" + value = github_repository_collaborator.softservedata.username +} + +output "deploy_key_id" { + description = "ID of the deploy key" + value = github_repository_deploy_key.deploy_key.id +} + +output "webhook_url" { + description = "Discord webhook URL (masked)" + value = "Configured" + sensitive = true +} + diff --git a/src/terraform.tfvars.example b/src/terraform.tfvars.example new file mode 100644 index 0000000..f0541bd --- /dev/null +++ b/src/terraform.tfvars.example @@ -0,0 +1,19 @@ +# Copy this file to terraform.tfvars and fill in your values + +github_token = "ghp_your_github_token_here" +github_owner = "Practical-DevOps-GitHub" +repository_name = "github-terraform-task-Sp1ker2" + +# Generate SSH key pair with: ssh-keygen -t ed25519 -C "deploy_key" -f deploy_key +# Then use the public key (deploy_key.pub) here +deploy_key_public = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA... deploy_key" + +# Discord webhook URL (Create in Discord: Server Settings -> Integrations -> Webhooks) +discord_webhook_url = "https://discord.com/api/webhooks/YOUR_WEBHOOK_ID/YOUR_WEBHOOK_TOKEN" + +# PAT with "Full control of private repositories" and "Full control of orgs and teams" +pat_token = "ghp_your_pat_token_here" + +# This will be populated automatically - leave empty for now +terraform_code = "" + diff --git a/src/variables.tf b/src/variables.tf new file mode 100644 index 0000000..a8f3cc7 --- /dev/null +++ b/src/variables.tf @@ -0,0 +1,40 @@ +variable "github_token" { + description = "GitHub Personal Access Token with repo and admin:org permissions" + type = string + sensitive = true +} + +variable "github_owner" { + description = "GitHub repository owner (username or organization)" + type = string +} + +variable "repository_name" { + description = "Name of the GitHub repository" + type = string +} + +variable "deploy_key_public" { + description = "Public SSH key for deploy key" + type = string + sensitive = true +} + +variable "discord_webhook_url" { + description = "Discord webhook URL for pull request notifications" + type = string + sensitive = true +} + +variable "pat_token" { + description = "Personal Access Token with full control of private repositories and orgs" + type = string + sensitive = true +} + +variable "terraform_code" { + description = "The Terraform code to be stored in repository secret" + type = string + sensitive = true +} +