- Убрана подстановка значений по умолчанию для devops_password и devops_ssh_public_key - Добавлена строгая валидация секретов из vault/secrets.yml с детальными сообщениями об ошибках - Убран подробный вывод установки пакетов в тасках - Исправлена проблема с созданием симлинков в vault/ при тестировании - Обновлена логика загрузки vault переменных в molecule тестах - Добавлена очистка симлинков в destroy.yml для дополнительной безопасности Автор: Сергей Антропов Сайт: https://devops.org.ru
		
			
				
	
	
		
			914 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
			
		
		
	
	
			914 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
| # Настройка CI/CD для DevOpsLab
 | ||
| 
 | ||
| **Автор:** Сергей Антропов  
 | ||
| **Сайт:** https://devops.org.ru
 | ||
| 
 | ||
| ## 🚀 GitHub Actions
 | ||
| 
 | ||
| ### Базовая конфигурация
 | ||
| 
 | ||
| **`.github/workflows/ansible-test.yml`:**
 | ||
| ```yaml
 | ||
| name: Ansible Testing
 | ||
| on: [push, pull_request]
 | ||
| 
 | ||
| jobs:
 | ||
|   lint:
 | ||
|     runs-on: ubuntu-latest
 | ||
|     steps:
 | ||
|       - uses: actions/checkout@v4
 | ||
|       - name: Setup Python
 | ||
|         uses: actions/setup-python@v4
 | ||
|         with:
 | ||
|           python-version: '3.11'
 | ||
|       - name: Install dependencies
 | ||
|         run: |
 | ||
|           pip install ansible ansible-lint
 | ||
|           ansible-galaxy collection install -r requirements.yml
 | ||
|       - name: Run lint
 | ||
|         run: make role lint
 | ||
| 
 | ||
|   test:
 | ||
|     runs-on: ubuntu-latest
 | ||
|     needs: lint
 | ||
|     strategy:
 | ||
|       matrix:
 | ||
|         preset: [minimal, default, performance]
 | ||
|     steps:
 | ||
|       - uses: actions/checkout@v4
 | ||
|       - name: Setup Docker
 | ||
|         run: |
 | ||
|           sudo systemctl start docker
 | ||
|           sudo usermod -aG docker $USER
 | ||
|       - name: Run tests
 | ||
|         run: make role test ${{ matrix.preset }}
 | ||
| 
 | ||
|   deploy-check:
 | ||
|     runs-on: ubuntu-latest
 | ||
|     needs: [lint, test]
 | ||
|     if: github.ref == 'refs/heads/main'
 | ||
|     steps:
 | ||
|       - uses: actions/checkout@v4
 | ||
|       - name: Check deployment
 | ||
|         run: make role deploy
 | ||
|         env:
 | ||
|           ANSIBLE_HOST_KEY_CHECKING: false
 | ||
| ```
 | ||
| 
 | ||
| ### Продвинутая конфигурация
 | ||
| 
 | ||
| **`.github/workflows/ansible-advanced.yml`:**
 | ||
| ```yaml
 | ||
| name: Advanced Ansible Testing
 | ||
| on: [push, pull_request]
 | ||
| 
 | ||
| env:
 | ||
|   ANSIBLE_FORCE_COLOR: 'true'
 | ||
|   DOCKER_TLS_CERTDIR: ''
 | ||
| 
 | ||
| jobs:
 | ||
|   detect-roles:
 | ||
|     runs-on: ubuntu-latest
 | ||
|     outputs:
 | ||
|       roles: ${{ steps.detect.outputs.roles }}
 | ||
|     steps:
 | ||
|       - uses: actions/checkout@v4
 | ||
|       - name: Detect new roles
 | ||
|         id: detect
 | ||
|         run: |
 | ||
|           echo "roles=$(find roles/ -name 'main.yml' -path '*/tasks/*' | sed 's|roles/||; s|/tasks/main.yml||' | tr '\n' ' ')" >> $GITHUB_OUTPUT
 | ||
| 
 | ||
|   update-playbooks:
 | ||
|     runs-on: ubuntu-latest
 | ||
|     needs: detect-roles
 | ||
|     steps:
 | ||
|       - uses: actions/checkout@v4
 | ||
|       - name: Update playbooks
 | ||
|         run: |
 | ||
|           chmod +x scripts/update-playbooks.sh
 | ||
|           ./scripts/update-playbooks.sh
 | ||
|       - name: Commit changes
 | ||
|         run: |
 | ||
|           git config --local user.email "action@github.com"
 | ||
|           git config --local user.name "GitHub Action"
 | ||
|           git add molecule/default/run.yml roles/deploy.yml
 | ||
|           git diff --staged --quiet || git commit -m "Auto-update playbooks for new roles"
 | ||
|           git push
 | ||
| 
 | ||
|   lint:
 | ||
|     runs-on: ubuntu-latest
 | ||
|     needs: update-playbooks
 | ||
|     steps:
 | ||
|       - uses: actions/checkout@v4
 | ||
|       - name: Setup Python
 | ||
|         uses: actions/setup-python@v4
 | ||
|         with:
 | ||
|           python-version: '3.11'
 | ||
|       - name: Install dependencies
 | ||
|         run: |
 | ||
|           pip install ansible ansible-lint
 | ||
|           ansible-galaxy collection install -r requirements.yml
 | ||
|       - name: Run lint
 | ||
|         run: make role lint
 | ||
| 
 | ||
|   test:
 | ||
|     runs-on: ubuntu-latest
 | ||
|     needs: [update-playbooks, lint]
 | ||
|     strategy:
 | ||
|       matrix:
 | ||
|         preset: [minimal, default, performance]
 | ||
|     steps:
 | ||
|       - uses: actions/checkout@v4
 | ||
|       - name: Setup Docker
 | ||
|         run: |
 | ||
|           sudo systemctl start docker
 | ||
|           sudo usermod -aG docker $USER
 | ||
|       - name: Run tests
 | ||
|         run: make role test ${{ matrix.preset }}
 | ||
| 
 | ||
|   deploy-check:
 | ||
|     runs-on: ubuntu-latest
 | ||
|     needs: [lint, test]
 | ||
|     if: github.ref == 'refs/heads/main'
 | ||
|     steps:
 | ||
|       - uses: actions/checkout@v4
 | ||
|       - name: Check deployment
 | ||
|         run: make role deploy
 | ||
|         env:
 | ||
|           ANSIBLE_HOST_KEY_CHECKING: false
 | ||
| 
 | ||
|   notify:
 | ||
|     runs-on: ubuntu-latest
 | ||
|     needs: [lint, test, deploy-check]
 | ||
|     if: always()
 | ||
|     steps:
 | ||
|       - name: Notify on success
 | ||
|         if: needs.lint.result == 'success' && needs.test.result == 'success'
 | ||
|         run: |
 | ||
|           echo "✅ All tests passed for new roles"
 | ||
|           curl -X POST -H 'Content-type: application/json' \
 | ||
|             --data '{"text":"✅ Ansible role tests passed for new roles"}' \
 | ||
|             ${{ secrets.SLACK_WEBHOOK_URL }}
 | ||
|       - name: Notify on failure
 | ||
|         if: needs.lint.result == 'failure' || needs.test.result == 'failure'
 | ||
|         run: |
 | ||
|           echo "❌ Tests failed for new roles"
 | ||
|           curl -X POST -H 'Content-type: application/json' \
 | ||
|             --data '{"text":"❌ Ansible role tests failed for new roles"}' \
 | ||
|             ${{ secrets.SLACK_WEBHOOK_URL }}
 | ||
| ```
 | ||
| 
 | ||
| ## 🏢 Azure DevOps
 | ||
| 
 | ||
| ### Базовая конфигурация
 | ||
| 
 | ||
| **`azure-pipelines.yml`:**
 | ||
| ```yaml
 | ||
| trigger:
 | ||
| - main
 | ||
| - develop
 | ||
| 
 | ||
| pool:
 | ||
|   vmImage: 'ubuntu-latest'
 | ||
| 
 | ||
| variables:
 | ||
|   ANSIBLE_FORCE_COLOR: 'true'
 | ||
|   DOCKER_TLS_CERTDIR: ''
 | ||
| 
 | ||
| stages:
 | ||
| - stage: Lint
 | ||
|   displayName: 'Lint Stage'
 | ||
|   jobs:
 | ||
|   - job: LintJob
 | ||
|     displayName: 'Run Lint'
 | ||
|     steps:
 | ||
|     - task: UsePythonVersion@0
 | ||
|       inputs:
 | ||
|         versionSpec: '3.11'
 | ||
|     - script: |
 | ||
|         pip install ansible ansible-lint
 | ||
|         ansible-galaxy collection install -r requirements.yml
 | ||
|         make role lint
 | ||
|       displayName: 'Run Ansible Lint'
 | ||
| 
 | ||
| - stage: Test
 | ||
|   displayName: 'Test Stage'
 | ||
|   dependsOn: Lint
 | ||
|   jobs:
 | ||
|   - job: TestJob
 | ||
|     displayName: 'Run Tests'
 | ||
|     strategy:
 | ||
|       matrix:
 | ||
|         minimal:
 | ||
|           preset: minimal
 | ||
|         default:
 | ||
|           preset: default
 | ||
|         performance:
 | ||
|           preset: performance
 | ||
|     steps:
 | ||
|     - task: UsePythonVersion@0
 | ||
|       inputs:
 | ||
|         versionSpec: '3.11'
 | ||
|     - script: |
 | ||
|         pip install ansible ansible-lint
 | ||
|         ansible-galaxy collection install -r requirements.yml
 | ||
|         make role test $(preset)
 | ||
|       displayName: 'Run Molecule Tests'
 | ||
|       env:
 | ||
|         PRESET: $(preset)
 | ||
| 
 | ||
| - stage: Deploy
 | ||
|   displayName: 'Deploy Stage'
 | ||
|   dependsOn: Test
 | ||
|   condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))
 | ||
|   jobs:
 | ||
|   - job: DeployJob
 | ||
|     displayName: 'Check Deployment'
 | ||
|     steps:
 | ||
|     - script: make role deploy
 | ||
|       displayName: 'Check Deployment'
 | ||
|       env:
 | ||
|         ANSIBLE_HOST_KEY_CHECKING: false
 | ||
| ```
 | ||
