Skip to content
prod e051e98
Browse

6 · Optional integrations

Objective — surface (don’t silently skip) the optional integrations — Slack notifications for errors/deploys/backups, GitHub project management (labels, issue forms, project board, PR template), and privacy-first Rybbit analytics — so operations and feedback loops are wired before users arrive.

These are OPTIONAL but valuable. Per the phase’s optional-tasks policy, surface each one and let the operator decide — never silently skip. Configure them now if you have the time; defer explicitly if not.

flowchart LR
Sentry["Sentry errors"] --> Alerts["#app-alerts"]
Deployer["Deployer"] --> Deploys["#app-deploys"]
Backup["Backups"] --> Backups["#app-backups"]
Alerts --> Slack(["Slack workspace"])
Deploys --> Slack
Backups --> Slack

Automated Slack alerts for Sentry errors, deployments, and backup status.

  1. Set up the workspace (first project only). If you don’t have a workspace, create one at slack.com/create. Create an incoming-webhook app: api.slack.com/appsCreate New App → From scratch → name <Org> NotificationsIncoming Webhooks → Activate ONAdd New Webhook to Workspace → pick a channel → copy the URL (https://hooks.slack.com/services/T…/B…/xxx). Store the webhook URL, workspace, app name, and creation date in your password manager.

    • ✅ The workspace + incoming-webhook app exist, URL stored in the vault.
  2. Create the project channels & webhooks — one channel per concern, then a channel-specific webhook for each.

    ChannelPurpose
    #<app>-alertsSentry errors and critical alerts
    #<app>-deploysDeployment notifications
    #<app>-backupsBackup success/failure (optional)

    Add the webhook URLs to .env (real values) and .env.example (placeholders, safe to commit):

    Terminal window
    ## === SLACK NOTIFICATIONS ===
    SLACK_ALERTS_WEBHOOK=<your-slack-alerts-webhook-url>
    SLACK_DEPLOYS_WEBHOOK=<your-slack-deploys-webhook-url>
    SLACK_BACKUPS_WEBHOOK=<your-slack-backups-webhook-url>
    # Expected: placeholders in .env.example; real webhook URLs in .env
    • ✅ Per-concern channels exist with webhook URLs wired into env.
  3. Wire the integrations.

    • Sentry → Slack (requires Sentry Team plan) — Settings → Integrations → Slack → authorize, then Alerts → Create Alert Rule (> 0 errors in 1 min, filter production, action: send to #<app>-alerts). On the free plan, skip and track via a GitHub issue.

    • Deployer → Slack — add success/failure tasks to deploy.php:

      use Deployer\Utility\Httpie;
      task('slack:notify:success', function () {
      $webhookUrl = getenv('SLACK_DEPLOYS_WEBHOOK');
      if (!$webhookUrl) { writeln('<comment>SLACK_DEPLOYS_WEBHOOK not set - skipping</comment>'); return; }
      $app = get('application', 'App');
      $stage = get('labels')['stage'] ?? 'unknown';
      $branch = run('git rev-parse --abbrev-ref HEAD', ['timeout' => 5])->toString();
      $commit = run('git log -1 --oneline', ['timeout' => 5])->toString();
      Httpie::post($webhookUrl)->body([
      'text' => "*{$app}* deployed to *{$stage}*\nBranch: `{$branch}`\nCommit: {$commit}",
      'username' => 'Deployer', 'icon_emoji' => ':rocket:',
      ])->send();
      })->desc('Send deploy success notification to Slack');
      task('slack:notify:failure', function () {
      $webhookUrl = getenv('SLACK_DEPLOYS_WEBHOOK');
      if (!$webhookUrl) { return; }
      $app = get('application', 'App');
      $stage = get('labels')['stage'] ?? 'unknown';
      Httpie::post($webhookUrl)->body([
      'text' => "*{$app}* deployment to *{$stage}* failed\nCheck logs for details.",
      'username' => 'Deployer', 'icon_emoji' => ':x:',
      ])->send();
      })->desc('Send deploy failure notification to Slack');
      after('deploy:success', 'slack:notify:success');
      after('deploy:failed', 'slack:notify:failure');
    • Backups → Slack — easiest is to rely on Sentry Cron Monitors (no extra config). Otherwise add a slack block to config/backup.php’s notifications with 'webhook_url' => env('SLACK_BACKUPS_WEBHOOK').

    • ✅ The Sentry, Deployer, and backup notification paths are wired (or consciously skipped).

  4. Test the webhook.

    Terminal window
    set -a && source .env && set +a # or export each SLACK_*_WEBHOOK you test
    curl -X POST -H 'Content-type: application/json' \
    --data '{"text":"Slack webhook test successful!"}' \
    "$SLACK_ALERTS_WEBHOOK"
    # Expected: "ok" and the message appears in the channel

    Then run dep deploy staging and confirm the notification lands in #<app>-deploys. Finally, add the SLACK_*_WEBHOOK vars to the production .env and clear the config cache.

    • ✅ The test curl returns ok and a real deploy notifies #<app>-deploys.

Set up GitHub Issues, typed labels, YAML issue forms, a project board, and a PR template.

  1. Create the typed labels. At github.com/<org>/<repo>/labels: delete the redundant defaults (bug, documentation, enhancement, question — replaced by typed labels), keep duplicate/good first issue/help wanted/invalid/wontfix, then create four typed families (~25 labels total).

    FamilyLabels (color)
    Prioritypriority: critical #b60205, high #d93f0b, medium #fbca04, low #0e8a16
    Typetype: bug #d73a4a, feature #a2eeef, enhancement #7057ff, docs #0075ca, refactor #f9d0c4, security #ee0701, question #d876e3
    Statusstatus: triage #cfd3d7, confirmed #1d76db, in-progress #5319e7, blocked #e99695, needs-info #d876e3
    Areaarea: frontend #bfd4f2, backend #b4a7d6, database #c5def5, devops #d4c5f9 (+ optional auth/payments/api)
    • ✅ The four typed label families exist.
  2. Create the issue forms under .github/ISSUE_TEMPLATE/. Example bug_report.yml:

    name: Bug Report
    description: Report a bug or unexpected behavior
    title: "[BUG] "
    labels: ["type: bug", "status: triage"]
    body:
    - type: textarea
    id: description
    attributes: { label: Bug Description }
    validations: { required: true }
    - type: textarea
    id: steps
    attributes: { label: Steps to Reproduce }
    validations: { required: true }
    - type: textarea
    id: expected
    attributes: { label: Expected Behavior }
    validations: { required: true }
    - type: dropdown
    id: severity
    attributes:
    label: Severity
    options:
    - Critical (app unusable, data loss)
    - High (major feature broken)
    - Medium (workaround exists)
    - Low (minor inconvenience)
    validations: { required: true }
    - type: checkboxes
    id: checklist
    attributes:
    label: Pre-submission Checklist
    options:
    - label: I searched existing issues to ensure this is not a duplicate
    required: true

    Add feature_request.yml (problem statement, proposed solution, importance dropdown) and task.yml (description, acceptance criteria, area dropdown) on the same pattern, plus config.yml to disable blank issues and route security reports privately:

    blank_issues_enabled: false
    contact_links:
    - name: Documentation
    url: https://docs.<domain>
    about: Check the docs before opening an issue
    - name: Security Vulnerability
    url: https://github.com/<org>/<repo>/security/advisories/new
    about: Report security vulnerabilities privately
    • ✅ Bug/feature/task issue forms + config.yml exist under .github/ISSUE_TEMPLATE/.
  3. Create the project board. Organization → Projects → New project → Kanban → name <App> Development; Status field: Backlog, Triage, Todo, In Progress, In Review, Done; custom fields Priority (Critical/High/Medium/Low), optional Estimate (XS–XL); workflows item added → Backlog, reopened → Todo, closed / PR merged → Done, Enable Auto-add with filter is:issue is:open; link it: gh project link <number> --owner <owner> --repo <owner>/<repo>.

    • ✅ The Kanban board exists, is linked, and auto-adds open issues.
  4. Create the PR template & discussions. Create .github/PULL_REQUEST_TEMPLATE.md with sections: Description, Type of Change, Related Issues, Changes Made, Screenshots, Testing Instructions, Checklist, Deployment Notes. Optionally enable Discussions (Settings → General → Features). Commit .github/ once done.

    • ✅ The PR template is committed and Discussions are enabled if wanted.

Privacy-first, cookieless analytics — session replay, funnels, goals, web vitals, and error tracking with no consent banner. A complement to (not replacement for) Google Analytics.

  1. Activate & add the site. app.rybbit.io/redeem → redeem license → Dashboard → Sites → Add Website (domain, no https://) → set Public Analytics Off, User ID Salting On → copy the Site ID.

    • ✅ The site is added and its Site ID is copied.
  2. Configure the site settings — Block Bot Traffic On, Track IP Address Off, Web Vitals On, Error Tracking On, Track Outbound Links On, Track SPA Navigation On; connect Google Search Console.

    • ✅ The site settings match the privacy-first profile.
  3. Install the tracking script — find layout files with a <head> and add the tracking script (ideally a shared partials/analytics.blade.php).

    Terminal window
    grep -r "<!DOCTYPE html" resources/views/ packages/ --include="*.blade.php" -l
    # Expected: the layout files with a <head> to inject the script
    .env
    RYBBIT_SITE_ID=<your-site-id>
    config/services.php
    'rybbit' => ['site_id' => env('RYBBIT_SITE_ID')],
    • ✅ The tracking script is wired via a shared partial and the Site ID is in env/config.
  4. Set skip & mask patterns — Dashboard → Settings → Tracking Script: skip /admin/**, /setting/**; mask /users/*/profile.

    • ✅ Admin paths are skipped and sensitive paths masked.
  5. Enable the dashboard features — Performance (Web Vitals); Session Replay On with Masking + Mask All Inputs On; Error Tracking On.

    • ✅ Performance, masked session replay, and error tracking are on.
  6. Wire custom events & identity.

    <button data-rybbit-event="signup_clicked">Sign Up</button>
    window.rybbit.event("plan_purchased", { plan: "pro", interval: "yearly" });
    // inside an @auth block:
    window.rybbit.identify("{{ auth()->id() }}");
    • ✅ Custom events and authenticated-user identity are wired.
  7. Create goals & funnels — goals (Signup Completed, Pricing Page Viewed, Trial Started) and a funnel (//pricing/register → event).

    • ✅ Goals and a conversion funnel exist.
  8. Deploy & verify. Deploy, set RYBBIT_SITE_ID in production, php artisan config:clear && php artisan view:clear, then visit the site in incognito and confirm hits in the Rybbit real-time dashboard. Store the Site ID, account email, dashboard URL, tier, and any API key in your password manager.

    • ✅ Real-time hits appear in the Rybbit dashboard after deploy.

Do not mark this step done until every box below is checked.

  • 🔀 Slack webhook test posts — Deployer notifies #<app>-deploys (or consciously deferred).
  • 🔀 GitHub labels, issue forms, project board, PR template — in place (or deferred).
  • 🔀 Rybbit live and recording hits — admin paths skipped and inputs masked (or deferred).
  • 👤 Every deferred item was surfaced — to the operator, not silently skipped.