Some checks failed
Ansible Testing / lint (push) Has been cancelled
Ansible Testing / test (default) (push) Has been cancelled
Ansible Testing / test (minimal) (push) Has been cancelled
Ansible Testing / test (performance) (push) Has been cancelled
Ansible Testing / deploy-check (push) Has been cancelled
22 KiB
22 KiB
Настройка CI/CD для DevOpsLab
Автор: Сергей Антропов
Сайт: https://devops.org.ru
🚀 GitHub Actions
Базовая конфигурация
.github/workflows/ansible-test.yml:
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:
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/site.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:
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:
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/site.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:
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:
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/site.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:
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:
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/site.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 уведомления
# .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 уведомления
# .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
Метрики производительности
# .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 }}"
Отчеты о тестировании
# .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
# Настройка секретов в 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
# azure-pipelines.yml
variables:
- group: ansible-secrets
- name: SLACK_WEBHOOK_URL
value: $(SLACK_WEBHOOK_URL)
Jenkins Credentials
// Jenkinsfile
pipeline {
agent any
environment {
SLACK_WEBHOOK_URL = credentials('slack-webhook-url')
}
// ... остальная конфигурация
}
🚀 Автоматизация
Автоматическое создание скриптов
#!/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