| 
 | ||
| ### Продвинутая конфигурация
 | ||
| 
 | ||
| **`azure-pipelines-advanced.yml`:**
 | ||
| ```yaml
 | ||
| trigger:
 | ||
| - main
 | ||
| - develop
 | ||
| 
 | ||
| pool:
 | ||
|   vmImage: 'ubuntu-latest'
 | ||
| 
 | ||
| variables:
 | ||
|   ANSIBLE_FORCE_COLOR: 'true'
 | ||
|   DOCKER_TLS_CERTDIR: ''
 | ||
| 
 | ||
| stages:
 | ||
| - stage: Detect
 | ||
|   displayName: 'Detect Roles'
 | ||
|   jobs:
 | ||
|   - job: DetectJob
 | ||
|     displayName: 'Detect New Roles'
 | ||
|     steps:
 | ||
|     - script: |
 | ||
|         echo "##vso[task.setvariable variable=roles;isOutput=true]$(find roles/ -name 'main.yml' -path '*/tasks/*' | sed 's|roles/||; s|/tasks/main.yml||' | tr '\n' ' ')"
 | ||
|       displayName: 'Detect Roles'
 | ||
|       name: detect
 | ||
| 
 | ||
| - stage: Update
 | ||
|   displayName: 'Update Playbooks'
 | ||
|   dependsOn: Detect
 | ||
|   jobs:
 | ||
|   - job: UpdateJob
 | ||
|     displayName: 'Update Playbooks'
 | ||
|     steps:
 | ||
|     - script: |
 | ||
|         chmod +x scripts/update-playbooks.sh
 | ||
|         ./scripts/update-playbooks.sh
 | ||
|       displayName: 'Update Playbooks'
 | ||
|     - script: |
 | ||
|         git config --local user.email "action@azure.com"
 | ||
|         git config --local user.name "Azure DevOps"
 | ||
|         git add molecule/default/run.yml deploy.yml
 | ||
|         git diff --staged --quiet || git commit -m "Auto-update playbooks for new roles"
 | ||
|         git push
 | ||
|       displayName: 'Commit Changes'
 | ||
| 
 | ||
| - stage: Lint
 | ||
|   displayName: 'Lint Stage'
 | ||
|   dependsOn: Update
 | ||
|   jobs:
 | ||
|   - job: LintJob
 | ||
|     displayName: 'Run Lint'
 | ||
|     steps:
 | ||
|     - task: UsePythonVersion@0
 | ||
|       inputs:
 | ||
|         versionSpec: '3.11'
 | ||
|     - script: |
 | ||
|         pip install ansible ansible-lint
 | ||
|         ansible-galaxy collection install -r requirements.yml
 | ||
|         make role lint
 | ||
|       displayName: 'Run Ansible Lint'
 | ||
| 
 | ||
| - stage: Test
 | ||
|   displayName: 'Test Stage'
 | ||
|   dependsOn: [Update, Lint]
 | ||
|   jobs:
 | ||
|   - job: TestJob
 | ||
|     displayName: 'Run Tests'
 | ||
|     strategy:
 | ||
|       matrix:
 | ||
|         minimal:
 | ||
|           preset: minimal
 | ||
|         default:
 | ||
|           preset: default
 | ||
|         performance:
 | ||
|           preset: performance
 | ||
|     steps:
 | ||
|     - task: UsePythonVersion@0
 | ||
|       inputs:
 | ||
|         versionSpec: '3.11'
 | ||
|     - script: |
 | ||
|         pip install ansible ansible-lint
 | ||
|         ansible-galaxy collection install -r requirements.yml
 | ||
|         make role test $(preset)
 | ||
|       displayName: 'Run Molecule Tests'
 | ||
|       env:
 | ||
|         PRESET: $(preset)
 | ||
| 
 | ||
| - stage: Deploy
 | ||
|   displayName: 'Deploy Stage'
 | ||
|   dependsOn: [Lint, Test]
 | ||
|   condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))
 | ||
|   jobs:
 | ||
|   - job: DeployJob
 | ||
|     displayName: 'Check Deployment'
 | ||
|     steps:
 | ||
|     - script: make role deploy
 | ||
|       displayName: 'Check Deployment'
 | ||
|       env:
 | ||
|         ANSIBLE_HOST_KEY_CHECKING: false
 | ||
| 
 | ||
| - stage: Notify
 | ||
|   displayName: 'Notification Stage'
 | ||
|   dependsOn: [Lint, Test, Deploy]
 | ||
|   condition: always()
 | ||
|   jobs:
 | ||
|   - job: NotifyJob
 | ||
|     displayName: 'Send Notifications'
 | ||
|     steps:
 | ||
|     - script: |
 | ||
|         if [ "$(Lint.result)" == "Succeeded" ] && [ "$(Test.result)" == "Succeeded" ]; then
 | ||
|           echo "✅ All tests passed for new roles"
 | ||
|           curl -X POST -H 'Content-type: application/json' \
 | ||
|             --data '{"text":"✅ Ansible role tests passed for new roles"}' \
 | ||
|             $(SLACK_WEBHOOK_URL)
 | ||
|         else
 | ||
|           echo "❌ Tests failed for new roles"
 | ||
|           curl -X POST -H 'Content-type: application/json' \
 | ||
|             --data '{"text":"❌ Ansible role tests failed for new roles"}' \
 | ||
|             $(SLACK_WEBHOOK_URL)
 | ||
|         fi
 | ||
|       displayName: 'Send Notifications'
 | ||
|       env:
 | ||
|         SLACK_WEBHOOK_URL: $(SLACK_WEBHOOK_URL)
 | ||
| ```
 | ||
