Skip to content

feat: implement reserved service name validation for Apl services - #1074

Open
CasLubbers wants to merge 4 commits into
mainfrom
APL-2099
Open

feat: implement reserved service name validation for Apl services#1074
CasLubbers wants to merge 4 commits into
mainfrom
APL-2099

Conversation

@CasLubbers

Copy link
Copy Markdown
Contributor

No description provided.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Implements validation to prevent creation/update of APL team services whose names are reserved due to collisions with per-team platform hostnames.

Changes:

  • Added RESERVED_SERVICE_NAMES environment validator with a default reserved list.
  • Enforced reserved-name validation in createAplService and editAplService.
  • Added Jest coverage for reserved-name behavior and env overrides; updated package-lock.json.

Reviewed changes

Copilot reviewed 3 out of 4 changed files in this pull request and generated 2 comments.

File Description
src/validators.ts Adds a new env validator for RESERVED_SERVICE_NAMES.
src/otomi-stack.ts Parses reserved names and rejects reserved service names on create/edit.
src/otomi-stack.test.ts Adds tests for reserved-name validation and env customization.
package-lock.json Lockfile metadata updates (removed peer flags in multiple entries).

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/otomi-stack.ts Outdated
Comment on lines +217 to +223
function getReservedServiceNames(): Set<string> {
return new Set(
env.RESERVED_SERVICE_NAMES.split(',')
.map((name) => name.trim().toLowerCase())
.filter((name) => name.length > 0),
)
}
Comment thread src/otomi-stack.ts Outdated
Comment on lines +227 to +229
if (reserved.has(name.trim().toLowerCase())) {
throw new ValidationError(`Service name is reserved. Reserved names: ${Array.from(reserved).join(', ')}`)
}
Copilot AI review requested due to automatic review settings August 26, 2026 09:33

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 6 changed files in this pull request and generated 2 comments.

Comment on lines +41 to +45
it('trims whitespace and ignores case', () => {
let assertServiceNameNotReserved: typeof import('./serviceUtils').assertServiceNameNotReserved
jest.isolateModules(() => {
;({ assertServiceNameNotReserved } = require('./serviceUtils'))
})
Comment thread src/otomi-stack.test.ts
Comment on lines +275 to +276
it('allows a non-reserved name on create', async () => {
await expect(otomiStack.createAplService(teamId, buildService('my-service'))).resolves.not.toThrow()
Copilot AI review requested due to automatic review settings September 9, 2026 12:41

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

A newly added unit test is environment-dependent and can become flaky unless it explicitly controls process.env.RESERVED_SERVICE_NAMES.

Review details

Suppressed comments (1)

src/utils/serviceUtils.test.ts:46

  • The "trims whitespace and ignores case" test relies on whatever RESERVED_SERVICE_NAMES happens to be in the test runner environment. If CI (or another suite) sets it to a value that doesn’t include grafana, this test will fail even though the implementation is correct. Make the test deterministic by explicitly deleting the env var (so the validator default applies) before requiring the module.
  it('trims whitespace and ignores case', () => {
    let assertServiceNameNotReserved: typeof import('./serviceUtils').assertServiceNameNotReserved
    jest.isolateModules(() => {
      ;({ assertServiceNameNotReserved } = require('./serviceUtils'))
    })

  • Files reviewed: 5/6 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

Copilot AI review requested due to automatic review settings September 10, 2026 13:38

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

The new tests include a Jest matcher misuse (resolves.not.toThrow()) and one unit test is environment-dependent unless RESERVED_SERVICE_NAMES is explicitly controlled.

Review details

Suppressed comments (2)

src/utils/serviceUtils.test.ts:45

  • In this test, RESERVED_SERVICE_NAMES is not set/cleared before loading ./serviceUtils, so the assertion can become environment-dependent if RESERVED_SERVICE_NAMES is defined externally when the suite runs. Set or delete the env var explicitly (like the other tests in this file) before isolateModules to keep the test deterministic.
  it('trims whitespace and ignores case', () => {
    let assertServiceNameNotReserved: typeof import('./serviceUtils').assertServiceNameNotReserved
    jest.isolateModules(() => {
      ;({ assertServiceNameNotReserved } = require('./serviceUtils'))
    })

src/otomi-stack.test.ts:277

  • resolves.not.toThrow() is a matcher misuse: toThrow expects a function, so this assertion can fail with "received value must be a function" even when the promise resolves successfully. Assert that the promise resolves (and optionally check the returned value) instead.
    it('allows a non-reserved name on create', async () => {
      await expect(otomiStack.createAplService(teamId, buildService('my-service'))).resolves.not.toThrow()
    })
  • Files reviewed: 5/6 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants