Tutorial: integrate Sentry into your GitHub Actions deploy pipeline — automatic source map upload & issue creation (PHP & JavaScript)

Ferramentas & Produtividade · By · Published on · 9 min read

Office desk with large monitor showing interface layouts, mechanical keyboard and plants
Clean workstation with a monitor displaying layouts; conveys development and deploy Photo: Pew Nguyen / Pexels

This tutorial shows how to integrate Sentry into your GitHub Actions deploy pipeline to automatically upload source maps and create issues for PHP and JavaScript. You’ll create releases, upload frontend source maps in CI, and tag both frontend and backend with the same release so stack traces are readable and correlated with deploy commits.

Prerequisites and what you’ll configure

You’ll build a CI/CD flow that registers a release in Sentry, uploads frontend source maps, and tags the PHP backend with the release. At the end, any production exception becomes a Sentry issue with an unobfuscated stack trace associated with the deploy commit.

What you need before starting:

- A Sentry account and project (organization slug and project slug).

- A Sentry DSN for the frontend (public) and the backend (server).

- A SENTRY_AUTH_TOKEN with releases permissions.

- A GitHub repository with GitHub Actions enabled.

- A JS project that generates source maps (Vite or Webpack) and a PHP backend with the Sentry SDK.

Configure Sentry in JavaScript and generate build source maps

Initialize the Sentry SDK in your JS app and ensure the bundler generates production source maps. A source map maps minified JavaScript back to the original source so stack traces are readable. MDN has a good explanation of the concept.

Set the release and environment variables from the pipeline (for example, via Vite). Do NOT publish .map files to your CDN; we’ll upload them to Sentry in CI.

// Instale o SDK do browser
// npm i @sentry/browser --save

// src/sentry.ts (ou no bootstrap do app)
import * as Sentry from "@sentry/browser";

Sentry.init({
  dsn: import.meta.env.VITE_SENTRY_DSN, // DSN público do projeto
  release: import.meta.env.VITE_RELEASE, // versão injetada pelo CI
  environment: import.meta.env.MODE || "production",
});

// Exemplo: capturar erro manual (para teste)
// Sentry.captureException(new Error("Sentry JS test error"));

// vite.config.ts (Vite) — habilite sourcemap em produção
// import { defineConfig } from "vite";
// export default defineConfig({
//   build: { sourcemap: true },
// });

// webpack.config.js (Webpack) — alternativa
// module.exports = {
//   // ...
//   devtool: "source-map", // gera .map para produção
// };

PHP: install the SDK and mark release/environment in bootstrap

On the PHP backend, install the SDK and initialize it with the DSN, release and environment. This ensures server exceptions are attributed to the same release as the frontend. Frameworks may provide integrations; the example below works in any PHP app.

To capture unhandled exceptions, use the SDK’s default handler or integrate with your framework. Do NOT log sensitive tokens in exceptions.

<?php
// Instale o SDK PHP (Composer):
// composer require sentry/sdk

require_once __DIR__ . '/vendor/autoload.php';

Sentry\init([
    'dsn' => getenv('SENTRY_DSN'),
    'release' => getenv('RELEASE') ?: getenv('SENTRY_RELEASE'),
    'environment' => getenv('ENVIRONMENT') ?: 'production',
]);

// Exemplo de teste
// try {
//     throw new Exception('Sentry PHP test error');
// } catch (Throwable $e) {
//     Sentry\captureException($e);
// }

Which secrets and variables to use in GitHub Actions?

Create repository secrets for the Sentry token and the organization/project slugs. Release and environment variables can be set as workflow env. Do NOT expose SENTRY_AUTH_TOKEN in logs.

Key Type Purpose
SENTRY_AUTH_TOKEN Secret Authenticate sentry-cli for releases and source map uploads
SENTRY_ORG Secret Sentry organization slug
SENTRY_PROJECT Secret Sentry project slug
SENTRY_DSN_PUBLIC Secret Public DSN for the frontend (injected into the build)
SENTRY_DSN Secret Server DSN for PHP (configured in infrastructure)
RELEASE Env Deploy version (e.g. GITHUB_SHA or a tag)
ENVIRONMENT Env Deploy environment (e.g. production, staging)

GitHub Actions pipeline: build, release and automatic source map upload

The workflow below creates a Sentry release, associates commits, uploads the source maps generated by your bundler, and finalizes the release. It also injects RELEASE and the public DSN into the frontend build so events are correctly tagged.

If your deploy has extra steps (canary, smoke tests, rollback), integrate this into your existing pipeline. Examples: Canary deploys with GitHub Actions and Nginx/ PHP and a pipeline with rollback and smoke tests.

name: deploy

on:
  push:
    branches: ["main"]

env:
  RELEASE: ${{ github.sha }}
  ENVIRONMENT: production