| 
 | ||
| ## 🏭 Jenkins
 | ||
| 
 | ||
| ### Базовая конфигурация
 | ||
| 
 | ||
| **`Jenkinsfile`:**
 | ||
| ```groovy
 | ||
| pipeline {
 | ||
|     agent any
 | ||
|     
 | ||
|     environment {
 | ||
|         ANSIBLE_FORCE_COLOR = 'true'
 | ||
|         DOCKER_TLS_CERTDIR = ''
 | ||
|     }
 | ||
|     
 | ||
|     stages {
 | ||
|         stage('Checkout') {
 | ||
|             steps {
 | ||
|                 checkout scm
 | ||
|             }
 | ||
|         }
 | ||
|         
 | ||
|         stage('Install Dependencies') {
 | ||
|             steps {
 | ||
|                 sh '''
 | ||
|                     pip install --upgrade pip
 | ||
|                     pip install ansible ansible-lint
 | ||
|                     ansible-galaxy collection install -r requirements.yml
 | ||
|                 '''
 | ||
|             }
 | ||
|         }
 | ||
|         
 | ||
|         stage('Lint') {
 | ||
|             steps {
 | ||
|                 sh 'make role lint'
 | ||
|             }
 | ||
|         }
 | ||
|         
 | ||
|         stage('Test') {
 | ||
|             parallel {
 | ||
|                 stage('Test Minimal') {
 | ||
|                     steps {
 | ||
|                         sh 'make role test minimal'
 | ||
|                     }
 | ||
|                 }
 | ||
|                 stage('Test Default') {
 | ||
|                     steps {
 | ||
|                         sh 'make role test default'
 | ||
|                     }
 | ||
|                 }
 | ||
|                 stage('Test Performance') {
 | ||
|                     steps {
 | ||
|                         sh 'make role test performance'
 | ||
|                     }
 | ||
|                 }
 | ||
|             }
 | ||
|         }
 | ||
|         
 | ||
|         stage('Deploy Check') {
 | ||
|             when {
 | ||
|                 branch 'main'
 | ||
|             }
 | ||
|             steps {
 | ||
|                 sh 'make role deploy'
 | ||
|             }
 | ||
|         }
 | ||
|     }
 | ||
|     
 | ||
|     post {
 | ||
|         always {
 | ||
|             archiveArtifacts artifacts: 'molecule/**/.molecule/**/*', allowEmptyArchive: true
 | ||
|         }
 | ||
|         
 | ||
|         success {
 | ||
|             echo 'Pipeline completed successfully!'
 | ||
|         }
 | ||
|         
 | ||
|         failure {
 | ||
|             echo 'Pipeline failed!'
 | ||
|         }
 | ||
|     }
 | ||
| }
 | ||
| ```
 | ||
| 
 | ||
| ### Продвинутая конфигурация
 | ||
| 
 | ||
| **`Jenkinsfile-advanced`:**
 | ||
| ```groovy
 | ||
| pipeline {
 | ||
|     agent any
 | ||
|     
 | ||
|     environment {
 | ||
|         ANSIBLE_FORCE_COLOR = 'true'
 | ||
|         DOCKER_TLS_CERTDIR = ''
 | ||
|     }
 | ||
|     
 | ||
|     stages {
 | ||
|         stage('Checkout') {
 | ||
|             steps {
 | ||
|                 checkout scm
 | ||
|             }
 | ||
|         }
 | ||
|         
 | ||
|         stage('Detect Roles') {
 | ||
|             steps {
 | ||
|                 script {
 | ||
|                     env.ROLES = sh(
 | ||
|                         script: 'find roles/ -name "main.yml" -path "*/tasks/*" | sed "s|roles/||; s|/tasks/main.yml||" | tr "\\n" " "',
 | ||
|                         returnStdout: true
 | ||
|                     ).trim()
 | ||
|                 }
 | ||
|                 echo "Detected roles: ${env.ROLES}"
 | ||
|             }
 | ||
|         }
 | ||
|         
 | ||
|         stage('Update Playbooks') {
 | ||
|             steps {
 | ||
|                 sh '''
 | ||
|                     chmod +x scripts/update-playbooks.sh
 | ||
|                     ./scripts/update-playbooks.sh
 | ||
|                 '''
 | ||
|                 sh '''
 | ||
|                     git config --local user.email "jenkins@example.com"
 | ||
|                     git config --local user.name "Jenkins"
 | ||
|                     git add molecule/default/run.yml roles/deploy.yml
 | ||
|                     git diff --staged --quiet || git commit -m "Auto-update playbooks for new roles"
 | ||
|                     git push
 | ||
|                 '''
 | ||
|             }
 | ||
|         }
 | ||
|         
 | ||
|         stage('Install Dependencies') {
 | ||
|             steps {
 | ||
|                 sh '''
 | ||
|                     pip install --upgrade pip
 | ||
|                     pip install ansible ansible-lint
 | ||
|                     ansible-galaxy collection install -r requirements.yml
 | ||
|                 '''
 | ||
|             }
 | ||
|         }
 | ||
|         
 | ||
|         stage('Lint') {
 | ||
|             steps {
 | ||
|                 sh 'make role lint'
 | ||
|             }
 | ||
|         }
 | ||
|         
 | ||
|         stage('Test') {
 | ||
|             parallel {
 | ||
|                 stage('Test Minimal') {
 | ||
|                     steps {
 | ||
|                         sh 'make role test minimal'
 | ||
|                     }
 | ||
|                 }
 | ||
|                 stage('Test Default') {
 | ||
|                     steps {
 | ||
|                         sh 'make role test default'
 | ||
|                     }
 | ||
|                 }
 | ||
|                 stage('Test Performance') {
 | ||
|                     steps {
 | ||
|                         sh 'make role test performance'
 | ||
|                     }
 | ||
|                 }
 | ||
|             }
 | ||
|         }
 | ||
|         
 | ||
|         stage('Deploy Check') {
 | ||
|             when {
 | ||
|                 branch 'main'
 | ||
|             }
 | ||
|             steps {
 | ||
|                 sh 'make role deploy'
 | ||
|             }
 | ||
|         }
 | ||
|     }
 | ||
|     
 | ||
|     post {
 | ||
|         always {
 | ||
|             archiveArtifacts artifacts: 'molecule/**/.molecule/**/*', allowEmptyArchive: true
 | ||
|         }
 | ||
|         
 | ||
|         success {
 | ||
|             echo 'Pipeline completed successfully!'
 | ||
|             script {
 | ||
|                 if (env.SLACK_WEBHOOK_URL) {
 | ||
|                     sh '''
 | ||
|                         curl -X POST -H 'Content-type: application/json' \
 | ||
|                           --data '{"text":"✅ Ansible role tests passed for new roles"}' \
 | ||
|                           ${SLACK_WEBHOOK_URL}
 | ||
|                     '''
 | ||
|                 }
 | ||
|             }
 | ||
|         }
 | ||
|         
 | ||
|         failure {
 | ||
|             echo 'Pipeline failed!'
 | ||
|             script {
 | ||
|                 if (env.SLACK_WEBHOOK_URL) {
 | ||
|                     sh '''
 | ||
|                         curl -X POST -H 'Content-type: application/json' \
 | ||
|                           --data '{"text":"❌ Ansible role tests failed for new roles"}' \
 | ||
|                           ${SLACK_WEBHOOK_URL}
 | ||
|                     '''
 | ||
|                 }
 | ||
|             }
 | ||
|         }
 | ||
|     }
 | ||
| }
 | ||
| ```
 | ||
