Перейти к основному контенту
Tech Path Finder
КурсыИнтервьюКод-ревьюБлог
Tech Path Finder

Персонализированный путеводитель в IT. Квизы, мок-интервью, код ревью и аналитика прогресса.

@potapov_me

Платформа

  • Курсы
  • Прогресс
  • Мок-интервью
  • Код ревью
  • Живое ревью с ИИ
  • Тренажёр переговоров
  • Закладки

Контент

  • Блог
  • Главная
  • Обратная связь

Компания

  • О проекте
  • Тарифы
  • Условия использования
  • Конфиденциальность
  • Согласие на обработку данных
  • Cookie
  • Реквизиты

Аккаунт

  • Войти
  • Зарегистрироваться
  • Профиль

© 2026 Tech Path Finder. Все права защищены.

·ИП Потапов К.С.·Политика конфиденциальности·
Сделано с ❤️ в России
  1. Интеграции
integrations

Интеграции

Интеграция с Jira, Sentry, SonarQube и другими инструментами.

Интеграции

Интеграция CI/CD с инструментами разработки создаёт единую экосистему для отслеживания кода от commit до production. Изучите интеграцию с Jira, Sentry, SonarQube и другими системами.

#Jira Integration

#Автоматическая связь деплоя с задачами

Jira автоматически связывает деплои с задачами по ключу задачи (например, PROJ-123).

Источники ключа задачи:

  • Commit message: feat: implement login (PROJ-123)
  • Branch name: feature/PROJ-123-add-login
  • Pipeline variables: JIRA_ISSUE=PROJ-123
name: Deploy with Jira Integration on: push: branches: [main] jobs: deploy: runs-on: ubuntu-latest environment: production steps: - uses: actions/checkout@v4 with: fetch-depth: 0 # Full history for commit parsing - name: Extract Jira Issue id: jira run: | # Extract from branch name ISSUE=$(echo "${{ github.ref_name }}" | grep -oE '[A-Z]+-[0-9]+' | head -1) # Fallback: extract from commit message if [ -z "$ISSUE" ]; then ISSUE=$(git log -1 --pretty=%B | grep -oE '[A-Z]+-[0-9]+' | head -1) fi echo "issue=$ISSUE" >> $GITHUB_OUTPUT echo "Found Jira issue: $ISSUE" - name: Deploy run: ./deploy.sh env: JIRA_ISSUE: ${{ steps.jira.outputs.issue }} - name: Update Jira Status if: success() && steps.jira.outputs.issue != '' run: | # Transition issue to "Done" status curl -X POST "https://api.atlassian.com/ex/jira/${JIRA_CLOUD_ID}/rest/api/3/issue/${JIRA_ISSUE}/transitions" \ -H "Authorization: Bearer $JIRA_API_TOKEN" \ -H "Content-Type: application/json" \ -d "{ \"transition\": {\"id\": \"31\"} }" # Add comment with deploy info curl -X POST "https://api.atlassian.com/ex/jira/${JIRA_CLOUD_ID}/rest/api/3/issue/${JIRA_ISSUE}/comment" \ -H "Authorization: Bearer $JIRA_API_TOKEN" \ -H "Content-Type: application/json" \ -d "{ \"body\": { \"type\": \"doc\", \"version\": 1, \"content\": [ { \"type\": \"paragraph\", \"content\": [ {\"type\": \"text\", \"text\": \"✅ Deployed to production\"}, {\"type\": \"text\", \"text\": \"\\nCommit: \"}, {\"type\": \"text\", \"text\": \"${{ github.sha }}\", \"marks\": [{\"type\": \"code\"}]}, {\"type\": \"text\", \"text\": \"\\nWorkflow: \"}, {\"type\": \"hyperlink\", \"text\": \"View\", \"attrs\": {\"url\": \"${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}\"}} ] } ] } }" env: JIRA_CLOUD_ID: ${{ secrets.JIRA_CLOUD_ID }} JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }} JIRA_ISSUE: ${{ steps.jira.outputs.issue }}

#GitLab Jira Integration

