diff --git a/.vortex/docs/content/deployment/notifications.mdx b/.vortex/docs/content/deployment/notifications.mdx index c20b70f4b..e521e38a7 100644 --- a/.vortex/docs/content/deployment/notifications.mdx +++ b/.vortex/docs/content/deployment/notifications.mdx @@ -46,6 +46,22 @@ notification script. | `VORTEX_NOTIFY_PR_NUMBER` | No | Pull request number (empty for branch deployments) | | `VORTEX_NOTIFY_LABEL` | **Yes** | Human-readable deployment label | +## Branch filtering + +Each notification channel can be restricted to specific branches using +a `VORTEX_NOTIFY__BRANCHES` variable. When set, the channel +only sends notifications for deployments on the listed branches +(comma-separated, exact match). When empty or unset, the channel runs +on all branches. + +For example, to restrict New Relic notifications to only `main` and `staging`: + +```shell +VORTEX_NOTIFY_NEWRELIC_BRANCHES=main,staging +``` + +New Relic defaults to `main,master`. All other channels default to no filter. + ## Message templates and tokens Most notification channels support customizable message templates using replacement tokens: @@ -88,6 +104,7 @@ Send deployment notification via email. | `VORTEX_NOTIFY_EMAIL_RECIPIENTS` | **Yes** | | `.env` | Recipients (format: `email\|name`) | | `VORTEX_NOTIFY_EMAIL_PROJECT` | No | `VORTEX_NOTIFY_PROJECT` | `.env` | Project name for email | | `VORTEX_NOTIFY_EMAIL_MESSAGE` | No | Default template | `.env` | Custom message template | +| `VORTEX_NOTIFY_EMAIL_BRANCHES` | No | | `.env` | Restrict to specific branches (comma-separated) | --- @@ -108,6 +125,7 @@ Post deployment status to GitHub pull requests. | `VORTEX_NOTIFY_GITHUB_TOKEN` | **Yes** | | Hosting | GitHub personal access token | | `VORTEX_NOTIFY_GITHUB_REPOSITORY` | **Yes** | | Hosting | Repository in `owner/repo` format | | `VORTEX_NOTIFY_GITHUB_ENVIRONMENT_TYPE` | No | `${VORTEX_NOTIFY_LABEL}` | `.env` | Environment name (defaults to label, e.g. `PR-123`) | +| `VORTEX_NOTIFY_GITHUB_BRANCHES` | No | | `.env` | Restrict to specific branches (comma-separated) | ### Example @@ -139,6 +157,7 @@ Post a deployment comment and optionally update issue status and assignee. | `VORTEX_NOTIFY_JIRA_ASSIGNEE_EMAIL` | No | | `.env` | Assignee email after deployment | | `VORTEX_NOTIFY_JIRA_TRANSITION` | No | | `.env` | Transition name (e.g., "In Review") | | `VORTEX_NOTIFY_JIRA_ENDPOINT` | No | `https://jira.atlassian.com` | `.env` | JIRA API endpoint | +| `VORTEX_NOTIFY_JIRA_BRANCHES` | No | | `.env` | Restrict to specific branches (comma-separated) | ### Issue key extraction @@ -183,6 +202,7 @@ in development or feature branch environments. | `VORTEX_NOTIFY_NEWRELIC_CHANGELOG` | No | Description | `.env` | Deployment changelog | | `VORTEX_NOTIFY_NEWRELIC_USER` | No | `Deployment robot` | `.env` | User performing deployment | | `VORTEX_NOTIFY_NEWRELIC_ENDPOINT` | No | `https://api.newrelic.com/v2` | `.env` | API endpoint | +| `VORTEX_NOTIFY_NEWRELIC_BRANCHES` | No | `main,master` | `.env` | Restrict to specific branches (comma-separated) | ### Example @@ -209,6 +229,7 @@ Post deployment notifications to a Slack channel. | `VORTEX_NOTIFY_SLACK_CHANNEL` | No | | `.env` | Target channel (overrides webhook default) | | `VORTEX_NOTIFY_SLACK_USERNAME` | No | `Deployment Bot` | `.env` | Bot display name | | `VORTEX_NOTIFY_SLACK_ICON_EMOJI` | No | `:rocket:` | `.env` | Bot icon emoji | +| `VORTEX_NOTIFY_SLACK_BRANCHES` | No | | `.env` | Restrict to specific branches (comma-separated) | ### Event behavior @@ -240,6 +261,7 @@ Send HTTP requests to arbitrary webhook URLs. | `VORTEX_NOTIFY_WEBHOOK_HEADERS` | No | `Content-Type: application/json` | `.env` | Pipe-separated headers | | `VORTEX_NOTIFY_WEBHOOK_PAYLOAD` | No | Default template | `.env` | JSON payload | | `VORTEX_NOTIFY_WEBHOOK_RESPONSE_STATUS` | No | `200` | `.env` | Expected HTTP status | +| `VORTEX_NOTIFY_WEBHOOK_BRANCHES` | No | | `.env` | Restrict to specific branches (comma-separated) | ### Default payload template diff --git a/.vortex/docs/content/development/variables.mdx b/.vortex/docs/content/development/variables.mdx index 105c36341..a8b242b4e 100644 --- a/.vortex/docs/content/development/variables.mdx +++ b/.vortex/docs/content/development/variables.mdx @@ -314,8 +314,8 @@ The list below is automatically generated with [Shellvar](https://github.com/ale | `VORTEX_LOGIN_CONTAINER_REGISTRY_USER` | The username to login into the container registry.