| 
 | ||
| ## 🦊 GitLab CI
 | ||
| 
 | ||
| ### Базовая конфигурация
 | ||
| 
 | ||
| **`.gitlab-ci.yml`:**
 | ||
| ```yaml
 | ||
| stages:
 | ||
|   - lint
 | ||
|   - test
 | ||
|   - deploy
 | ||
| 
 | ||
| variables:
 | ||
|   ANSIBLE_FORCE_COLOR: "true"
 | ||
|   DOCKER_TLS_CERTDIR: ""
 | ||
| 
 | ||
| lint:
 | ||
|   stage: lint
 | ||
|   image: python:3.11
 | ||
|   before_script:
 | ||
|     - pip install ansible ansible-lint
 | ||
|     - ansible-galaxy collection install -r requirements.yml
 | ||
|   script:
 | ||
|     - make role lint
 | ||
| 
 | ||
| test:
 | ||
|   stage: test
 | ||
|   image: docker:latest
 | ||
|   services:
 | ||
|     - docker:dind
 | ||
|   variables:
 | ||
|     DOCKER_TLS_CERTDIR: ""
 | ||
|   before_script:
 | ||
|     - apk add --no-cache make python3 py3-pip
 | ||
|     - pip install ansible ansible-lint
 | ||
|     - ansible-galaxy collection install -r requirements.yml
 | ||
|   script:
 | ||
|     - make role test $PRESET
 | ||
|   parallel:
 | ||
|     matrix:
 | ||
|       - PRESET: [minimal, default, performance]
 | ||
| 
 | ||
| deploy:
 | ||
|   stage: deploy
 | ||
|   image: python:3.11
 | ||
|   only:
 | ||
|     - main
 | ||
|   before_script:
 | ||
|     - pip install ansible ansible-lint
 | ||
|     - ansible-galaxy collection install -r requirements.yml
 | ||
|   script:
 | ||
|     - make role deploy
 | ||
|   variables:
 | ||
|     ANSIBLE_HOST_KEY_CHECKING: "false"
 | ||
| ```
 | ||
| 
 | ||
| ### Продвинутая конфигурация
 | ||
| 
 | ||
| **`.gitlab-ci-advanced.yml`:**
 | ||
| ```yaml
 | ||
| stages:
 | ||
|   - detect
 | ||
|   - update
 | ||
|   - lint
 | ||
|   - test
 | ||
|   - deploy
 | ||
|   - notify
 | ||
| 
 | ||
| variables:
 | ||
|   ANSIBLE_FORCE_COLOR: "true"
 | ||
|   DOCKER_TLS_CERTDIR: ""
 | ||
| 
 | ||
| detect-roles:
 | ||
|   stage: detect
 | ||
|   image: alpine:latest
 | ||
|   script:
 | ||
|     - echo "ROLES=$(find roles/ -name 'main.yml' -path '*/tasks/*' | sed 's|roles/||; s|/tasks/main.yml||' | tr '\n' ' ')" >> build.env
 | ||
|   artifacts:
 | ||
|     reports:
 | ||
|       dotenv: build.env
 | ||
| 
 | ||
| update-playbooks:
 | ||
|   stage: update
 | ||
|   image: alpine:latest
 | ||
|   script:
 | ||
|     - apk add --no-cache make bash
 | ||
|     - chmod +x scripts/update-playbooks.sh
 | ||
|     - ./scripts/update-playbooks.sh
 | ||
|     - git config --local user.email "gitlab@example.com"
 | ||
|     - git config --local user.name "GitLab CI"
 | ||
|     - git add molecule/default/run.yml deploy.yml
 | ||
|     - git diff --staged --quiet || git commit -m "Auto-update playbooks for new roles"
 | ||
|     - git push
 | ||
|   only:
 | ||
|     - main
 | ||
|     - develop
 | ||
| 
 | ||
| lint:
 | ||
|   stage: lint
 | ||
|   image: python:3.11
 | ||
|   before_script:
 | ||
|     - pip install ansible ansible-lint
 | ||
|     - ansible-galaxy collection install -r requirements.yml
 | ||
|   script:
 | ||
|     - make role lint
 | ||
| 
 | ||
| test:
 | ||
|   stage: test
 | ||
|   image: docker:latest
 | ||
|   services:
 | ||
|     - docker:dind
 | ||
|   variables:
 | ||
|     DOCKER_TLS_CERTDIR: ""
 | ||
|   before_script:
 | ||
|     - apk add --no-cache make python3 py3-pip
 | ||
|     - pip install ansible ansible-lint
 | ||
|     - ansible-galaxy collection install -r requirements.yml
 | ||
|   script:
 | ||
|     - make role test $PRESET
 | ||
|   parallel:
 | ||
|     matrix:
 | ||
|       - PRESET: [minimal, default, performance]
 | ||
| 
 | ||
| deploy:
 | ||
|   stage: deploy
 | ||
|   image: python:3.11
 | ||
|   only:
 | ||
|     - main
 | ||
|   before_script:
 | ||
|     - pip install ansible ansible-lint
 | ||
|     - ansible-galaxy collection install -r requirements.yml
 | ||
|   script:
 | ||
|     - make role deploy
 | ||
|   variables:
 | ||
|     ANSIBLE_HOST_KEY_CHECKING: "false"
 | ||
| 
 | ||
| notify:
 | ||
|   stage: notify
 | ||
|   image: alpine:latest
 | ||
|   script:
 | ||
|     - |
 | ||
|       if [ "$CI_JOB_STATUS" == "success" ]; then
 | ||
|         echo "✅ All tests passed for new roles"
 | ||
|         curl -X POST -H 'Content-type: application/json' \
 | ||
|           --data '{"text":"✅ Ansible role tests passed for new roles"}' \
 | ||
|           ${SLACK_WEBHOOK_URL}
 | ||
|       else
 | ||
|         echo "❌ Tests failed for new roles"
 | ||
|         curl -X POST -H 'Content-type: application/json' \
 | ||
|           --data '{"text":"❌ Ansible role tests failed for new roles"}' \
 | ||
|           ${SLACK_WEBHOOK_URL}
 | ||
|       fi
 | ||
|   when: always
 | ||
|   variables:
 | ||
|     SLACK_WEBHOOK_URL: $SLACK_WEBHOOK_URL
 | ||
| ```
 | ||
