Monitor your Microsoft 365 tenant's security configuration using Maester, the PowerShell-based test automation framework.
Check out the Maester documentation for more information on how to use Maester, or the github action documentation for more details on how to use the action.
Note
This github action only supports workload identity federation for authentication, since that is the recommended way to authenticate to Microsoft 365 services from Github Actions.
- Run public and private tests for Microsoft 365 security configurations.
- Supports Exchange Online and Teams tests.
- Customizable test runs with include/exclude tags.
- Detailed test results with optional email and Teams notifications.
- Uploads test results as GitHub Action artifacts.
- Supports telemetry control for privacy-conscious workflows.
| Name | Description | Required | Default |
|---|---|---|---|
tenant_id |
Entra ID Tenant ID. | β | |
client_id |
App Registration Client ID. | β | |
include_public_tests |
Maester 2 only. Install public tests from module. Empty means true. No effect on Maester 3 (use skip_builtin_tests). |
β | (empty, true) |
include_private_tests |
Check out the current repository. Maester 2: run the private tests in it. Maester 3: use its maester-config.json and custom tests, if there are any; set to false when the repository only holds the workflow file. |
β | true |
include_exchange |
Include Exchange Online tests in the test run. | β | false |
include_teams |
Include Teams tests in the test run. | β | true |
include_longrunning_tests |
Include long running tests. | β | false |
include_preview_tests |
Include preview tests. | β | false |
include_affected_objects |
Collect affected objects (Affected objects page and -affected-objects.json). |
β | false |
include_tags |
A list of tags to include in the test run (comma-separated). | β | |
exclude_tags |
A list of tags to exclude from the test run (comma-separated). | β | |
maester_version |
The version of Maester PowerShell to use (latest, preview, or specific version). latest and preview resolve to the newest release within maester_major_version. |
β | latest |
maester_major_version |
The Maester major version to run: 2 or 3. Set to 3 to opt in to Maester 3.0, see Upgrading to Maester 3.0. An exact maester_version must belong to this major version (2 also accepts exact 1.x versions). |
β | 2 |
skip_builtin_tests |
Maester 3 only. Run only the custom tests in the repository (Invoke-Maester -SkipBuiltIn). |
β | false |
install_pester |
Maester 3 only. Always install Pester 5.7.1 or later. By default it is installed only when the repository contains *.Tests.ps1 files. |
β | false |
test_ids |
Maester 3 only. Test IDs to run, comma-separated, * wildcards allowed (-TestId). |
β | |
exclude_test_ids |
Maester 3 only. Test IDs to exclude, comma-separated, * wildcards allowed (-ExcludeTestId). |
β | |
config_path |
Maester 3 only. Path to a maester-config.json run configuration, relative to the repository root (-Config). |
β | |
pester_verbosity |
Pester verbosity level (None, Normal, Detailed, Diagnostic). |
β | None |
step_summary |
Level of detail in the GitHub Actions step summary: Full (complete report), Summary (counts + per-test pass/fail list), Table (counts only), or false to disable. Legacy true maps to Full. |
β | Table |
artifact_upload |
Upload test results as GitHub Action artifacts. | β | true |
artifact_upload_html |
Upload the self-contained HTML report as a separate artifact and add a link to it in the step summary (served with an HTML mime type so it renders in the browser). | β | false |
disable_telemetry |
Disable telemetry logging. | β | false |
mail_recipients |
A list of email addresses to send the test results to (comma-separated). | β | |
mail_userid |
The user ID of the sender of the email. | β | |
mail_testresultsuri |
URI to the detailed test results page. | β | ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} |
notification_teams_webhook |
Webhook URL for sending test results to Teams. | β | |
notification_teams_channel_id |
The ID of the Teams channel to send the test results to. | β | |
notification_teams_team_id |
The ID of the Teams team to send the test results to. | β |
| Name | Description |
|---|---|
results_json |
The file location of the JSON output of the test results. |
tests_total |
The total number of tests |
tests_passed |
Number of passed tests |
tests_failed |
Number of failed tests |
tests_skipped |
Number of skipped tests |
result |
Result of all the tests Failed or Passed |
maester_version |
The exact Maester version that was installed and run |
Note
To use the outputs in your workflow, you need to set the id for the step that runs the action. The outputs can be accessed using ${{ steps.<step_id>.outputs.<output_name> }}.
Hereβs an example of how to use the Maester Action in your workflow file .github/workflows/maester.yml:
name: Run Maester Tests
on:
push:
branches:
- main
schedule:
# Daily at 7:30 UTC, change accordingly
- cron: "30 7 * * *"
# Allows to run this workflow manually from the Actions tab
workflow_dispatch:
permissions:
id-token: write
contents: read
checks: write
jobs:
test:
name: Run Maester Test Job
runs-on: ubuntu-latest
steps:
- name: Run Maester π₯
id: maester
# Set the action version to a specific version, to keep using that exact version.
# Or even better set it to a specific commit SHA to be sure nothing breaks unexpectedly.
uses: maester365/maester-action@main
with:
tenant_id: ${{ secrets.AZURE_TENANT_ID }}
client_id: ${{ secrets.AZURE_CLIENT_ID }}
include_public_tests: true
include_private_tests: false
include_exchange: false
include_teams: false
# Set a specific version of the powershell module here or 'latest' or 'preview'
# check out https://www.powershellgallery.com/packages/Maester/
maester_version: latest
disable_telemetry: false
step_summary: Table # Full, Summary, Table, or false
artifact_upload_html: true # Upload html report as separate artifact
- name: Write status π
shell: bash
run: |
echo "The result of the test run is: ${{ steps.maester.outputs.result }}"
echo "Total tests: ${{ steps.maester.outputs.tests_total }}"
echo "Passed tests: ${{ steps.maester.outputs.tests_passed }}"
echo "Failed tests: ${{ steps.maester.outputs.tests_failed }}"
echo "Skipped tests: ${{ steps.maester.outputs.tests_skipped }}"Maester 3.0 runs the built-in tests from inside the module and no longer depends on Pester. This action keeps
running Maester 2.x until you opt in: maester_version: latest and preview resolve to the newest 2.x release
while maester_major_version is 2 (the default), even after 3.0 is published. Nothing changes until you set
maester_major_version: "3".
Note
A later major version of this action will default to Maester 3 once 3.0 is generally available. Pipelines
pinned to a 1.x release of the action (for example maester365/maester-action@v1.2.0) or to a commit SHA keep
running Maester 2.x. Pipelines that use @main get the new default when it ships; set
maester_major_version: "2" now to stay on Maester 2.x.
On Maester 3 your repository only needs the workflow file. You no longer need a copy of
maester-tests or Install-MaesterTests: the built-in tests ship in
the module. Add a maester-config.json or a custom/ folder only if you want them.
Before:
- name: Run Maester π₯
uses: maester365/maester-action@main
with:
tenant_id: ${{ secrets.AZURE_TENANT_ID }}
client_id: ${{ secrets.AZURE_CLIENT_ID }}
include_public_tests: true
maester_version: latestAfter:
- name: Run Maester π₯
uses: maester365/maester-action@main
with:
tenant_id: ${{ secrets.AZURE_TENANT_ID }}
client_id: ${{ secrets.AZURE_CLIENT_ID }}
maester_major_version: "3" # opt in to Maester 3.x
maester_version: latest # newest 3.x release (or 'preview', or an exact 3.x version)
# The repository only holds this workflow file, so there is nothing to check out.
# Leave this out (default 'true') if the repository has a maester-config.json or custom tests.
include_private_tests: falseWhat changes on Maester 3:
- The built-in tests always run. The action no longer installs the public tests (
maester365/maester-tests) into the workspace, soinclude_public_testshas no effect (you get a warning if you set it). Your repository needs only the workflow file, plus an optionalmaester-config.jsonand custom tests. Withinclude_private_tests: falsethe repository is not checked out andInvoke-Maesterruns without-Path. Setskip_builtin_tests: trueto run only your custom tests (this needsinclude_private_tests: true), or useinclude_tags,test_idsandexclude_test_idsto pick tests. - Custom Pester tests need Pester. Pester-format custom tests (
*.Tests.ps1) need Pester 5.7.1 or later. The action installs it automatically when it finds*.Tests.ps1files in the repository; setinstall_pester: trueto always install it. - The
AllandFulltags were removed. The action stops with an error ifinclude_tagsorexclude_tagscontain them. Useinclude_preview_testsinstead ofAllandinclude_longrunning_testsinstead ofFull. - PowerShell 7.4 or later is required. GitHub-hosted runners already have it; check self-hosted runners.
- New inputs:
skip_builtin_tests,install_pester,test_ids,exclude_test_idsandconfig_path. They only work on Maester 3; the action fails if you set them whilemaester_major_versionis2. - An exact
maester_versionmust matchmaester_major_version:maester_version: 3.0.0withmaester_major_version: "2"fails with an error instead of guessing. Exact 1.x versions still work withmaester_major_version: "2".
Read Upgrading from Maester 2.x before you switch, and try the
upgrade on a branch or with workflow_dispatch first.
We welcome contributions, since this is a community project! Please check out our contributing guidelines for more information on how to get started.
Thanks for using Maester! If you have any questions or feedback, feel free to reach out to us on GitHub Discussions or Discord.