GitLab имеет встроенную интеграцию с Jira:

# .gitlab-ci.yml variables: JIRA_TRANSITION_ID: "31" # ID перехода в "Done" deploy_production: stage: deploy environment: production script: - ./deploy.sh after_script: - | if [ -n "$JIRA_ISSUE" ]; then # Update Jira status curl -X POST "https://api.atlassian.com/ex/jira/${JIRA_CLOUD_ID}/rest/api/3/issue/${JIRA_ISSUE}/transitions" \ -H "Authorization: Bearer $JIRA_API_TOKEN" \ -H "Content-Type: application/json" \ -d "{\"transition\": {\"id\": \"$JIRA_TRANSITION_ID\"}}" fi rules: - if: $CI_COMMIT_BRANCH == "main"

#Smart Commits

Jira поддерживает Smart Commits для управления задачами из commit messages:

PROJ-123 #comment Deployed to production #close
PROJ-123 #time 2h #assign john.doe
- name: Process Smart Commits run: | # Extract Smart Commands from commit message COMMIT_MSG=$(git log -1 --pretty=%B) # Extract time tracking if [[ $COMMIT_MSG =~ #time[[:space:]]*([0-9]+h)?([0-9]+m)? ]]; then TIME_LOGGED="${BASH_REMATCH[1]}${BASH_REMATCH[2]}" echo "Logging time: $TIME_LOGGED" # Call Jira API to log work fi # Extract close command if [[ $COMMIT_MSG =~ \#close ]]; then echo "Closing issue via Smart Commit" # Transition to Done fi env: JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }}

#Sentry Integration

#Создание Release

Sentry CLI позволяет управлять releases из CI/CD.

name: Deploy with Sentry Release on: push: branches: [main] jobs: deploy: runs-on: ubuntu-latest environment: production steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Set up Sentry CLI uses: getsentry/action-setup-cli@v2 with: auth_token: ${{ secrets.SENTRY_AUTH_TOKEN }} org_slug: my-org project_slug: my-project - name: Create Sentry Release run: | # Generate version from commit VERSION="prod-${GITHUB_SHA:0:7}" # Create new release sentry-cli releases new $VERSION # Associate commits with release sentry-cli releases set-commits $VERSION --auto # Mark deployment start sentry-cli releases deploys $VERSION new -e production - name: Deploy Application run: ./deploy.sh env: SENTRY_RELEASE: ${{ env.SENTRY_RELEASE }} - name: Mark Deploy Complete if: always() run: | VERSION="prod-${GITHUB_SHA:0:7}" if [ "${{ job.status }}" = "success" ]; then sentry-cli releases deploys $VERSION finalize -e production else sentry-cli releases deploys $VERSION new -e production --status failed fi env: SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} ORG_SLUG: my-org PROJECT_SLUG: my-project

#Sentry Configuration в приложении

// Sentry SDK configuration import * as Sentry from "@sentry/node"; Sentry.init({ dsn: process.env.SENTRY_DSN, environment: process.env.NODE_ENV, release: process.env.SENTRY_RELEASE, // Performance monitoring tracesSampleRate: 0.1, // Session replay replaysSessionSampleRate: 0.1, replaysOnErrorSampleRate: 1.0, integrations: [ Sentry.replayIntegration({ maskAllText: true, blockAllMedia: true, }), ], });

#Source Maps Upload

- name: Upload Source Maps run: | sentry-cli sourcemaps inject ./dist sentry-cli sourcemaps upload ./dist \ --release $VERSION \ --dist $GITHUB_SHA env: SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} ORG_SLUG: my-org PROJECT_SLUG: my-project

#Performance Monitoring в Pipeline

- name: Check Sentry Performance run: | # Query Sentry API for error rate after deploy sleep 60 # Wait for data ERROR_RATE=$(curl -s "https://sentry.io/api/0/projects/${ORG_SLUG}/${PROJECT_SLUG}/stats/" \ -H "Authorization: Bearer $SENTRY_AUTH_TOKEN" \ -G --data-urlencode "stat=generated" \ --data-urlencode "interval=1h" \ --data-urlencode "query=is:unresolved" | jq '.[0].data[-1].count') if [ "$ERROR_RATE" -gt 100 ]; then echo "High error rate detected: $ERROR_RATE" exit 1 fi echo "Error rate OK: $ERROR_RATE" env: SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} ORG_SLUG: my-org PROJECT_SLUG: my-project