| 
 | ||
| ## 🔔 Настройка уведомлений
 | ||
| 
 | ||
| ### Slack уведомления
 | ||
| 
 | ||
| ```yaml
 | ||
| # .github/workflows/notifications.yml
 | ||
| name: Notifications
 | ||
| on: [workflow_run]
 | ||
| 
 | ||
| jobs:
 | ||
|   notify:
 | ||
|     runs-on: ubuntu-latest
 | ||
|     if: always()
 | ||
|     steps:
 | ||
|       - name: Notify Slack
 | ||
|         uses: 8398a7/action-slack@v3
 | ||
|         with:
 | ||
|           status: ${{ job.status }}
 | ||
|           channel: '#ansible'
 | ||
|           webhook_url: ${{ secrets.SLACK_WEBHOOK_URL }}
 | ||
| ```
 | ||
| 
 | ||
| ### Teams уведомления
 | ||
| 
 | ||
| ```yaml
 | ||
| # .github/workflows/teams-notifications.yml
 | ||
| name: Teams Notifications
 | ||
| on: [workflow_run]
 | ||
| 
 | ||
| jobs:
 | ||
|   notify:
 | ||
|     runs-on: ubuntu-latest
 | ||
|     if: always()
 | ||
|     steps:
 | ||
|       - name: Notify Teams
 | ||
|         uses: skitionek/notify-microsoft-teams@master
 | ||
|         with:
 | ||
|           webhook_url: ${{ secrets.TEAMS_WEBHOOK_URL }}
 | ||
|           status: ${{ job.status }}
 | ||
|           title: 'Ansible Role Tests'
 | ||
| ```
 | ||
| 
 | ||
| ## 📊 Мониторинг CI/CD
 | ||
| 
 | ||
| ### Метрики производительности
 | ||
| 
 | ||
| ```yaml
 | ||
| # .github/workflows/metrics.yml
 | ||
| name: CI/CD Metrics
 | ||
| on: [workflow_run]
 | ||
| 
 | ||
| jobs:
 | ||
|   metrics:
 | ||
|     runs-on: ubuntu-latest
 | ||
|     steps:
 | ||
|       - name: Collect Metrics
 | ||
|         run: |
 | ||
|           echo "Build time: $(date)"
 | ||
|           echo "Commit: ${{ github.sha }}"
 | ||
|           echo "Branch: ${{ github.ref }}"
 | ||
|           echo "Actor: ${{ github.actor }}"
 | ||
| ```
 | ||
| 
 | ||
| ### Отчеты о тестировании
 | ||
| 
 | ||