jobs:
  build-and-release:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0 # necessário para set-commits --auto

      - name: Setup Node
        uses: actions/setup-node@v4
        with:
          node-version: '20'

      - name: Install deps
        run: npm ci

      - name: Build (inject release and DSN)
        run: |
          echo "VITE_RELEASE=${RELEASE}" >> .env
          echo "VITE_SENTRY_DSN=${{ secrets.SENTRY_DSN_PUBLIC }}" >> .env
          npm run build

      - name: Install sentry-cli
        run: npm i -g @sentry/cli

      - name: Create release in Sentry
        env:
          SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
          SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
          SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }}
        run: |
          sentry-cli releases new "$RELEASE"
          sentry-cli releases set-commits "$RELEASE" --auto

      - name: Upload source maps to Sentry
        env:
          SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
          SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
          SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }}
        run: |
          # Ajuste o caminho conforme seu bundler (ex.: dist, build)
          sentry-cli releases files "$RELEASE" upload-sourcemaps ./dist \
            --url-prefix "~/" \
            --validate --rewrite

      - name: Finalize release
        env:
          SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
          SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
          SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }}
        run: sentry-cli releases finalize "$RELEASE"

      - name: Deploy
        run: |
          # Execute seu deploy (ex.: rsync, kubectl, serverless, etc.)
          echo "Deploy step here"

How to mark the same release in the PHP backend during deploy

The backend must receive the same RELEASE and ENVIRONMENT variables used in the workflow. You can write these variables into the server .env, the container manifest, or the service manager (e.g. systemd, ECS). PHP will read them at bootstrap so events are sent with the correct version.

  • Persist RELEASE and ENVIRONMENT in the service configuration.
  • Restart PHP/FPM after changing variables.
  • Ensure the server DSN (SENTRY_DSN) is configured in the host, container, or secret manager.
# Exemplo simples: escrever variáveis em um .env no servidor durante o deploy
# (substitua /var/www/app pelo caminho do seu app)
ssh user@host "echo 'RELEASE=${RELEASE}' | sudo tee -a /var/www/app/.env && \
               echo 'ENVIRONMENT=${ENVIRONMENT}' | sudo tee -a /var/www/app/.env && \
               sudo systemctl restart php-fpm"

How to verify it worked (post-deploy checks)

Validate the integration by generating a test exception in the frontend and backend. Within seconds, Sentry should create issues with the correct release and environment, and the JS stack trace should be de-obfuscated thanks to the source maps.

Run tests only in a controlled environment and remove the test code after validation.

  • Check in Sentry that events are tied to the correct release.
  • Confirm the JS stack trace points to original files/lines.
  • Verify the environment matches production or staging.
# Frontend (abra o console do navegador após o deploy)
// window.Sentry.captureException(new Error("Sentry JS test after deploy"));

# Backend PHP (rota temporária)
<?php
// /debug/sentry-test (remova depois)
throw new Exception('Sentry PHP test after deploy');

Common troubleshooting

Events show up without a release? Ensure RELEASE was injected into the frontend build and is available to the PHP bootstrap. The value must match the one used with sentry-cli releases.

Source maps not applying? The url-prefix must match how your app serves assets in production. If assets are under /static or a CDN, adjust the prefix. Do NOT publish .map files publicly; keep them private and upload only to Sentry.

Invalid token or insufficient permissions? Recreate SENTRY_AUTH_TOKEN with release scopes in Sentry. Do not print the token in logs. Use GitHub Secrets.

Build removes .map files? Check bundler config (Vite: build.sourcemap=true; Webpack: devtool=source-map). MDN has a guide on source maps.

Commits don't appear in the release? Make sure the repo was checked out with history (fetch-depth: 0) before set-commits, or provide the commit range manually to sentry-cli. In monorepos, target the correct project.

Frequently asked questions

Do I need to expose the DSN in the frontend?

Yes. The browser SDK uses a public DSN to send events. This DSN doesn’t grant administrative access. The server DSN must remain protected. Never expose SENTRY_AUTH_TOKEN, which is used only in CI for releases and source map uploads.

How should I set the release automatically in CI?

Use a repository-derived identifier like GITHUB_SHA, a semantic tag, or a short hash. The important part is using the same value with sentry-cli releases, in the frontend build, and in the backend configuration so events map to the same release.

Where should source maps live: Sentry or the CDN?

You only need to upload source maps to Sentry via CI/CD for Sentry to de-obfuscate stack traces. They don’t need to be public on the CDN. Keeping .map files private avoids exposing source code. Just make sure url-prefix and paths match your production assets.

What permissions does the Sentry token need for uploads?

SENTRY_AUTH_TOKEN must allow creating and editing releases and uploading files. Create it in Sentry with the appropriate scopes and store it in GitHub Secrets. Limit scope to the organization/project and rotate tokens periodically.

Can I use the official action instead of sentry-cli via npm?

Yes. There are Actions that simplify creating releases, setting commits, uploading source maps, and finalizing releases. The secrets and variables remain the same. Use an Action to reduce shell steps in the workflow if you prefer.

Does this work with monorepos and multiple Sentry projects?

Yes, but run sentry-cli per project where you want to publish a release and source maps, setting the correct SENTRY_PROJECT. Adjust build directories per app and keep releases consistent between services to maintain correlation between frontend and backends.

Want to improve your pipeline with practical observability?

Integrate releases, source maps, and fast regression detection into your CI/CD. If you use GitHub Actions and want to add canary deploys, smoke tests and rollback, follow the suggested guides and implement it today.

Explore more tutorials

See also