#SonarQube Integration

#Анализ в GitHub Actions

name: CI with SonarQube on: pull_request: branches: [main] push: branches: [main] jobs: sonarqube: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: fetch-depth: 0 # Shallow clones should be disabled for better blame - name: Set up Node.js uses: actions/setup-node@v4 with: node-version: '20' - name: Install dependencies run: npm ci - name: Run tests with coverage run: npm run test:coverage - name: SonarQube Scan uses: SonarSource/sonarqube-scan-action@v3 env: SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }} with: args: > -Dsonar.projectKey=my-project -Dsonar.projectName=My Project -Dsonar.sources=src -Dsonar.tests=tests -Dsonar.javascript.lcov.reportPaths=coverage/lcov.info -Dsonar.coverage.exclusions=**/*.test.ts,**/*.spec.ts - name: Check Quality Gate id: quality-gate run: | # Wait for analysis to complete sleep 30 # Get Quality Gate status RESPONSE=$(curl -s "$SONAR_HOST_URL/api/qualitygates/project_status?projectKey=my-project" \ -u $SONAR_TOKEN:) STATUS=$(echo $RESPONSE | jq -r '.projectStatus.status') CONDITIONS=$(echo $RESPONSE | jq -r '.projectStatus.conditions[] | select(.status == "ERROR")') echo "Quality Gate Status: $STATUS" if [ "$STATUS" != "OK" ]; then echo "Quality Gate failed:" echo "$CONDITIONS" | jq '.' exit 1 fi echo "Quality Gate passed!" env: SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }} SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}

#Quality Gate Conditions

Примеры условий Quality Gate в SonarQube:

ConditionOperatorThreshold
Coverage on New Codeis less than80%
Bugs on New Codeis greater than0
Vulnerabilities on New Codeis greater than0
Code Smells on New Codeis greater than5
Technical Debt Ratiois greater than5%
Duplicated Linesis greater than3%

#Multi-Project Analysis (Monorepo)

name: SonarQube Monorepo Scan on: push jobs: scan-services: runs-on: ubuntu-latest strategy: matrix: service: [api, frontend, worker] steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Scan ${{ matrix.service }} uses: SonarSource/sonarqube-scan-action@v3 env: SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }} with: args: > -Dsonar.projectKey=monorepo-${{ matrix.service }} -Dsonar.projectName=${{ matrix.service }} -Dsonar.sources=services/${{ matrix.service }}/src -Dsonar.tests=services/${{ matrix.service }}/tests -Dsonar.javascript.lcov.reportPaths=services/${{ matrix.service }}/coverage/lcov.info - name: Check Quality Gate for ${{ matrix.service }} run: | RESPONSE=$(curl -s "$SONAR_HOST_URL/api/qualitygates/project_status?projectKey=monorepo-${{ matrix.service }}" \ -u $SONAR_TOKEN:) STATUS=$(echo $RESPONSE | jq -r '.projectStatus.status') if [ "$STATUS" != "OK" ]; then echo "Quality Gate failed for ${{ matrix.service }}" exit 1 fi env: SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }} SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}

#Branch Analysis

- name: SonarQube Branch Analysis uses: SonarSource/sonarqube-scan-action@v3 env: SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }} with: args: > -Dsonar.projectKey=my-project -Dsonar.branch.name=${{ github.ref_name }} -Dsonar.branch.target=main

#Additional Integrations

#Datadog Integration