If not provided, the script will skip the login step. | `${VORTEX_CONTAINER_REGISTRY_USER}` | `scripts/vortex/login-container-registry.sh` | | `VORTEX_LOGIN_UNBLOCK_ADMIN` | Flag to unblock admin. | `1` | `scripts/vortex/login.sh` | | `VORTEX_LOGOUT_BLOCK_ADMIN` | Flag to block or unblock admin. | `1` | `scripts/vortex/logout.sh` | -| `VORTEX_NOTIFY_BRANCH` | Notification git branch name. | `UNDEFINED` | `scripts/vortex/notify.sh` | | `VORTEX_NOTIFY_CHANNELS` | The channels of the notifications.

A combination of comma-separated values: email,slack,newrelic,github,jira,webhook | `email` | `.env`, `scripts/vortex/notify.sh` | +| `VORTEX_NOTIFY_EMAIL_BRANCHES` | Email notification branch filter.

Comma-separated list of branch names. When set, email notifications are only sent for deployments on the listed branches. When empty, no filtering is applied. | `UNDEFINED` | `scripts/vortex/notify-email.sh` | | `VORTEX_NOTIFY_EMAIL_ENVIRONMENT_URL` | Email notification environment URL. | `${VORTEX_NOTIFY_ENVIRONMENT_URL}` | `scripts/vortex/notify-email.sh` | | `VORTEX_NOTIFY_EMAIL_EVENT` | Email notification event type. Can be 'pre_deployment' or 'post_deployment'. | `post_deployment` | `scripts/vortex/notify-email.sh` | | `VORTEX_NOTIFY_EMAIL_FROM` | An email address to send notifications from.

