Notification & Reporting

Notification & Reporting #

Pipeline yang selesai tanpa memberitahu siapapun adalah pipeline yang berjalan di kekosongan. Tim perlu tahu saat deployment berhasil, dan perlu tahu lebih cepat lagi saat deployment gagal. Tapi notifikasi yang berlebihan adalah noise yang diabaikan — sama buruknya dengan tidak ada notifikasi. Artikel ini membahas cara membangun sistem notifikasi yang informatif tanpa menjadi spam, dan laporan yang memberikan visibilitas nyata atas aktivitas deployment.

Notifikasi Slack yang Informatif #

# roles/notify/tasks/slack.yml
---
- name: Kirim notifikasi Slack
  uri:
    url: "{{ slack_webhook_url }}"
    method: POST
    body_format: json
    body:
      attachments:
        - color: "{{ 'good' if status == 'success' else 'danger' }}"
          title: >
            {{ '✅' if status == 'success' else '❌' }}
            {{ title }}            
          fields:
            - title: Environment
              value: "{{ env | upper }}"
              short: true
            - title: Versi
              value: "{{ app_version }}"
              short: true
            - title: Waktu
              value: "{{ ansible_date_time.iso8601 }}"
              short: true
            - title: Oleh
              value: "{{ deployed_by | default('CI Pipeline') }}"
              short: true
            - title: Detail
              value: "{{ detail | default('') }}"
              short: false
          footer: "Ansible Deployment"
          ts: "{{ ansible_date_time.epoch }}"
  delegate_to: localhost
  run_once: true
  no_log: true
  when: slack_webhook_url is defined

Penggunaan di playbook deployment:

# Di post_tasks playbook deploy
post_tasks:
  - name: Notifikasi deployment sukses
    include_role:
      name: notify
      tasks_from: slack.yml
    vars:
      status: success
      title: "Deployment Berhasil — {{ app_name }}"
      detail: >
        Versi {{ app_version }} sukses di-deploy ke
        {{ ansible_play_hosts | length }} server.        
    run_once: true

rescue:
  - name: Notifikasi deployment gagal
    include_role:
      name: notify
      tasks_from: slack.yml
    vars:
      status: failure
      title: "Deployment GAGAL — {{ app_name }}"
      detail: >
        {{ ansible_failed_result.msg | default('Error tidak diketahui') }}
        di {{ inventory_hostname }}        
    run_once: true

Notifikasi Email untuk Summary Harian #

# playbooks/daily-deployment-summary.yml
---
- name: Generate dan kirim summary deployment harian
  hosts: localhost
  vars:
    log_file: /var/log/deployments.log
    report_date: "{{ ansible_date_time.date }}"

  tasks:
    - name: Baca log deployment hari ini
      shell: "grep {{ report_date }} {{ log_file }} || echo 'Tidak ada deployment hari ini'"
      register: today_deployments
      changed_when: false

    - name: Hitung statistik deployment
      set_fact:
        total_deployments: "{{ today_deployments.stdout_lines | select('search', 'SUCCESS|ROLLBACK|FAILED') | list | length }}"
        successful_deployments: "{{ today_deployments.stdout_lines | select('search', 'SUCCESS') | list | length }}"
        failed_deployments: "{{ today_deployments.stdout_lines | select('search', 'FAILED|ROLLBACK') | list | length }}"

    - name: Kirim email summary
      community.general.mail:
        host: "{{ smtp_host }}"
        port: "{{ smtp_port | default(587) }}"
        username: "{{ smtp_username }}"
        password: "{{ vault_smtp_password }}"
        to: "{{ deployment_report_recipients }}"
        subject: "Deployment Summary {{ report_date }} — {{ successful_deployments }}/{{ total_deployments }} sukses"
        subtype: html
        body: |
          <h2>Deployment Summary {{ report_date }}</h2>
          <table border="1" cellpadding="5">
            <tr><td><b>Total Deployment</b></td><td>{{ total_deployments }}</td></tr>
            <tr><td><b>Sukses</b></td><td style="color:green">{{ successful_deployments }}</td></tr>
            <tr><td><b>Gagal/Rollback</b></td><td style="color:red">{{ failed_deployments }}</td></tr>
          </table>
          <h3>Detail:</h3>
          <pre>{{ today_deployments.stdout }}</pre>          
      no_log: true

Deployment Changelog Otomatis #