| ```yaml
 | ||
| # .github/workflows/reports.yml
 | ||
| name: Test Reports
 | ||
| on: [workflow_run]
 | ||
| 
 | ||
| jobs:
 | ||
|   reports:
 | ||
|     runs-on: ubuntu-latest
 | ||
|     steps:
 | ||
|       - name: Generate Report
 | ||
|         run: |
 | ||
|           echo "## Test Results" >> $GITHUB_STEP_SUMMARY
 | ||
|           echo "- Lint: ✅ Passed" >> $GITHUB_STEP_SUMMARY
 | ||
|           echo "- Test: ✅ Passed" >> $GITHUB_STEP_SUMMARY
 | ||
|           echo "- Deploy: ✅ Passed" >> $GITHUB_STEP_SUMMARY
 | ||
| ```
 | ||
| 
 | ||
| ## 🔧 Настройка секретов
 | ||
| 
 | ||
| ### GitHub Secrets
 | ||
| 
 | ||
| ```bash
 | ||
| # Настройка секретов в GitHub
 | ||
| gh secret set SLACK_WEBHOOK_URL --body "https://hooks.slack.com/services/..."
 | ||
| gh secret set TEAMS_WEBHOOK_URL --body "https://outlook.office.com/webhook/..."
 | ||
| ```
 | ||
| 
 | ||
| ### Azure DevOps Variables
 | ||
| 
 | ||
| ```yaml
 | ||
| # azure-pipelines.yml
 | ||
| variables:
 | ||
|   - group: ansible-secrets
 | ||
|   - name: SLACK_WEBHOOK_URL
 | ||
|     value: $(SLACK_WEBHOOK_URL)
 | ||
| ```
 | ||
| 
 | ||
| ### Jenkins Credentials
 | ||
| 
 | ||
| ```groovy
 | ||
| // Jenkinsfile
 | ||
| pipeline {
 | ||
|     agent any
 | ||
|     environment {
 | ||
|         SLACK_WEBHOOK_URL = credentials('slack-webhook-url')
 | ||
|     }
 | ||
|     // ... остальная конфигурация
 | ||
| }
 | ||
| ```
 | ||
| 
 | ||
| ## 🚀 Автоматизация
 | ||
| 
 | ||
| ### Автоматическое создание скриптов
 | ||
| 
 | ||
| ```bash
 | ||
| #!/bin/bash
 | ||
| # scripts/setup-cicd.sh
 | ||
| # Автоматическая настройка CI/CD
 | ||
| 
 | ||
| echo "🔧 Настройка CI/CD для DevOpsLab..."
 | ||
| 
 | ||
| # Создание директории .github/workflows
 | ||
| mkdir -p .github/workflows
 | ||
| 
 | ||
| # Создание базового workflow
 | ||
| cat > .github/workflows/ansible-test.yml << 'EOF'
 | ||
| name: Ansible Testing
 | ||
| on: [push, pull_request]
 | ||
| 
 | ||
| jobs:
 | ||
|   test:
 | ||
|     runs-on: ubuntu-latest
 | ||
|     steps:
 | ||
|       - uses: actions/checkout@v4
 | ||
|       - name: Run tests
 | ||
|         run: make role test
 | ||
| EOF
 | ||
| 
 | ||
| # Создание Azure DevOps pipeline
 | ||
| cat > azure-pipelines.yml << 'EOF'
 | ||
| trigger:
 | ||
| - main
 | ||
| pool:
 | ||
|   vmImage: 'ubuntu-latest'
 | ||
| stages:
 | ||
| - stage: Test
 | ||
|   jobs:
 | ||
|   - job: TestJob
 | ||
|     steps:
 | ||
|     - script: make role test
 | ||
| EOF
 | ||
| 
 | ||
| # Создание Jenkinsfile
 | ||
| cat > Jenkinsfile << 'EOF'
 | ||
| pipeline {
 | ||
|     agent any
 | ||
|     stages {
 | ||
|         stage('Test') {
 | ||
|             steps {
 | ||
|                 sh 'make role test'
 | ||
|             }
 | ||
|         }
 | ||
|     }
 | ||
| }
 | ||
| EOF
 | ||
| 
 | ||
| # Создание GitLab CI
 | ||
| cat > .gitlab-ci.yml << 'EOF'
 | ||
| stages:
 | ||
|   - test
 | ||
| test:
 | ||
|   stage: test
 | ||
|   script:
 | ||
|     - make role test
 | ||
| EOF
 | ||
| 
 | ||
| echo "✅ CI/CD настроен"
 | ||
| ```
 | ||
| 
 | ||
| ---
 | ||
| 
 | ||
| **Автор:** Сергей Антропов  
 | ||
| **Сайт:** https://devops.org.ru
 |