- name: Send Deploy Event to Datadog run: | curl -X POST "https://api.datadoghq.com/api/v1/events" \ -H "DD-API-KEY: $DD_API_KEY" \ -H "Content-Type: application/json" \ -d "{ \"title\": \"Deploy to production\", \"text\": \"${{ github.repository }} deployed ${{ github.sha }}\", \"priority\": \"normal\", \"host\": \"github-actions\", \"tags\": [ \"env:production\", \"service:${{ github.repository }}\", \"commit:${{ github.sha }}\", \"deployer:${{ github.actor }}\" ], \"alert_type\": \"success\" }" env: DD_API_KEY: ${{ secrets.DATADOG_API_KEY }}

#New Relic Deployment Marker

- name: Mark Deployment in New Relic run: | curl -X POST "https://api.newrelic.com/v2/applications/${NEW_RELIC_APP_ID}/deployments.json" \ -H "X-Api-Key: $NEW_RELIC_API_KEY" \ -H "Content-Type: application/json" \ -d "{ \"deployment\": { \"revision\": \"${{ github.sha }}\", \"changelog\": \"Deployed via GitHub Actions\", \"description\": \"Production deployment\", \"user\": \"${{ github.actor }}\" } }" env: NEW_RELIC_API_KEY: ${{ secrets.NEW_RELIC_API_KEY }} NEW_RELIC_APP_ID: ${{ secrets.NEW_RELIC_APP_ID }}

#LaunchDarkly Feature Flags

- name: Update LaunchDarkly Feature Flags run: | # Enable feature flag for new release curl -X PATCH "https://app.launchdarkly.com/api/v2/flags/${LD_PROJECT_KEY}/${LD_FLAG_KEY}" \ -H "Authorization: $LD_API_KEY" \ -H "Content-Type: application/json" \ -d "{ \"patch\": [{ \"op\": \"replace\", \"path\": \"/environments/production/on\", \"value\": true }] }" env: LD_API_KEY: ${{ secrets.LAUNCHDARKLY_API_KEY }} LD_PROJECT_KEY: my-project LD_FLAG_KEY: new-feature

#Slack + Jira Combined

- name: Notify Slack with Jira Link if: always() run: | STATUS="${{ job.status }}" COLOR=$([ "$STATUS" = "success" ] && echo "good" || echo "danger") EMOJI=$([ "$STATUS" = "success" ] && echo "✅" || echo "❌") # Build Jira link if issue exists JIRA_LINK="" if [ -n "$JIRA_ISSUE" ]; then JIRA_LINK=" | <https://company.atlassian.net/browse/$JIRA_ISSUE|Jira: $JIRA_ISSUE>" fi curl -X POST $SLACK_WEBHOOK \ -H "Content-Type: application/json" \ -d "{ \"attachments\": [{ \"color\": \"$COLOR\", \"title\": \"$EMOJI Deploy $STATUS$JIRA_LINK\", \"fields\": [ {\"title\": \"Repository\", \"value\": \"${{ github.repository }}\", \"short\": true}, {\"title\": \"Commit\", \"value\": \"\`${{ github.sha }}\`\", \"short\": true} ], \"actions\": [{ \"type\": \"button\", \"text\": \"View Workflow\", \"url\": \"${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}\" }] }] }" env: SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }} JIRA_ISSUE: ${{ steps.jira.outputs.issue }}

#Best Practices

#1. Хранение секретов

# Правильно: использовать secrets env: SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }} # Неправильно: хардкод env: SONAR_TOKEN: sqp_abc123 # ❌ Никогда не делайте так

#2. Обработка ошибок интеграции

- name: Jira Update with Error Handling run: | curl -X POST "$JIRA_API_URL" \ -H "Authorization: Bearer $JIRA_TOKEN" \ --max-time 30 \ --retry 3 \ --retry-delay 5 || echo "Jira update failed, continuing..."

#3. Rate Limiting

- name: Respect API Rate Limits run: | # Add delay between API calls sleep 1 # Check rate limit headers REMAINING=$(curl -sI "$JIRA_API_URL" | grep -i "X-RateLimit-Remaining" | cut -d' ' -f2) if [ "$REMAINING" -lt 10 ]; then echo "Rate limit low, waiting..." sleep 60 fi

Далее: Кейс: Python API с тестами и деплоем