Generate changelog antara versi yang lama dan yang baru:

# tasks/generate-changelog.yml
---
- name: Generate changelog antara versi
  shell: |
    git log \
      v{{ previous_version }}..v{{ current_version }} \
      --oneline \
      --no-merges \
      --format="- %h %s (%an)"    
  args:
    chdir: "{{ app_src_dir }}"
  register: changelog_raw
  changed_when: false
  delegate_to: localhost

- name: Set changelog fact
  set_fact:
    deployment_changelog: "{{ changelog_raw.stdout }}"

- name: Kirim changelog ke Slack
  uri:
    url: "{{ slack_webhook_url }}"
    method: POST
    body_format: json
    body:
      text: "*Changelog v{{ previous_version }} → v{{ current_version }}*"
      attachments:
        - color: good
          text: "{{ deployment_changelog | truncate(2000) }}"
  delegate_to: localhost
  no_log: true
  when:
    - deployment_changelog | length > 0
    - slack_webhook_url is defined

Update Deployment Status di Sistem Eksternal #

# Catat deployment di Jira
- name: Tambahkan komentar di Jira issues yang ada di changelog
  uri:
    url: "https://company.atlassian.net/rest/api/3/issue/{{ item }}/comment"
    method: POST
    user: "{{ jira_username }}"
    password: "{{ vault_jira_token }}"
    force_basic_auth: true
    body_format: json
    body:
      body:
        type: doc
        version: 1
        content:
          - type: paragraph
            content:
              - type: text
                text: "Deployed to {{ env }} in version {{ app_version }}"
    status_code: [201, 400]   # 400 jika issue tidak ditemukan — tidak masalah
  loop: "{{ jira_issues_in_changelog }}"
  no_log: true
  when: jira_issues_in_changelog | length > 0

# Catat deployment di Datadog sebagai event
- name: Catat deployment event di Datadog
  uri:
    url: "https://api.datadoghq.com/api/v1/events"
    method: POST
    headers:
      DD-API-KEY: "{{ vault_datadog_api_key }}"
    body_format: json
    body:
      title: "Deployment: {{ app_name }} v{{ app_version }}"
      text: "Deploy ke {{ env }} oleh {{ deployed_by | default('pipeline') }}"
      tags:
        - "env:{{ env }}"
        - "service:{{ app_name }}"
        - "version:{{ app_version }}"
      alert_type: info
      source_type_name: ansible
  delegate_to: localhost
  no_log: true

Dashboard Deployment History #

# playbooks/generate-deployment-report.yml
---
- name: Generate HTML deployment report
  hosts: localhost
  tasks:
    - name: Baca semua log deployment
      slurp:
        src: /var/log/deployments.log
      register: raw_log

    - name: Parse log deployment
      set_fact:
        deployments: >-
          {{ raw_log.content | b64decode | split('\n')
             | select('match', '.*SUCCESS|.*FAILED|.*ROLLBACK')
             | list }}          

    - name: Generate HTML report
      template:
        src: deployment-report.html.j2
        dest: /var/www/html/deployments/index.html

    - name: Deploy report ke server internal
      copy:
        src: /var/www/html/deployments/index.html
        dest: /var/www/reports/deployments.html
        remote_src: false

Ringkasan #

  • Notifikasi Slack yang informatif mencantumkan: environment, versi, waktu, siapa yang deploy, dan (saat gagal) pesan error yang jelas.
  • Gunakan run_once: true untuk notifikasi di playbook multi-host — cegah satu notifikasi per host saat play berjalan di banyak server.
  • Summary harian via email lebih baik dari notifikasi per-deployment untuk lingkungan staging yang sering deploy — kurangi noise sambil tetap memberikan visibilitas.
  • Changelog otomatis dari git log antara dua versi memberikan konteks ke tim tentang apa yang berubah — sangat berguna untuk review pasca-deployment.
  • Integrasikan deployment event ke Datadog/New Relic/Grafana sebagai annotation — langsung terlihat di dashboard metrik kapan deployment terjadi dan korelasinya dengan perubahan metrik.
  • Notifikasi yang baik tidak mengganggu — kirim notifikasi sukses ke channel deployment, notifikasi gagal ke channel yang juga dimonitor on-call duty.

← Sebelumnya: Artifact Management   Berikutnya: Best Practice →

About | Author | Content Scope | Editorial Policy | Privacy Policy | Disclaimer | Contact