Skip to content

marcus-hooper/deployment-notification-o365

Repository files navigation

Deployment Notification O365

CI codecov CodeQL Security OpenSSF Scorecard GitHub release Python 3.13+ License: MIT

A GitHub Action that sends deployment notifications via email using Microsoft Graph API and Microsoft Entra ID (formerly Azure Active Directory).

Features

  • Sends deployment notification emails when deployments complete
  • Integrates with Microsoft Graph API for email delivery
  • Uses Microsoft Entra ID for secure authentication
  • Includes repository, environment, timestamp, and recent commit messages
  • Validates recipient email addresses with clear error messages for misconfiguration
  • Automatic retry with exponential backoff for transient errors (429, 503, 504, timeouts)
  • Structured log output with repository and environment context on every log line
  • Cross-platform (runs on Linux, macOS, and Windows runners)

Quick Start

- name: Send Deployment Notification
  uses: marcus-hooper/deployment-notification-o365@v1
  env:
    AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
    AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
    AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
    NOTIFICATION_TO: [email protected]
    NOTIFICATION_FROM: [email protected]

Inputs

This action uses environment variables instead of with: inputs. See Environment Variables for configuration.

Outputs

This action does not produce outputs.

Usage

- name: Send Deployment Notification
  uses: marcus-hooper/deployment-notification-o365@v1
  env:
    AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
    AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
    AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
    GITHUB_REPOSITORY: ${{ github.repository }}
    GITHUB_ACTOR: ${{ github.actor }}
    GITHUB_ENVIRONMENT: production
    NOTIFICATION_TO: [email protected], [email protected]
    NOTIFICATION_FROM: [email protected]

With Commit Messages

To include recent commit messages in the notification, create a commit_message.txt file before calling the action:

- name: Get recent commits
  run: git log --oneline -5 > commit_message.txt

- name: Send Deployment Notification
  uses: marcus-hooper/deployment-notification-o365@v1
  env:
    AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
    AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
    AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
    GITHUB_REPOSITORY: ${{ github.repository }}
    GITHUB_ACTOR: ${{ github.actor }}
    GITHUB_ENVIRONMENT: production
    NOTIFICATION_TO: [email protected], [email protected]
    NOTIFICATION_FROM: [email protected]

Complete Workflow Example

Here's a complete deployment workflow with notification:

name: Deploy and Notify

on:
  push:
    branches: [main]

jobs:
  deploy:
    name: Deploy Application
    runs-on: ubuntu-latest
    environment: production
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 5

      - name: Deploy to production
        run: |
          # Your deployment steps here
          echo "Deploying application..."

      - name: Capture recent commits
        run: git log --oneline -5 > commit_message.txt

      - name: Send Deployment Notification
        uses: marcus-hooper/deployment-notification-o365@v1
        env:
          AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
          AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
          AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
          GITHUB_REPOSITORY: ${{ github.repository }}
          GITHUB_ACTOR: ${{ github.actor }}
          GITHUB_ENVIRONMENT: ${{ github.environment }}
          NOTIFICATION_TO: ${{ vars.NOTIFICATION_TO }}
          NOTIFICATION_FROM: ${{ vars.NOTIFICATION_FROM }}

Sample Email Output

The action sends a plain text email with the following format:

Subject:

Deployment Successful: owner/repo to production on 2026-01-15 14:30:45

Body:

Repository: owner/repo
Environment: production
Deployment Time: 2026-01-15 14:30:45
Status: Successful
Started by: username
Repository URL: https://github.com/owner/repo

Recent Commit Messages:
abc1234 Fix authentication bug
def5678 Add new feature

Prerequisites

Microsoft Entra ID Application

  1. Register an application in Azure Portal > Microsoft Entra ID > App registrations > New registration

    • Name: GitHub Deployment Notifications (or your preference)
    • Supported account types: Single tenant
    • Redirect URI: Leave blank
  2. Add API permissions

    • Go to API permissions > Add a permission > Microsoft Graph
    • Select Application permissions (not Delegated)
    • Search for and add Mail.Send
    • Click Grant admin consent (requires admin privileges)
  3. Create a client secret

    • Go to Certificates & secrets > New client secret
    • Set an expiration (recommend 12-24 months)
    • Copy the secret value immediately (shown only once)
  4. Note your credentials

    • Tenant ID: Found in Overview
    • Client ID: Found in Overview (Application ID)
    • Client Secret: The value you copied above

GitHub Secrets

Add the following secrets to your repository (Settings > Secrets and variables > Actions):

Secret Description
AZURE_TENANT_ID Azure AD Tenant ID
AZURE_CLIENT_ID Azure AD Application Client ID
AZURE_CLIENT_SECRET Azure AD Application Client Secret

Environment Variables

Required (User-Provided)

Variable Description
AZURE_TENANT_ID Microsoft Entra ID Tenant ID
AZURE_CLIENT_ID Microsoft Entra ID Application Client ID
AZURE_CLIENT_SECRET Microsoft Entra ID Application Client Secret
NOTIFICATION_TO Comma-separated recipient email addresses
NOTIFICATION_FROM Sender email address (must have a mailbox in your tenant)

