Repository navigation
Conversation
Projects can list their environments, discard events from environments that are not listed, and choose which environments send notifications. Project settings: a list of named environments (stored casing, Notify toggle, max 100, case-insensitive duplicates rejected), plus DiscardUnlistedEnvironments, DiscardEventsWithoutEnvironment and NotifyOtherEnvironments (default true). Defaults keep today's behavior. Discarding happens in a new pipeline action before stacking and uses the existing IsDiscarded path, so it is counted as discarded usage like stack discards. Rejected names are recorded in the cache per project (first-seen casing, per-day counts, last seen, capped, 7 day expiry) and exposed through the API. Notifications: every channel requires a notifying environment. New notifications use a new Stack.IsNewNotificationPending flag that is claimed atomically in Elasticsearch, so a stack first seen in a non-notifying environment is reported as new the first time it reaches a notifying one. Stacks created before the flag never notify as new. Notification emails and Slack messages mention the environment. Daily summaries are unchanged. New project endpoints manage the list and settings, and the Svelte project settings gain an Environments page. Listed casing is used in the environment filter, event details, event and session tables. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 38228a850a
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Escape client-controlled text in Slack messages. Environment names, project names and the notification type could mention @channel or inject links. Guard against a stale whole-document stack save restoring a claimed notification: a successful Elasticsearch claim also takes a per-stack cache key, so a restored flag is cleared again without notifying twice. The ingestion paths that saved the whole stack (tags and regressions) now patch only the fields they change. Regressions follow the same rule as new stacks. A regression seen only in a non-notifying environment is reported by the first notifying occurrence, and a status change drops anything still pending. Notifying environments behave as before. Names beyond the discarded-environment cap are no longer silently skipped: the page reports how many events came from how many other names. Matching and keys now share one normalization. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Adding an observed environment now pre-fills the add form instead of saving the lowercase aggregation key, so the casing can be confirmed or corrected first. Turning on discarding of unlisted environments asks for confirmation when no environment is listed or none of the listed ones has had recent events. The discarded table reports events from names beyond the tracked limit. The add form uses the generated project environment schema, the filter trigger and event cell titles show the listed casing, and the change-environment messages are named like their siblings. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Key the regression claim guard by regression cycle (the fix date), so a stack that regresses again is never blocked by the previous cycle's claim while the new pending flag is already visible in Elasticsearch. The key is no longer removed after patching. Route every status change through Stack.SetStatus, including the duplicate stack merge in CleanupOrphanedDataJob and FixDuplicateStacks, so merged stacks drop pending notifications too. Add a test that drives AssignToStackAction with a stack another batch claimed after it was loaded, so reverting the tags update to a whole-document save fails. Update tags for several stacks in parallel and document at-most-once delivery when the guard cannot be written. Reword the overflow row of the discarded table so it says what users can actually do. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 03eaf9def5
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Events with an explicit stack id each load their own copy of the stack, so a regression first seen in a non-notifying environment left later production events in the same batch without the pending regression state. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d2fece8372
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
An immediate regression now reserves the same per-cycle key a pending claim takes, so a concurrent batch that marks the regression pending from a non-notifying environment can't send it again. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Put the environment table first, add environments through a dialog like the other project settings pages, move the other-environments notification toggle into the table, replace the discard switches with an "Accept events from" choice, and only show discarded names when they matter. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Cancel button inside the add-environment form defaulted to a submit button, so cancelling added the typed name. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8911758556
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| await test.step('observed environments appear as unlisted rows', async () => { | ||
| await page.goto(`/project/${projectId}/environments`); | ||
|
|
||
| await expect(page.getByRole('button', { name: 'Add Environment' })).toBeVisible(); |
There was a problem hiding this comment.
Add explicit Arrange–Act–Assert sections to the browser journey
The new browser test omits the required explicit // Arrange, // Act, and // Assert sections throughout its scenarios. Named test.step blocks do not satisfy the ClientApp test-structure requirement, and several steps interleave assertions with subsequent actions. Add the required sections within each scenario, repeating them for multi-step interactions where needed.
AGENTS.md reference: src/Exceptionless.Web/ClientApp/AGENTS.md:L27-L27
Useful? React with 👍 / 👎.
|
|
||
| namespace Exceptionless.Tests.Extensions; | ||
|
|
||
| public class ProjectEnvironmentExtensionsTests |
There was a problem hiding this comment.
Inherit the required base for isolated C# tests
This new test class does not inherit a repository test base. Root AGENTS.md explicitly requires TestWithLoggingBase for isolated C# tests; these extension-method tests fit that category. Use the existing ITestOutputHelper constructor and base-class pattern used by neighboring extension tests so this suite follows the required fixture convention.
AGENTS.md reference: AGENTS.md:L53-L53
Useful? React with 👍 / 👎.
Names are now 1 to 64 ASCII letters, digits, periods, underscores, or hyphens that start with a letter or digit, so they can be used in filters and scripts. Invalid names, including ones with spaces, stay unspecified instead of being rewritten. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6264e61a1e
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| return String.IsNullOrEmpty(name) || name.Length > 64 || name.Any(Char.IsControl) | ||
| ? null | ||
| : name; | ||
| return name is not null && EnvironmentNameRegex().IsMatch(name) ? name : null; |
There was a problem hiding this comment.
Preserve previously valid environments when reading stored events
BLOCKER: For existing events with previously valid names such as Staging West, prod/eu, or produção, this stricter normalization also runs during deserialization, not just when adding managed environments. EventEnvironmentConverter.Read uses this method and now moves those stored values into custom data instead of populating Environment, so fetching historical events changes their public API representation and makes their environment disappear from event details. Preserve the previous read contract for persisted events, even if newly listed names must follow stricter rules, and cover a historical-record round trip.
AGENTS.md reference: AGENTS.md:L74-L75
Useful? React with 👍 / 👎.
Environment names are identifiers now, so the filter no longer offers qa,east. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Manage a project's environments under Project settings → Environments, and stop lower environments from sending notifications.
What you get
With the defaults, nothing changes from today.
Ingestion
flowchart LR E[Event] --> L{Environment<br/>listed?} L -- yes --> K[Keep] L -- no --> D{Discard<br/>unlisted?} D -- no --> K D -- yes --> X[Discard and count the name]Clients get a 202, so discards would be invisible. The page lists every discarded name with a count and an Allow button. Discarded events don't count toward the plan limit.
Notifications (email, Slack, webhooks)
flowchart LR A[Event] --> N{Environment<br/>notifies?} N -- no --> H[Hold: stack stays pending] N -- yes --> P{New or regression<br/>pending?} P -- yes --> C[Send once] P -- no --> R[Usual rules]Example: a bug appears in
devand gets no notification. The day it reachesproduction, one "new error" notification goes out. Regressions work the same way.Deploy notes
.,_or-, starting with a letter or digit (e.g.staging-eu). Anything else, including spaces, is treated as no environment. This tightens Add event environments and filtering #2570, which hasn't been released.API
POST,PATCHandDELETE /api/v2/projects/{id}/environments·PUT …/environments/settings·GET …/environments/discardedTesting
🤖 Generated with Claude Code