Applies to email notifications. | `webmaster@your-site-domain.example` | `.env`, `scripts/vortex/notify-email.sh` | @@ -327,6 +327,7 @@ The list below is automatically generated with [Shellvar](https://github.com/ale | `VORTEX_NOTIFY_ENVIRONMENT_URL` | Notification environment URL (where the site was deployed). | `UNDEFINED` | `scripts/vortex/notify.sh` | | `VORTEX_NOTIFY_EVENT` | Notification event type.

Can be 'pre_deployment' or 'post_deployment'. | `post_deployment` | `scripts/vortex/notify.sh` | | `VORTEX_NOTIFY_GITHUB_BRANCH` | GitHub notification git branch name. This will be used as the 'ref' parameter in GitHub's Deployment API. | `${VORTEX_NOTIFY_BRANCH}` | `scripts/vortex/notify-github.sh` | +| `VORTEX_NOTIFY_GITHUB_BRANCHES` | GitHub notification branch filter.

Comma-separated list of branch names. When set, GitHub notifications are only sent for deployments on the listed branches. When empty, no filtering is applied. | `UNDEFINED` | `scripts/vortex/notify-github.sh` | | `VORTEX_NOTIFY_GITHUB_ENVIRONMENT_TYPE` | GitHub notification environment type. Used as the 'environment' parameter in GitHub's Deployment API. Defaults to VORTEX_NOTIFY_LABEL (e.g. "PR-`123`" or branch name) for unique per-PR/branch environments. This prevents cross-PR deployment interference where deploying one PR would mark another PR's deployment as inactive. | `PR` | `scripts/vortex/notify-github.sh` | | `VORTEX_NOTIFY_GITHUB_ENVIRONMENT_URL` | GitHub notification deployment environment URL. | `${VORTEX_NOTIFY_ENVIRONMENT_URL}` | `scripts/vortex/notify-github.sh` | | `VORTEX_NOTIFY_GITHUB_EVENT` | GitHub notification event type. Can be 'pre_deployment' or 'post_deployment'. | `${VORTEX_NOTIFY_EVENT}` | `scripts/vortex/notify-github.sh` | @@ -334,6 +335,7 @@ The list below is automatically generated with [Shellvar](https://github.com/ale | `VORTEX_NOTIFY_GITHUB_TOKEN` | GitHub notification personal access token. | `${GITHUB_TOKEN}` | `scripts/vortex/notify-github.sh`, `ACQUIA ENVIRONMENT`, `LAGOON ENVIRONMENT` | | `VORTEX_NOTIFY_JIRA_ASSIGNEE_EMAIL` | JIRA notification assignee email address.

If left empty - no assignment will be performed. | `UNDEFINED` | `scripts/vortex/notify-jira.sh` | | `VORTEX_NOTIFY_JIRA_BRANCH` | JIRA notification git branch name (used for issue extraction). | `${VORTEX_NOTIFY_BRANCH}` | `scripts/vortex/notify-jira.sh` | +| `VORTEX_NOTIFY_JIRA_BRANCHES` | JIRA notification branch filter.

Comma-separated list of branch names. When set, JIRA notifications are only sent for deployments on the listed branches. When empty, no filtering is applied. | `UNDEFINED` | `scripts/vortex/notify-jira.sh` | | `VORTEX_NOTIFY_JIRA_ENDPOINT` | JIRA notification API endpoint. | `https://jira.atlassian.com` | `scripts/vortex/notify-jira.sh` | | `VORTEX_NOTIFY_JIRA_ENVIRONMENT_URL` | JIRA notification environment URL. | `${VORTEX_NOTIFY_ENVIRONMENT_URL}` | `scripts/vortex/notify-jira.sh` | | `VORTEX_NOTIFY_JIRA_EVENT` | JIRA notification event type. Can be 'pre_deployment' or 'post_deployment'. | `post_deployment` | `scripts/vortex/notify-jira.sh` | @@ -349,6 +351,7 @@ The list below is automatically generated with [Shellvar](https://github.com/ale | `VORTEX_NOTIFY_NEWRELIC_APIKEY` | NewRelic API key, usually of type 'USER'.

@see https://www.vortextemplate.com/docs/deployment/notifications#new-relic | `UNDEFINED` | `ACQUIA ENVIRONMENT`, `LAGOON ENVIRONMENT` | | `VORTEX_NOTIFY_NEWRELIC_APPID` | New Relic notification application ID (auto-discovered if not provided).

Will be discovered automatically from application name if not provided. | `UNDEFINED` | `scripts/vortex/notify-newrelic.sh` | | `VORTEX_NOTIFY_NEWRELIC_APP_NAME` | New Relic notification application name as it appears in the dashboard. | `${VORTEX_NOTIFY_NEWRELIC_PROJECT}-${VORTEX_NOTIFY_NEWRELIC_LABEL}` | `scripts/vortex/notify-newrelic.sh` | +| `VORTEX_NOTIFY_NEWRELIC_BRANCHES` | New Relic notification branch filter.

Comma-separated list of branch names. When set, New Relic notifications are only sent for deployments on the listed branches. When empty, no filtering is applied. | `main,master` | `scripts/vortex/notify-newrelic.sh` | | `VORTEX_NOTIFY_NEWRELIC_CHANGELOG` | New Relic notification deployment changelog. Defaults to the description. | `UNDEFINED` | `scripts/vortex/notify-newrelic.sh` | | `VORTEX_NOTIFY_NEWRELIC_DESCRIPTION` | New Relic notification deployment description template. Available tokens: %project%, %label%, %timestamp%, %environment_url%, %login_url% | `UNDEFINED` | `scripts/vortex/notify-newrelic.sh` | | `VORTEX_NOTIFY_NEWRELIC_ENABLED` | Flag to enable New Relic notifications. Set to "true" (not "`1`") in environments where New Relic is configured. | `${NEWRELIC_ENABLED}` | `scripts/vortex/notify-newrelic.sh` | @@ -366,6 +369,7 @@ The list below is automatically generated with [Shellvar](https://github.com/ale | `VORTEX_NOTIFY_PR_NUMBER` | Notification pull request number. | `UNDEFINED` | `scripts/vortex/notify.sh` | | `VORTEX_NOTIFY_SHA` | Notification git commit SHA. | `UNDEFINED` | `scripts/vortex/notify.sh` | | `VORTEX_NOTIFY_SKIP` | Notification skip flag. | `UNDEFINED` | `scripts/vortex/notify.sh` | +| `VORTEX_NOTIFY_SLACK_BRANCHES` | Slack notification branch filter.

Comma-separated list of branch names. When set, Slack notifications are only sent for deployments on the listed branches. When empty, no filtering is applied. | `UNDEFINED` | `scripts/vortex/notify-slack.sh` | | `VORTEX_NOTIFY_SLACK_CHANNEL` | Slack notification target channel (optional, overrides webhook default). Format: #channel-name or @username | `UNDEFINED` | `scripts/vortex/notify-slack.sh` | | `VORTEX_NOTIFY_SLACK_ENVIRONMENT_URL` | Slack notification environment URL. | `${VORTEX_NOTIFY_ENVIRONMENT_URL}` | `scripts/vortex/notify-slack.sh` | | `VORTEX_NOTIFY_SLACK_EVENT` | Slack notification event type. Can be 'pre_deployment' or 'post_deployment'. | `post_deployment` | `scripts/vortex/notify-slack.sh` | @@ -376,6 +380,7 @@ The list below is automatically generated with [Shellvar](https://github.com/ale | `VORTEX_NOTIFY_SLACK_PROJECT` | Slack notification project name. | `${VORTEX_NOTIFY_PROJECT}` | `scripts/vortex/notify-slack.sh` | | `VORTEX_NOTIFY_SLACK_USERNAME` | Slack notification bot display name (optional). | `Deployment Bot` | `scripts/vortex/notify-slack.sh` | | `VORTEX_NOTIFY_SLACK_WEBHOOK` | Slack notification webhook URL. The incoming Webhook URL from your Slack app configuration. @see https://www.vortextemplate.com/docs/deployment/notifications#slack | `UNDEFINED` | `scripts/vortex/notify-slack.sh`, `ACQUIA ENVIRONMENT`, `LAGOON ENVIRONMENT` | +| `VORTEX_NOTIFY_WEBHOOK_BRANCHES` | Webhook notification branch filter.

Comma-separated list of branch names. When set, webhook notifications are only sent for deployments on the listed branches. When empty, no filtering is applied. | `UNDEFINED` | `scripts/vortex/notify-webhook.sh` | | `VORTEX_NOTIFY_WEBHOOK_ENVIRONMENT_URL` | Webhook notification environment URL. | `${VORTEX_NOTIFY_ENVIRONMENT_URL}` | `scripts/vortex/notify-webhook.sh` | | `VORTEX_NOTIFY_WEBHOOK_EVENT` | Webhook notification event type. Can be 'pre_deployment' or 'post_deployment'. | `post_deployment` | `scripts/vortex/notify-webhook.sh` | | `VORTEX_NOTIFY_WEBHOOK_HEADERS` | Webhook notification pipe-separated headers. Separate multiple headers with a pipe `|`. Example: `Content-type: application/json|Authorization: Bearer API_KEY`. | `Content-type: application/json` | `scripts/vortex/notify-webhook.sh` | diff --git a/.vortex/tests/bats/unit/notify-email.bats b/.vortex/tests/bats/unit/notify-email.bats index 858c68e1c..8deca5260 100644 --- a/.vortex/tests/bats/unit/notify-email.bats +++ b/.vortex/tests/bats/unit/notify-email.bats @@ -89,6 +89,30 @@ load ../_helper.bash popd >/dev/null || exit 1 } +@test "Notify: email, branch filter skip" { + pushd "${LOCAL_REPO_DIR}" >/dev/null || exit 1 + + export VORTEX_NOTIFY_CHANNELS="email" + export VORTEX_NOTIFY_PROJECT="testproject" + export DRUPAL_SITE_EMAIL="testproject@example.com" + export VORTEX_NOTIFY_EMAIL_RECIPIENTS="john@example.com" + export VORTEX_NOTIFY_BRANCH="feature/test" + export VORTEX_NOTIFY_SHA="abc123def456" + export VORTEX_NOTIFY_LABEL="feature/test" + export VORTEX_NOTIFY_ENVIRONMENT_URL="https://develop.testproject.com" + export VORTEX_NOTIFY_EMAIL_BRANCHES="main,develop" + + run ./scripts/vortex/notify.sh + assert_success + + assert_output_contains "Started dispatching notifications." + assert_output_contains "Skipping email notification for branch 'feature/test'." + assert_output_not_contains "Started email notification." + assert_output_contains "Finished dispatching notifications." + + popd >/dev/null || exit 1 +} + @test "Notify: email, shell injection protection" { pushd "${LOCAL_REPO_DIR}" >/dev/null || exit 1 diff --git a/.vortex/tests/bats/unit/notify-github.bats b/.vortex/tests/bats/unit/notify-github.bats index bad58acd2..439c76af2 100644 --- a/.vortex/tests/bats/unit/notify-github.bats +++ b/.vortex/tests/bats/unit/notify-github.bats @@ -230,6 +230,30 @@ load ../_helper.bash popd >/dev/null || exit 1 } +@test "Notify: github, branch filter skip" { + pushd "${LOCAL_REPO_DIR}" >/dev/null || exit 1 + + export VORTEX_NOTIFY_CHANNELS="github" + export VORTEX_NOTIFY_EVENT="pre_deployment" + export VORTEX_NOTIFY_GITHUB_TOKEN="token12345" + export VORTEX_NOTIFY_GITHUB_REPOSITORY="myorg/myrepo" + export VORTEX_NOTIFY_BRANCH="feature/test" + export VORTEX_NOTIFY_SHA="abc123def456" + export VORTEX_NOTIFY_LABEL="feature/test" + export VORTEX_NOTIFY_ENVIRONMENT_URL="https://develop.testproject.com" + export VORTEX_NOTIFY_GITHUB_BRANCHES="main,develop" + + run ./scripts/vortex/notify.sh + assert_success + + assert_output_contains "Started dispatching notifications." + assert_output_contains "Skipping GitHub notification for branch 'feature/test'." + assert_output_not_contains "Started GitHub notification" + assert_output_contains "Finished dispatching notifications." + + popd >/dev/null || exit 1 +} + @test "Notify: github, post_deployment, failure to set status" { pushd "${LOCAL_REPO_DIR}" >/dev/null || exit 1 diff --git a/.vortex/tests/bats/unit/notify-jira.bats b/.vortex/tests/bats/unit/notify-jira.bats index e0ad142e9..b56da2763 100644 --- a/.vortex/tests/bats/unit/notify-jira.bats +++ b/.vortex/tests/bats/unit/notify-jira.bats @@ -82,6 +82,30 @@ load ../_helper.bash popd >/dev/null || exit 1 } +@test "Notify: jira, branch filter skip" { + pushd "${LOCAL_REPO_DIR}" >/dev/null || exit 1 + + export VORTEX_NOTIFY_CHANNELS="jira" + export VORTEX_NOTIFY_JIRA_USER_EMAIL="john.doe@example.com" + export VORTEX_NOTIFY_JIRA_TOKEN="token12345" + export VORTEX_NOTIFY_JIRA_PROJECT="PROJ" + export VORTEX_NOTIFY_BRANCH="feature/proj-1234-test" + export VORTEX_NOTIFY_SHA="abc123def456" + export VORTEX_NOTIFY_LABEL="feature/proj-1234-test" + export VORTEX_NOTIFY_ENVIRONMENT_URL="https://develop.testproject.com" + export VORTEX_NOTIFY_JIRA_BRANCHES="main,develop" + + run ./scripts/vortex/notify.sh + assert_success + + assert_output_contains "Started dispatching notifications." + assert_output_contains "Skipping JIRA notification for branch 'feature/proj-1234-test'." + assert_output_not_contains "Started JIRA notification." + assert_output_contains "Finished dispatching notifications." + + popd >/dev/null || exit 1 +} + @test "Notify: jira, shell injection protection" { pushd "${LOCAL_REPO_DIR}" >/dev/null || exit 1 diff --git a/.vortex/tests/bats/unit/notify-newrelic.bats b/.vortex/tests/bats/unit/notify-newrelic.bats index cd69735d0..c86a49e6c 100644 --- a/.vortex/tests/bats/unit/notify-newrelic.bats +++ b/.vortex/tests/bats/unit/notify-newrelic.bats @@ -12,9 +12,9 @@ load ../_helper.bash export VORTEX_NOTIFY_CHANNELS="newrelic" export VORTEX_NOTIFY_PROJECT="testproject" export VORTEX_NOTIFY_NEWRELIC_USER_KEY="key1234" - export VORTEX_NOTIFY_BRANCH="develop" + export VORTEX_NOTIFY_BRANCH="main" export VORTEX_NOTIFY_SHA="abc123def456" - export VORTEX_NOTIFY_LABEL="develop" + export VORTEX_NOTIFY_LABEL="main" export VORTEX_NOTIFY_ENVIRONMENT_URL="https://test.example.com" # VORTEX_NOTIFY_NEWRELIC_ENABLED is intentionally not set @@ -36,7 +36,7 @@ load ../_helper.bash app_id="9876543210" mock_curl=$(mock_command "curl") - mock_set_output "${mock_curl}" "{\"applications\": [{\"id\": ${app_id}, \"name\": \"testproject-develop\"}]}" 1 + mock_set_output "${mock_curl}" "{\"applications\": [{\"id\": ${app_id}, \"name\": \"testproject-main\"}]}" 1 mock_set_output "${mock_curl}" "201" 2 export VORTEX_NOTIFY_CHANNELS="newrelic" @@ -44,9 +44,9 @@ load ../_helper.bash export VORTEX_NOTIFY_PROJECT="testproject" export VORTEX_NOTIFY_NEWRELIC_USER_KEY="key1234" export VORTEX_NOTIFY_EMAIL_RECIPIENTS="john@example.com|John Doe,jane@example.com|Jane Doe" - export VORTEX_NOTIFY_BRANCH="develop" + export VORTEX_NOTIFY_BRANCH="main" export VORTEX_NOTIFY_SHA="abc123def456" - export VORTEX_NOTIFY_LABEL="develop" + export VORTEX_NOTIFY_LABEL="main" export VORTEX_NOTIFY_ENVIRONMENT_URL="https://test.example.com" run ./scripts/vortex/notify.sh @@ -57,9 +57,9 @@ load ../_helper.bash assert_output_contains "Started New Relic notification." assert_output_contains "Discovering APP id by name if it was not provided." assert_output_contains "Checking if the application ID is valid." - assert_output_contains "Creating a deployment notification for application testproject-develop with ID 9876543210." + assert_output_contains "Creating a deployment notification for application testproject-main with ID 9876543210." - assert_equal "-s -X GET https://api.newrelic.com/v2/applications.json -H Api-Key: key1234 -s -G -d filter[name]=testproject-develop&exclude_links=true" "$(mock_get_call_args "${mock_curl}" 1)" + assert_equal "-s -X GET https://api.newrelic.com/v2/applications.json -H Api-Key: key1234 -s -G -d filter[name]=testproject-main&exclude_links=true" "$(mock_get_call_args "${mock_curl}" 1)" # Extract revision from actual curl call (since it's auto-generated with timestamp) actual_curl_call="$(mock_get_call_args "${mock_curl}" 2)" @@ -86,9 +86,9 @@ load ../_helper.bash export VORTEX_NOTIFY_EVENT="pre_deployment" export VORTEX_NOTIFY_PROJECT="testproject" export VORTEX_NOTIFY_NEWRELIC_USER_KEY="key1234" - export VORTEX_NOTIFY_BRANCH="develop" + export VORTEX_NOTIFY_BRANCH="main" export VORTEX_NOTIFY_SHA="abc123def456" - export VORTEX_NOTIFY_LABEL="develop" + export VORTEX_NOTIFY_LABEL="main" export VORTEX_NOTIFY_ENVIRONMENT_URL="https://test.example.com" run ./scripts/vortex/notify.sh assert_success @@ -102,13 +102,67 @@ load ../_helper.bash popd >/dev/null || exit 1 } +@test "Notify: newrelic, branch filter default skip" { + pushd "${LOCAL_REPO_DIR}" >/dev/null || exit 1 + + export VORTEX_NOTIFY_CHANNELS="newrelic" + export VORTEX_NOTIFY_NEWRELIC_ENABLED=true + export VORTEX_NOTIFY_PROJECT="testproject" + export VORTEX_NOTIFY_NEWRELIC_USER_KEY="key1234" + export VORTEX_NOTIFY_BRANCH="develop" + export VORTEX_NOTIFY_SHA="abc123def456" + export VORTEX_NOTIFY_LABEL="develop" + export VORTEX_NOTIFY_ENVIRONMENT_URL="https://test.example.com" + # VORTEX_NOTIFY_NEWRELIC_BRANCHES defaults to "main,master" + + run ./scripts/vortex/notify.sh + assert_success + + assert_output_contains "Started dispatching notifications." + assert_output_contains "Skipping New Relic notification for branch 'develop'." + assert_output_not_contains "Started New Relic notification." + assert_output_contains "Finished dispatching notifications." + + popd >/dev/null || exit 1 +} + +@test "Notify: newrelic, branch filter custom" { + pushd "${LOCAL_REPO_DIR}" >/dev/null || exit 1 + + app_id="9876543210" + mock_curl=$(mock_command "curl") + + mock_set_output "${mock_curl}" "{\"applications\": [{\"id\": ${app_id}, \"name\": \"testproject-staging\"}]}" 1 + mock_set_output "${mock_curl}" "201" 2 + + export VORTEX_NOTIFY_CHANNELS="newrelic" + export VORTEX_NOTIFY_NEWRELIC_ENABLED=true + export VORTEX_NOTIFY_PROJECT="testproject" + export VORTEX_NOTIFY_NEWRELIC_USER_KEY="key1234" + export VORTEX_NOTIFY_BRANCH="staging" + export VORTEX_NOTIFY_SHA="abc123def456" + export VORTEX_NOTIFY_LABEL="staging" + export VORTEX_NOTIFY_ENVIRONMENT_URL="https://test.example.com" + export VORTEX_NOTIFY_NEWRELIC_BRANCHES="main,staging" + + run ./scripts/vortex/notify.sh + assert_success + + assert_output_contains "Started dispatching notifications." + assert_output_contains "Started New Relic notification." + assert_output_not_contains "Skipping New Relic notification for branch" + assert_output_contains "Finished dispatching notifications." + + popd >/dev/null || exit 1 +} + @test "Notify: newrelic, shell injection protection" { pushd "${LOCAL_REPO_DIR}" >/dev/null || exit 1 app_id="9876543210" mock_curl=$(mock_command "curl") - mock_set_output "${mock_curl}" "{\"applications\": [{\"id\": ${app_id}, \"name\": \"test-develop\"}]}" 1 + mock_set_output "${mock_curl}" "{\"applications\": [{\"id\": ${app_id}, \"name\": \"test-main\"}]}" 1 mock_set_output "${mock_curl}" "201" 2 # Attempt shell injection through project name with PHP code that would create a file @@ -116,9 +170,9 @@ load ../_helper.bash export VORTEX_NOTIFY_NEWRELIC_ENABLED=true export VORTEX_NOTIFY_PROJECT="test'); file_put_contents('/tmp/injected_newrelic_test', 'HACKED'); //" export VORTEX_NOTIFY_NEWRELIC_USER_KEY="key1234" - export VORTEX_NOTIFY_BRANCH="develop" + export VORTEX_NOTIFY_BRANCH="main" export VORTEX_NOTIFY_SHA="abc123def456" - export VORTEX_NOTIFY_LABEL="develop" + export VORTEX_NOTIFY_LABEL="main" export VORTEX_NOTIFY_ENVIRONMENT_URL="https://test.example.com" # Ensure test file doesn't exist before diff --git a/.vortex/tests/bats/unit/notify-slack.bats b/.vortex/tests/bats/unit/notify-slack.bats index 7a58dfa01..986a15a3c 100644 --- a/.vortex/tests/bats/unit/notify-slack.bats +++ b/.vortex/tests/bats/unit/notify-slack.bats @@ -272,6 +272,29 @@ load ../_helper.bash popd >/dev/null || exit 1 } +@test "Notify: slack, branch filter skip" { + pushd "${LOCAL_REPO_DIR}" >/dev/null || exit 1 + + export VORTEX_NOTIFY_CHANNELS="slack" + export VORTEX_NOTIFY_PROJECT="testproject" + export VORTEX_NOTIFY_BRANCH="feature/test" + export VORTEX_NOTIFY_SHA="abc123def456" + export VORTEX_NOTIFY_LABEL="feature/test" + export VORTEX_NOTIFY_ENVIRONMENT_URL="https://develop.testproject.com" + export VORTEX_NOTIFY_SLACK_WEBHOOK="https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXX" + export VORTEX_NOTIFY_SLACK_BRANCHES="main,develop" + + run ./scripts/vortex/notify.sh + assert_success + + assert_output_contains "Started dispatching notifications." + assert_output_contains "Skipping Slack notification for branch 'feature/test'." + assert_output_not_contains "Started Slack notification." + assert_output_contains "Finished dispatching notifications." + + popd >/dev/null || exit 1 +} + @test "Notify: slack, shell injection protection" { pushd "${LOCAL_REPO_DIR}" >/dev/null || exit 1 diff --git a/.vortex/tests/bats/unit/notify-webhook.bats b/.vortex/tests/bats/unit/notify-webhook.bats index e166b7da6..f7591d763 100644 --- a/.vortex/tests/bats/unit/notify-webhook.bats +++ b/.vortex/tests/bats/unit/notify-webhook.bats @@ -87,6 +87,31 @@ load ../_helper.bash popd >/dev/null || exit 1 } +@test "Notify: webhook, branch filter skip" { + pushd "${LOCAL_REPO_DIR}" >/dev/null || exit 1 + + export VORTEX_NOTIFY_CHANNELS="webhook" + export VORTEX_NOTIFY_PROJECT="testproject" + export VORTEX_NOTIFY_BRANCH="feature/test" + export VORTEX_NOTIFY_SHA="abc123def456" + export VORTEX_NOTIFY_LABEL="feature/test" + export VORTEX_NOTIFY_ENVIRONMENT_URL="https://develop.testproject.com" + export VORTEX_NOTIFY_WEBHOOK_URL="https://example-webhook-url.com" + export VORTEX_NOTIFY_WEBHOOK_METHOD="POST" + export VORTEX_NOTIFY_WEBHOOK_HEADERS="Content-type: application/json" + export VORTEX_NOTIFY_WEBHOOK_BRANCHES="main,develop" + + run ./scripts/vortex/notify.sh + assert_success + + assert_output_contains "Started dispatching notifications." + assert_output_contains "Skipping Webhook notification for branch 'feature/test'." + assert_output_not_contains "Started Webhook notification." + assert_output_contains "Finished dispatching notifications." + + popd >/dev/null || exit 1 +} + @test "Notify: webhook, shell injection protection" { pushd "${LOCAL_REPO_DIR}" >/dev/null || exit 1 diff --git a/.vortex/tests/bats/unit/notify.bats b/.vortex/tests/bats/unit/notify.bats index 689c59cb1..060829838 100644 --- a/.vortex/tests/bats/unit/notify.bats +++ b/.vortex/tests/bats/unit/notify.bats @@ -58,9 +58,9 @@ load ../_helper.bash export VORTEX_NOTIFY_CHANNELS="email,slack,github,newrelic,webhook,jira" export VORTEX_NOTIFY_EVENT="pre_deployment" export VORTEX_NOTIFY_PROJECT="testproject" - export VORTEX_NOTIFY_BRANCH="develop" + export VORTEX_NOTIFY_BRANCH="main" export VORTEX_NOTIFY_SHA="abc123def456" - export VORTEX_NOTIFY_LABEL="develop" + export VORTEX_NOTIFY_LABEL="main" export VORTEX_NOTIFY_ENVIRONMENT_URL="https://test.example.com" # Email required variables diff --git a/scripts/vortex/notify-email.sh b/scripts/vortex/notify-email.sh index f749d5788..7abe90fd5 100755 --- a/scripts/vortex/notify-email.sh +++ b/scripts/vortex/notify-email.sh @@ -48,6 +48,13 @@ VORTEX_NOTIFY_EMAIL_MESSAGE="${VORTEX_NOTIFY_EMAIL_MESSAGE:-}" # Email notification event type. Can be 'pre_deployment' or 'post_deployment'. VORTEX_NOTIFY_EMAIL_EVENT="${VORTEX_NOTIFY_EMAIL_EVENT:-${VORTEX_NOTIFY_EVENT:-post_deployment}}" +# Email notification branch filter. +# +# Comma-separated list of branch names. When set, email notifications +# are only sent for deployments on the listed branches. When empty, no +# filtering is applied. +VORTEX_NOTIFY_EMAIL_BRANCHES="${VORTEX_NOTIFY_EMAIL_BRANCHES:-}" + #------------------------------------------------------------------------------- # @formatter:off @@ -58,6 +65,13 @@ pass() { [ "${TERM:-}" != "dumb" ] && tput colors >/dev/null 2>&1 && printf "\03 fail() { [ "${TERM:-}" != "dumb" ] && tput colors >/dev/null 2>&1 && printf "\033[31m[FAIL] %s\033[0m\n" "${1}" || printf "[FAIL] %s\n" "${1}"; } # @formatter:on +if [ -n "${VORTEX_NOTIFY_EMAIL_BRANCHES}" ]; then + if ! echo ",${VORTEX_NOTIFY_EMAIL_BRANCHES}," | grep -qF ",${VORTEX_NOTIFY_BRANCH},"; then + pass "Skipping email notification for branch '${VORTEX_NOTIFY_BRANCH}'." + exit 0 + fi +fi + [ -z "${VORTEX_NOTIFY_EMAIL_PROJECT}" ] && fail "Missing required value for VORTEX_NOTIFY_EMAIL_PROJECT." && exit 1 [ -z "${VORTEX_NOTIFY_EMAIL_FROM}" ] && fail "Missing required value for VORTEX_NOTIFY_EMAIL_FROM." && exit 1 [ -z "${VORTEX_NOTIFY_EMAIL_RECIPIENTS}" ] && fail "Missing required value for VORTEX_NOTIFY_EMAIL_RECIPIENTS." && exit 1 diff --git a/scripts/vortex/notify-github.sh b/scripts/vortex/notify-github.sh index 1c20192fe..9d39c9e9e 100755 --- a/scripts/vortex/notify-github.sh +++ b/scripts/vortex/notify-github.sh @@ -39,6 +39,13 @@ VORTEX_NOTIFY_GITHUB_ENVIRONMENT_URL="${VORTEX_NOTIFY_GITHUB_ENVIRONMENT_URL:-${ # where deploying one PR would mark another PR's deployment as inactive. VORTEX_NOTIFY_GITHUB_ENVIRONMENT_TYPE="${VORTEX_NOTIFY_GITHUB_ENVIRONMENT_TYPE:-${VORTEX_NOTIFY_LABEL:-PR}}" +# GitHub notification branch filter. +# +# Comma-separated list of branch names. When set, GitHub notifications +# are only sent for deployments on the listed branches. When empty, no +# filtering is applied. +VORTEX_NOTIFY_GITHUB_BRANCHES="${VORTEX_NOTIFY_GITHUB_BRANCHES:-}" + # ------------------------------------------------------------------------------ # @formatter:off @@ -54,6 +61,13 @@ for cmd in php curl; do command -v "${cmd}" >/dev/null || { exit 1 }; done +if [ -n "${VORTEX_NOTIFY_GITHUB_BRANCHES}" ]; then + if ! echo ",${VORTEX_NOTIFY_GITHUB_BRANCHES}," | grep -qF ",${VORTEX_NOTIFY_BRANCH},"; then + pass "Skipping GitHub notification for branch '${VORTEX_NOTIFY_BRANCH}'." + exit 0 + fi +fi + [ -z "${VORTEX_NOTIFY_GITHUB_TOKEN}" ] && fail "Missing required value for VORTEX_NOTIFY_GITHUB_TOKEN" && exit 1 [ -z "${VORTEX_NOTIFY_GITHUB_REPOSITORY}" ] && fail "Missing required value for VORTEX_NOTIFY_GITHUB_REPOSITORY" && exit 1 [ -z "${VORTEX_NOTIFY_GITHUB_BRANCH}" ] && fail "Missing required value for VORTEX_NOTIFY_GITHUB_BRANCH" && exit 1 diff --git a/scripts/vortex/notify-jira.sh b/scripts/vortex/notify-jira.sh index 6baa80a6b..0a513c79e 100755 --- a/scripts/vortex/notify-jira.sh +++ b/scripts/vortex/notify-jira.sh @@ -59,6 +59,13 @@ VORTEX_NOTIFY_JIRA_ASSIGNEE_EMAIL="${VORTEX_NOTIFY_JIRA_ASSIGNEE_EMAIL:-}" # JIRA notification API endpoint. VORTEX_NOTIFY_JIRA_ENDPOINT="${VORTEX_NOTIFY_JIRA_ENDPOINT:-https://jira.atlassian.com}" +# JIRA notification branch filter. +# +# Comma-separated list of branch names. When set, JIRA notifications +# are only sent for deployments on the listed branches. When empty, no +# filtering is applied. +VORTEX_NOTIFY_JIRA_BRANCHES="${VORTEX_NOTIFY_JIRA_BRANCHES:-}" + # ------------------------------------------------------------------------------ # @formatter:off @@ -74,6 +81,13 @@ for cmd in php curl; do command -v "${cmd}" >/dev/null || { exit 1 }; done +if [ -n "${VORTEX_NOTIFY_JIRA_BRANCHES}" ]; then + if ! echo ",${VORTEX_NOTIFY_JIRA_BRANCHES}," | grep -qF ",${VORTEX_NOTIFY_BRANCH},"; then + pass "Skipping JIRA notification for branch '${VORTEX_NOTIFY_BRANCH}'." + exit 0 + fi +fi + [ -z "${VORTEX_NOTIFY_JIRA_USER_EMAIL}" ] && fail "Missing required value for VORTEX_NOTIFY_JIRA_USER_EMAIL" && exit 1 [ -z "${VORTEX_NOTIFY_JIRA_TOKEN}" ] && fail "Missing required value for VORTEX_NOTIFY_JIRA_TOKEN" && exit 1 [ -z "${VORTEX_NOTIFY_JIRA_LABEL}" ] && fail "Missing required value for VORTEX_NOTIFY_JIRA_LABEL" && exit 1 diff --git a/scripts/vortex/notify-newrelic.sh b/scripts/vortex/notify-newrelic.sh index ed7682b9e..8762ee3fd 100755 --- a/scripts/vortex/notify-newrelic.sh +++ b/scripts/vortex/notify-newrelic.sh @@ -70,6 +70,13 @@ VORTEX_NOTIFY_NEWRELIC_ENDPOINT="${VORTEX_NOTIFY_NEWRELIC_ENDPOINT:-https://api. # New Relic notification event type. Can be 'pre_deployment' or 'post_deployment'. VORTEX_NOTIFY_NEWRELIC_EVENT="${VORTEX_NOTIFY_NEWRELIC_EVENT:-${VORTEX_NOTIFY_EVENT:-post_deployment}}" +# New Relic notification branch filter. +# +# Comma-separated list of branch names. When set, New Relic notifications +# are only sent for deployments on the listed branches. When empty, no +# filtering is applied. +VORTEX_NOTIFY_NEWRELIC_BRANCHES="${VORTEX_NOTIFY_NEWRELIC_BRANCHES:-main,master}" + # ------------------------------------------------------------------------------ # @formatter:off @@ -85,6 +92,13 @@ if [ -z "${VORTEX_NOTIFY_NEWRELIC_ENABLED}" ]; then exit 0 fi +if [ -n "${VORTEX_NOTIFY_NEWRELIC_BRANCHES}" ]; then + if ! echo ",${VORTEX_NOTIFY_NEWRELIC_BRANCHES}," | grep -qF ",${VORTEX_NOTIFY_BRANCH},"; then + pass "Skipping New Relic notification for branch '${VORTEX_NOTIFY_BRANCH}'." + exit 0 + fi +fi + for cmd in curl; do command -v "${cmd}" >/dev/null || { fail "Command ${cmd} is not available" exit 1 diff --git a/scripts/vortex/notify-slack.sh b/scripts/vortex/notify-slack.sh index 1b0d72e71..197e8a890 100755 --- a/scripts/vortex/notify-slack.sh +++ b/scripts/vortex/notify-slack.sh @@ -45,6 +45,13 @@ VORTEX_NOTIFY_SLACK_USERNAME="${VORTEX_NOTIFY_SLACK_USERNAME:-Deployment Bot}" # Slack notification bot icon emoji (optional). VORTEX_NOTIFY_SLACK_ICON_EMOJI="${VORTEX_NOTIFY_SLACK_ICON_EMOJI:-:rocket:}" +# Slack notification branch filter. +# +# Comma-separated list of branch names. When set, Slack notifications +# are only sent for deployments on the listed branches. When empty, no +# filtering is applied. +VORTEX_NOTIFY_SLACK_BRANCHES="${VORTEX_NOTIFY_SLACK_BRANCHES:-}" + # ------------------------------------------------------------------------------ # @formatter:off @@ -60,6 +67,13 @@ for cmd in php curl; do command -v "${cmd}" >/dev/null || { exit 1 }; done +if [ -n "${VORTEX_NOTIFY_SLACK_BRANCHES}" ]; then + if ! echo ",${VORTEX_NOTIFY_SLACK_BRANCHES}," | grep -qF ",${VORTEX_NOTIFY_BRANCH},"; then + pass "Skipping Slack notification for branch '${VORTEX_NOTIFY_BRANCH}'." + exit 0 + fi +fi + [ -z "${VORTEX_NOTIFY_SLACK_PROJECT}" ] && fail "Missing required value for VORTEX_NOTIFY_SLACK_PROJECT" && exit 1 [ -z "${VORTEX_NOTIFY_SLACK_LABEL}" ] && fail "Missing required value for VORTEX_NOTIFY_SLACK_LABEL" && exit 1 [ -z "${VORTEX_NOTIFY_SLACK_ENVIRONMENT_URL}" ] && fail "Missing required value for VORTEX_NOTIFY_SLACK_ENVIRONMENT_URL" && exit 1 diff --git a/scripts/vortex/notify-webhook.sh b/scripts/vortex/notify-webhook.sh index 9eb830863..192b3eb5c 100755 --- a/scripts/vortex/notify-webhook.sh +++ b/scripts/vortex/notify-webhook.sh @@ -42,6 +42,13 @@ VORTEX_NOTIFY_WEBHOOK_PAYLOAD="${VORTEX_NOTIFY_WEBHOOK_PAYLOAD:-}" # Webhook notification expected HTTP status. VORTEX_NOTIFY_WEBHOOK_RESPONSE_STATUS="${VORTEX_NOTIFY_WEBHOOK_RESPONSE_STATUS:-200}" +# Webhook notification branch filter. +# +# Comma-separated list of branch names. When set, webhook notifications +# are only sent for deployments on the listed branches. When empty, no +# filtering is applied. +VORTEX_NOTIFY_WEBHOOK_BRANCHES="${VORTEX_NOTIFY_WEBHOOK_BRANCHES:-}" + # ------------------------------------------------------------------------------ # @formatter:off @@ -57,6 +64,13 @@ for cmd in php curl; do command -v "${cmd}" >/dev/null || { exit 1 }; done +if [ -n "${VORTEX_NOTIFY_WEBHOOK_BRANCHES}" ]; then + if ! echo ",${VORTEX_NOTIFY_WEBHOOK_BRANCHES}," | grep -qF ",${VORTEX_NOTIFY_BRANCH},"; then + pass "Skipping Webhook notification for branch '${VORTEX_NOTIFY_BRANCH}'." + exit 0 + fi +fi + [ -z "${VORTEX_NOTIFY_WEBHOOK_PROJECT}" ] && fail "Missing required value for VORTEX_NOTIFY_WEBHOOK_PROJECT" && exit 1 [ -z "${VORTEX_NOTIFY_WEBHOOK_LABEL}" ] && fail "Missing required value for VORTEX_NOTIFY_WEBHOOK_LABEL" && exit 1 [ -z "${VORTEX_NOTIFY_WEBHOOK_ENVIRONMENT_URL}" ] && fail "Missing required value for VORTEX_NOTIFY_WEBHOOK_ENVIRONMENT_URL" && exit 1