Provided by GitHub Actions

These variables are automatically available in GitHub Actions workflows and do not need to be explicitly set:

Variable Description
GITHUB_REPOSITORY Repository name (owner/repo) - automatically set
GITHUB_ACTOR User who triggered the deployment - automatically set
GITHUB_ENVIRONMENT Deployment environment - set when using environment: in job

Optional

File Description
commit_message.txt File containing recent commit messages to include

How It Works

  1. Loads Azure credentials from environment variables
  2. Reads commit_message.txt if present in the working directory
  3. Formats email with repository, environment, timestamp, and commits
  4. Authenticates via Microsoft Entra ID using client credentials flow
  5. Sends email via Microsoft Graph API (/users/{sender}/sendMail) with automatic retry for transient errors

Limitations

  • Plain text emails only - HTML formatting is not supported
  • US/Eastern timezone - Timestamps use US/Eastern timezone; not configurable
  • Limited retry scope - Retries transient Graph API errors (429/503/504/timeout) up to 3 times with exponential backoff; non-retryable errors (400/401/403/404) fail immediately
  • Environment variables only - Uses env: rather than with: inputs

Troubleshooting

Common Errors

Error Cause Solution
AADSTS7000215: Invalid client secret Client secret is incorrect or expired Regenerate the client secret in Azure Portal
AADSTS700016: Application not found Wrong Client ID or Tenant ID Verify IDs in Azure Portal > App registrations
Authorization_RequestDenied Missing Mail.Send permission Add permission and grant admin consent
ErrorItemNotFound / MailboxNotFound NOTIFICATION_FROM email doesn't exist Use an email with a valid mailbox in your tenant
Invalid email address(es) NOTIFICATION_TO contains malformed emails Check that all addresses have exactly one @ with non-empty local and domain parts
No valid email addresses provided NOTIFICATION_TO is empty or all entries are blank Provide at least one valid email address
Missing required environment variable Env var not set or empty Check secrets are correctly configured in GitHub

Debug Tips

  1. Check workflow logs - Expand the "Send notification" step for detailed error messages
  2. Verify Azure AD setup - Ensure admin consent is granted (green checkmark in API permissions)
  3. Test sender email - The NOTIFICATION_FROM address must be a valid mailbox, not just an alias
  4. Check secret expiration - Client secrets expire; regenerate if needed

Development

Requirements

  • Python 3.13+

Setup

# Install dev dependencies
pip install -r requirements-dev.txt

# Run tests
pytest

# Run linter
ruff check .

# Run type checker
mypy send_deployment_notification.py --ignore-missing-imports

Manual Testing

For end-to-end testing with real credentials:

export AZURE_TENANT_ID='your-tenant-id'
export AZURE_CLIENT_ID='your-client-id'
export AZURE_CLIENT_SECRET='your-secret'
export NOTIFICATION_TO='[email protected]'
export NOTIFICATION_FROM='[email protected]'
export GITHUB_REPOSITORY='owner/repo'
export GITHUB_ACTOR='username'
export GITHUB_ENVIRONMENT='test'
python send_deployment_notification.py

Project Structure

deployment-notification-o365/
├── .github/
│   ├── dependabot.yml
│   ├── ISSUE_TEMPLATE/
│   └── workflows/
│       ├── ci.yml              # Linting, type checking, tests
│       ├── codeql.yml          # CodeQL SAST analysis
│       ├── dependabot-auto-merge.yml  # Auto-merge Dependabot PRs
│       ├── labels.yml          # Repository label sync
│       ├── release.yml         # Version tag management
│       ├── schedule.yml        # Scheduled maintenance
│       ├── scorecard.yml       # OSSF Scorecard analysis
│       ├── security.yml        # Security scanning
│       └── validate.yml        # action.yml validation
├── tests/                      # Unit tests
├── action.yml                  # GitHub Action definition
├── send_deployment_notification.py
├── requirements.txt            # Production dependencies
├── requirements-dev.txt        # Development dependencies
└── pyproject.toml              # Tool configuration

Contributing

Contributions are welcome! Please see CONTRIBUTING.md for detailed guidelines.

Quick start:

  1. Check existing issues or open a new one
  2. Fork the repository
  3. Create a feature branch (git checkout -b feature/my-feature)
  4. Make your changes and add tests if applicable
  5. Ensure CI passes (lint, format, and test)
  6. Submit a pull request

See the issue templates for bug reports and feature requests.

Related Projects

Security

  • Store Azure credentials in GitHub Secrets (never as plain text)
  • Do not echo or log AZURE_CLIENT_SECRET in workflow steps
  • Rotate client secrets before expiration (check Azure Portal for expiry dates)
  • Use minimal Graph API permissions (Mail.Send only)

See SECURITY.md for security policy and reporting vulnerabilities.

Changelog

See CHANGELOG.md for version history.

License

This project is licensed under the MIT License - see the LICENSE file for details.

About

GitHub Action that sends deployment notifications via email using Microsoft Graph API and Azure AD authentication

Topics

Resources

License

Contributing

Security policy

Stars

Watchers

Forks

Contributors

Languages