Agent: "Stwórz workflow GitHub Actions z:
- Matrix builds dla wielu wersji
- Skanowaniem bezpieczeństwa
- Wdrożeniem na staging/production
# .github/workflows/main.yml
branches: [main, develop]
IMAGE_NAME: ${{ github.repository }}
# Jakość kodu i bezpieczeństwo
name: Sprawdzanie jakości kodu
uses: actions/checkout@v4
fetch-depth: 0 # Pełna historia dla lepszej analizy
- name: Konfiguracja Node.js
uses: actions/setup-node@v4
node-version: ${{ env.NODE_VERSION }}
- name: Instalacja zależności
- name: Uruchomienie lintingu
- name: Sprawdzanie typów
- name: Sprawdzanie formatowania kodu
run: npm run format:check
- name: Audit bezpieczeństwa
run: npm audit --audit-level=moderate
- name: Skanowanie SonarCloud
uses: SonarSource/sonarcloud-github-action@master
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
node-version: [18.x, 20.x, 22.x]
test-suite: [unit, integration, e2e]
POSTGRES_PASSWORD: postgres
--health-cmd "redis-cli ping"
uses: actions/checkout@v4
- name: Konfiguracja Node.js
uses: actions/setup-node@v4
node-version: ${{ matrix.node-version }}
- name: Instalacja zależności
- name: Uruchomienie migracji
DATABASE_URL: postgresql://postgres:postgres@localhost:5432/test_db
- name: Uruchomienie testów ${{ matrix.test-suite }}
run: npm run test:${{ matrix.test-suite }}
DATABASE_URL: postgresql://postgres:postgres@localhost:5432/test_db
REDIS_URL: redis://localhost:6379
if: matrix.test-suite == 'unit' && matrix.node-version == '20.x'
uses: codecov/codecov-action@v4
file: ./coverage/lcov.info
# Build i push obrazu Docker
name: Build obrazu Docker
image: ${{ steps.image.outputs.image }}
digest: ${{ steps.build.outputs.digest }}
uses: actions/checkout@v4
- name: Konfiguracja Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Logowanie do registry
uses: docker/login-action@v3
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Wyciąganie metadanych
uses: docker/metadata-action@v5
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}
- name: Build i push obrazu Docker
uses: docker/build-push-action@v5
platforms: linux/amd64,linux/arm64
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-to: type=gha,mode=max
VERSION=${{ github.sha }}
BUILD_DATE=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
uses: anchore/sbom-action@v0
image: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ steps.build.outputs.digest }}
output-file: sbom.spdx.json
- name: Uruchomienie skanera Trivy
uses: aquasecurity/trivy-action@master
image-ref: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ steps.build.outputs.digest }}
output: 'trivy-results.sarif'
severity: 'CRITICAL,HIGH'
- name: Upload wyników Trivy
uses: github/codeql-action/upload-sarif@v3
sarif_file: 'trivy-results.sarif'
run: echo "image=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ steps.build.outputs.digest }}" >> $GITHUB_OUTPUT
name: Wdrożenie na staging
if: github.ref == 'refs/heads/develop'
uses: actions/checkout@v4
- name: Konfiguracja credentials AWS
uses: aws-actions/configure-aws-credentials@v4
role-to-assume: ${{ secrets.AWS_ROLE_ARN }}
- name: Aktualizacja kubeconfig
aws eks update-kubeconfig --name staging-cluster --region us-east-1
- name: Wdrożenie na Kubernetes
kubectl set image deployment/app app=${{ needs.build.outputs.image }} -n staging
kubectl rollout status deployment/app -n staging
- name: Uruchomienie smoke testów
./scripts/smoke-test.sh https://staging.example.com
- name: Powiadomienie Slack
uses: 8398a7/action-slack@v3
status: ${{ job.status }}
webhook_url: ${{ secrets.SLACK_WEBHOOK }}
text: 'Wdrożenie staging ${{ job.status }}'
name: Wdrożenie na produkcję
needs: [build, deploy-staging]
if: github.event_name == 'release'
uses: actions/checkout@v4
- name: Konfiguracja credentials AWS
uses: aws-actions/configure-aws-credentials@v4
role-to-assume: ${{ secrets.AWS_PROD_ROLE_ARN }}
- name: Aktualizacja kubeconfig
aws eks update-kubeconfig --name production-cluster --region us-east-1
- name: Utworzenie rekordu wdrożenia
uses: actions/github-script@v7
const deployment = await github.rest.repos.createDeployment({
owner: context.repo.owner,
environment: 'production',
production_environment: true,
return deployment.data.id;
- name: Wdrożenie Blue-Green
# Wdrożenie na środowisko green
kubectl set image deployment/app-green app=${{ needs.build.outputs.image }} -n production
kubectl rollout status deployment/app-green -n production
# Uruchomienie health checks
./scripts/health-check.sh https://green.example.com
kubectl patch service app-service -n production -p '{"spec":{"selector":{"version":"green"}}}'
# Oczekiwanie i weryfikacja
./scripts/verify-deployment.sh https://example.com
- name: Aktualizacja statusu wdrożenia
uses: actions/github-script@v7
await github.rest.repos.createDeploymentStatus({
owner: context.repo.owner,
deployment_id: ${{ steps.deployment.outputs.result }},
state: '${{ job.status }}',
environment_url: 'https://example.com'
- name: Utworzenie notatek release
uses: actions/github-script@v7
const release = await github.rest.repos.getReleaseByTag({
owner: context.repo.owner,
tag: context.ref.replace('refs/tags/', '')
const newBody = release.data.body + '\n\n## Wdrożenie\n' +
`- Obraz: \`${{ needs.build.outputs.image }}\`\n` +
`- Wdrożono: ${new Date().toISOString()}\n` +
`- Wdrożył: @${context.actor}`;
await github.rest.repos.updateRelease({
owner: context.repo.owner,
release_id: release.data.id,