name: CI/CD Pipeline on: push: branches: [ main, develop ] pull_request: branches: [ main ] jobs: lint: name: Lint Ansible Playbooks runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@v4 with: python-version: '3.11' - name: Install dependencies run: | python -m pip install --upgrade pip pip install ansible ansible-lint yamllint - name: Lint YAML files run: | yamllint . continue-on-error: true - name: Lint Ansible playbooks run: | ansible-lint playbooks/*.yml continue-on-error: true - name: Validate Ansible syntax run: | for playbook in playbooks/*.yml; do ansible-playbook --syntax-check "$playbook" done test-ubuntu: name: Test on Ubuntu runs-on: ubuntu-latest needs: lint strategy: matrix: ubuntu_version: ['20.04', '22.04', '24.04'] steps: - name: Checkout code uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@v4 with: python-version: '3.11' - name: Install Ansible run: | python -m pip install --upgrade pip pip install ansible - name: Set up Docker uses: docker/setup-buildx-action@v3 - name: Create test inventory run: | mkdir -p test-inventory cat > test-inventory/hosts <> /etc/sudoers CMD ["/sbin/init"] EOF - name: Run test container run: | docker run -d --name test-server \ --privileged \ --tmpfs /tmp \ --tmpfs /run \ --tmpfs /run/lock \ -v /sys/fs/cgroup:/sys/fs/cgroup:ro \ test-ubuntu:${{ matrix.ubuntu_version }} - name: Test base LEMP installation run: | ansible-playbook -i test-inventory/hosts \ playbooks/lemp-wordpress.yml \ --extra-vars "mysql_root_password=test123 wordpress_db_password=test123 wp_admin_password=test123" \ -v - name: Test WordPress installation run: | ansible-playbook -i test-inventory/hosts \ playbooks/install-wordpress-official.yml \ --extra-vars "wp_admin_password=test123" \ -v - name: Verify installation run: | # Test if services are running docker exec test-server systemctl is-active nginx docker exec test-server systemctl is-active mysql docker exec test-server systemctl is-active php8.3-fpm || docker exec test-server systemctl is-active php8.1-fpm # Test if WordPress is accessible docker exec test-server curl -f http://localhost/ || true - name: Cleanup if: always() run: | docker stop test-server || true docker rm test-server || true test-centos: name: Test on CentOS Stream runs-on: ubuntu-latest needs: lint steps: - name: Checkout code uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@v4 with: python-version: '3.11' - name: Install Ansible run: | python -m pip install --upgrade pip pip install ansible - name: Set up Docker uses: docker/setup-buildx-action@v3 - name: Create test inventory run: | mkdir -p test-inventory cat > test-inventory/hosts <> /etc/sudoers CMD ["/sbin/init"] EOF - name: Run CentOS test container run: | docker run -d --name test-centos \ --privileged \ --tmpfs /tmp \ --tmpfs /run \ --tmpfs /run/lock \ -v /sys/fs/cgroup:/sys/fs/cgroup:ro \ test-centos:stream9 - name: Test LEMP installation on CentOS run: | ansible-playbook -i test-inventory/hosts \ playbooks/lemp-wordpress-multios.yml \ --extra-vars "mysql_root_password=test123 wordpress_db_password=test123 wp_admin_password=test123" \ -v continue-on-error: true - name: Cleanup CentOS if: always() run: | docker stop test-centos || true docker rm test-centos || true security-scan: name: Security Scanning runs-on: ubuntu-latest needs: lint steps: - name: Checkout code uses: actions/checkout@v4 - name: Run Trivy vulnerability scanner uses: aquasecurity/trivy-action@master with: scan-type: 'fs' scan-ref: '.' format: 'sarif' output: 'trivy-results.sarif' - name: Upload Trivy scan results to GitHub Security tab uses: github/codeql-action/upload-sarif@v2 if: always() with: sarif_file: 'trivy-results.sarif' release: name: Create Release runs-on: ubuntu-latest needs: [test-ubuntu, test-centos, security-scan] if: github.ref == 'refs/heads/main' && github.event_name == 'push' steps: - name: Checkout code uses: actions/checkout@v4 with: fetch-depth: 0 - name: Get latest tag id: get_tag run: | latest_tag=$(git describe --tags --abbrev=0 2>/dev/null || echo "v0.0.0") echo "latest_tag=$latest_tag" >> $GITHUB_OUTPUT - name: Generate changelog run: | echo "# Changelog" > CHANGELOG_RELEASE.md echo "" >> CHANGELOG_RELEASE.md git log ${{ steps.get_tag.outputs.latest_tag }}..HEAD --pretty=format:"- %s (%h)" >> CHANGELOG_RELEASE.md - name: Create Release uses: actions/create-release@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: tag_name: v${{ github.run_number }} release_name: Release v${{ github.run_number }} body_path: CHANGELOG_RELEASE.md draft: false prerelease: false