add ci/cd test
This commit is contained in:
240
.template/ci-cd/gitea-cicd.yml
Normal file
240
.template/ci-cd/gitea-cicd.yml
Normal file
@@ -0,0 +1,240 @@
|
|||||||
|
name: Gitea Actions - Terraform CI/CD
|
||||||
|
run-name: ${{ gitea.actor }} is running Terraform CI/CD 🚀
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
types: [opened, synchronize, reopened]
|
||||||
|
branches:
|
||||||
|
- main # Проверка PRs В main
|
||||||
|
- dev # Проверка PRs В dev
|
||||||
|
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- dev # При push в dev создаем PR в main
|
||||||
|
- main # При push в main применяем изменения
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
pull-requests: write
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
terraform-ci:
|
||||||
|
runs-on: code-runner00
|
||||||
|
env:
|
||||||
|
GITEA_URL: "http://code.hlc.lab" # ⚠️ ЗАМЕНИТЕ на ваш URL
|
||||||
|
GITEA_TOKEN: ${{ secrets.GITEATOKEN }}
|
||||||
|
|
||||||
|
# Terraform переменные
|
||||||
|
TF_IN_AUTOMATION: "true"
|
||||||
|
TF_VAR_PVE_CLUSTER_API_ID: ${{ secrets.TF_VAR_PVE_CLUSTER_API_ID }}
|
||||||
|
TF_VAR_PVE_CLUSTER_API_TOKEN: ${{ secrets.TF_VAR_PVE_CLUSTER_API_TOKEN }}
|
||||||
|
TF_VAR_PVE_CLUSTER_URL: ${{ secrets.TF_VAR_PVE_CLUSTER_URL }}
|
||||||
|
TF_VAR_POWERDNS_API_URL: ${{ secrets.TF_VAR_POWERDNS_API_URL }}
|
||||||
|
TF_VAR_POWERDNS_API_TOKEN: ${{ secrets.TF_VAR_POWERDNS_API_TOKEN }}
|
||||||
|
|
||||||
|
# AWS переменные (если используете)
|
||||||
|
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||||
|
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0 # Для корректной работы с ветками
|
||||||
|
|
||||||
|
- name: Create PR from dev to main
|
||||||
|
if: github.event_name == 'push' && github.ref == 'refs/heads/dev'
|
||||||
|
id: create-pr
|
||||||
|
run: |
|
||||||
|
echo "🔄 Создание Pull Request из dev в main..."
|
||||||
|
|
||||||
|
# Проверяем, существует ли уже открытый PR
|
||||||
|
EXISTING_PR=$(curl -s -H "Authorization: token $GITEA_TOKEN" \
|
||||||
|
"$GITEA_URL/api/v1/repos/${{ github.repository }}/pulls?state=open&base=main&head=dev" | jq length)
|
||||||
|
|
||||||
|
if [ "$EXISTING_PR" -eq "0" ]; then
|
||||||
|
# Создаем новый PR
|
||||||
|
RESPONSE=$(curl -s -X POST \
|
||||||
|
-H "Authorization: token $GITEA_TOKEN" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d "{
|
||||||
|
\"title\": \"[Auto] Merge dev → main - $(date +'%Y-%m-%d %H:%M')\",
|
||||||
|
\"body\": \"Автоматически созданный PR из ветки dev.\\n\\n**Изменения:**\\n${{ github.event.head_commit.message }}\",
|
||||||
|
\"head\": \"dev\",
|
||||||
|
\"base\": \"main\",
|
||||||
|
\"draft\": false
|
||||||
|
}" \
|
||||||
|
"$GITEA_URL/api/v1/repos/${{ github.repository }}/pulls")
|
||||||
|
|
||||||
|
PR_NUMBER=$(echo "$RESPONSE" | jq -r '.number // empty')
|
||||||
|
|
||||||
|
if [ -n "$PR_NUMBER" ]; then
|
||||||
|
echo "✅ PR создан: #$PR_NUMBER"
|
||||||
|
echo "pr_number=$PR_NUMBER" >> $GITHUB_OUTPUT
|
||||||
|
else
|
||||||
|
echo "❌ Ошибка создания PR"
|
||||||
|
echo "$RESPONSE" | jq .
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "📝 PR уже существует, обновляем..."
|
||||||
|
echo "pr_number=existing" >> $GITHUB_OUTPUT
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Setup Terraform
|
||||||
|
run: |
|
||||||
|
# Проверяем установку Terraform
|
||||||
|
terraform version
|
||||||
|
echo "Terraform готов к работе"
|
||||||
|
|
||||||
|
# 📋 Terraform проверки (выполняются всегда)
|
||||||
|
- name: Terraform Format Check
|
||||||
|
id: fmt
|
||||||
|
run: |
|
||||||
|
if terraform fmt -check -recursive; then
|
||||||
|
echo "✅ Форматирование корректно"
|
||||||
|
echo "fmt_status=passed" >> $GITHUB_OUTPUT
|
||||||
|
else
|
||||||
|
echo "⚠️ Найдены проблемы с форматированием"
|
||||||
|
echo "fmt_status=failed" >> $GITHUB_OUTPUT
|
||||||
|
fi
|
||||||
|
continue-on-error: true
|
||||||
|
|
||||||
|
- name: Terraform Init
|
||||||
|
id: init
|
||||||
|
run: terraform init
|
||||||
|
|
||||||
|
- name: Terraform Validate
|
||||||
|
id: validate
|
||||||
|
run: terraform validate -no-color
|
||||||
|
|
||||||
|
# 🗺️ Terraform Plan (для PR и push в dev)
|
||||||
|
- name: Terraform Plan
|
||||||
|
id: plan
|
||||||
|
if: |
|
||||||
|
github.event_name == 'pull_request' ||
|
||||||
|
(github.event_name == 'push' && github.ref == 'refs/heads/dev')
|
||||||
|
run: |
|
||||||
|
echo "📋 Генерация Terraform плана..."
|
||||||
|
|
||||||
|
# Генерируем план
|
||||||
|
terraform plan -no-color -out=tfplan 2>&1 | tee plan_output.txt
|
||||||
|
|
||||||
|
# Проверяем наличие опасных изменений
|
||||||
|
if grep -q "destroy and then create replacement" plan_output.txt; then
|
||||||
|
echo "has_replace=true" >> $GITHUB_OUTPUT
|
||||||
|
echo "replace_count=$(grep -c 'destroy and then create replacement' plan_output.txt)" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
# Извлекаем имена ресурсов для замены
|
||||||
|
grep -B1 "destroy and then create replacement" plan_output.txt | grep "# " | sed 's/^[[:space:]]*#[[:space:]]*//' > replace_resources.txt
|
||||||
|
echo "replace_resources<<EOF" >> $GITHUB_OUTPUT
|
||||||
|
cat replace_resources.txt >> $GITHUB_OUTPUT
|
||||||
|
echo "EOF" >> $GITHUB_OUTPUT
|
||||||
|
fi
|
||||||
|
|
||||||
|
if grep -q "^[[:space:]]*\- destroy" plan_output.txt; then
|
||||||
|
echo "has_destroy=true" >> $GITHUB_OUTPUT
|
||||||
|
echo "destroy_count=$(grep -c '^[[:space:]]*\- destroy' plan_output.txt)" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
# Извлекаем имена ресурсов для удаления
|
||||||
|
grep "^[[:space:]]*\- destroy" plan_output.txt -B1 | grep "# " | sed 's/^[[:space:]]*#[[:space:]]*//' > destroy_resources.txt
|
||||||
|
echo "destroy_resources<<EOF" >> $GITHUB_OUTPUT
|
||||||
|
cat destroy_resources.txt >> $GITHUB_OUTPUT
|
||||||
|
echo "EOF" >> $GITHUB_OUTPUT
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Сохраняем полный вывод плана
|
||||||
|
PLAN_CONTENT=$(cat plan_output.txt | jq -Rs .)
|
||||||
|
echo "plan_content=$PLAN_CONTENT" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
echo "✅ План сгенерирован"
|
||||||
|
|
||||||
|
- name: Create Gitea PR Comment
|
||||||
|
if: github.event_name == 'pull_request'
|
||||||
|
env:
|
||||||
|
PR_NUMBER: ${{ github.event.pull_request.number }}
|
||||||
|
REPO_OWNER: ${{ github.repository_owner }}
|
||||||
|
REPO_NAME: ${{ github.event.repository.name }}
|
||||||
|
run: |
|
||||||
|
echo "💬 Добавление комментария в PR #$PR_NUMBER..."
|
||||||
|
|
||||||
|
# Проверяем, сгенерирован ли план
|
||||||
|
if [ ! -f "plan_output.txt" ]; then
|
||||||
|
echo "⚠️ Файл плана не найден, пропускаем комментарий"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Создаем Markdown комментарий
|
||||||
|
cat > comment.md << 'EOF'
|
||||||
|
## 🔧 Terraform Plan Report
|
||||||
|
|
||||||
|
### 📊 Проверки:
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Добавляем статусы
|
||||||
|
echo "- **Format Check:** ${{ steps.fmt.outputs.fmt_status == 'passed' && '✅ passed' || '⚠️ failed' }}" >> comment.md
|
||||||
|
echo "- **Validation:** ${{ steps.validate.outcome == 'success' && '✅ passed' || '❌ failed' }}" >> comment.md
|
||||||
|
echo "- **Plan:** ${{ steps.plan.outcome == 'success' && '✅ generated' || '⚠️ issues' }}" >> comment.md
|
||||||
|
|
||||||
|
# Предупреждения о деструктивных изменениях
|
||||||
|
if [ "${{ steps.plan.outputs.has_replace }}" = "true" ]; then
|
||||||
|
echo "" >> comment.md
|
||||||
|
echo "### ⚠️ REPLACE OPERATIONS DETECTED!" >> comment.md
|
||||||
|
echo "**${{ steps.plan.outputs.replace_count }}** ресурсов будут пересозданы:" >> comment.md
|
||||||
|
echo '```' >> comment.md
|
||||||
|
echo "${{ steps.plan.outputs.replace_resources }}" >> comment.md
|
||||||
|
echo '```' >> comment.md
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "${{ steps.plan.outputs.has_destroy }}" = "true" ]; then
|
||||||
|
echo "" >> comment.md
|
||||||
|
echo "### 🗑️ DESTROY OPERATIONS DETECTED!" >> comment.md
|
||||||
|
echo "**${{ steps.plan.outputs.destroy_count }}** ресурсов будут удалены:" >> comment.md
|
||||||
|
echo '```' >> comment.md
|
||||||
|
echo "${{ steps.plan.outputs.destroy_resources }}" >> comment.md
|
||||||
|
echo '```' >> comment.md
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Полный план
|
||||||
|
echo "" >> comment.md
|
||||||
|
echo "<details>" >> comment.md
|
||||||
|
echo "<summary>📄 Full Terraform Plan Output</summary>" >> comment.md
|
||||||
|
echo "" >> comment.md
|
||||||
|
echo '```terraform' >> comment.md
|
||||||
|
cat plan_output.txt >> comment.md
|
||||||
|
echo '```' >> comment.md
|
||||||
|
echo "</details>" >> comment.md
|
||||||
|
|
||||||
|
# Отправляем через Gitea API
|
||||||
|
COMMENT_BODY=$(jq -n --arg body "$(cat comment.md)" '{"body": $body}')
|
||||||
|
|
||||||
|
curl -X POST \
|
||||||
|
-H "Authorization: token $GITEA_TOKEN" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d "$COMMENT_BODY" \
|
||||||
|
"$GITEA_URL/api/v1/repos/${{ github.repository }}/issues/$PR_NUMBER/comments"
|
||||||
|
|
||||||
|
echo "✅ Комментарий добавлен"
|
||||||
|
|
||||||
|
- name: Block on Destructive Changes
|
||||||
|
if: |
|
||||||
|
github.event_name == 'pull_request' &&
|
||||||
|
(steps.plan.outputs.has_replace == 'true' || steps.plan.outputs.has_destroy == 'true')
|
||||||
|
run: |
|
||||||
|
echo "🚨 ОБНАРУЖЕНЫ ОПАСНЫЕ ИЗМЕНЕНИЯ!"
|
||||||
|
echo "Этот PR содержит destroy/replace операции."
|
||||||
|
echo "Требуется ручной review перед мержем."
|
||||||
|
exit 1
|
||||||
|
|
||||||
|
- name: Terraform Apply
|
||||||
|
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
||||||
|
run: |
|
||||||
|
echo "🚀 Применение изменений в main..."
|
||||||
|
|
||||||
|
if [ -f "tfplan" ]; then
|
||||||
|
terraform apply -auto-approve tfplan
|
||||||
|
else
|
||||||
|
terraform apply -auto-approve
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "✅ Изменения применены"
|
||||||
|
|
||||||
Reference in New Issue
Block a user