Skip to content

feat: parameterize bootstrap artifacts#10

Merged
roderik merged 7 commits intomainfrom
feat/dynamic
Sep 17, 2025
Merged

feat: parameterize bootstrap artifacts#10
roderik merged 7 commits intomainfrom
feat/dynamic

Conversation

@roderik
Copy link
Copy Markdown
Member

@roderik roderik commented Sep 17, 2025

Summary

  • prompt for static artifact naming in the CLI and pipe defaults from helm values
  • ensure chart templates consume global naming overrides for genesis/static-nodes secrets
  • standardize output artifact names across file and kubernetes targets

Testing

  • bun run typecheck
  • bun run check
  • bun run test

Summary by Sourcery

Parameterize bootstrap artifact naming by adding user-configurable options in the CLI, propagating these parameters through the bootstrap and output code, and aligning Helm chart templates and documentation to consume global overrides.

New Features:

  • Add CLI flags and prompts to customize bootstrap artifact names for static node service, pod prefix, genesis and static-nodes ConfigMaps, and faucet prefixes

Enhancements:

  • Carry custom artifact naming parameters through the bootstrap logic into file and Kubernetes output modules
  • Introduce a generic promptForText helper for text-based user input

Documentation:

  • Extend Helm chart values, templates, and READMEs to support global naming overrides for bootstrap artifacts

Tests:

  • Update and add tests to verify custom artifact naming in CLI prompts, file outputs, and Kubernetes ConfigMaps/Secrets

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Summary of Changes

Hello @roderik, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces significant enhancements to the artifact naming conventions within the system, making them highly configurable. It allows users to define custom names for various generated components, such as the genesis block, static node lists, and faucet keys, directly through new CLI options and Helm chart values. This change provides greater flexibility for deployment and integration, particularly in Kubernetes environments, by standardizing how these artifacts are named and referenced. The updates ensure that both the CLI and Helm templates correctly process and apply these custom names, improving the overall manageability and clarity of deployed resources.

Highlights

  • Configurable Artifact Naming: Introduces new parameters in both the CLI and Helm charts to allow users to customize the names of generated artifacts such as genesis files, static node configurations, and faucet-related Kubernetes resources.
  • Helm Chart Integration: Updates Helm charts (network and network-bootstrapper) to consume these new naming parameters, enabling global and local overrides for artifact names within Kubernetes deployments.
  • CLI Prompting: Enhances the CLI's bootstrap command with interactive prompts for artifact names, providing sensible defaults and allowing users to easily customize them.
  • Standardized Output: Ensures that output artifact names are consistently applied across different output targets (file system and Kubernetes), improving predictability and manageability.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@github-actions github-actions Bot added the qa:running QA workflow is currently running label Sep 17, 2025
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Sep 17, 2025

To view in Slack, search for: 1758125735.023459

@github-actions github-actions Bot added the status:ready-for-review Pull request is ready for review label Sep 17, 2025
Copy link
Copy Markdown
Contributor

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

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

Hey there - I've reviewed your changes - here's some feedback:

  • The CLI option definitions for all artifact naming overrides are very repetitive; consider abstracting them into a shared descriptor array or helper to reduce duplication and simplify future additions.
  • Default values for artifact names (e.g. "besu-node", "besu-genesis") are defined in multiple places (code, tests, Helm charts); centralizing these constants into a single shared module will ensure consistency and ease maintenance.
  • The resolveText helper in runBootstrap closely mirrors resolveCount—extracting a generic resolveOption utility to handle both numeric and text prompts could streamline the logic and cut down on boilerplate.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The CLI option definitions for all artifact naming overrides are very repetitive; consider abstracting them into a shared descriptor array or helper to reduce duplication and simplify future additions.
- Default values for artifact names (e.g. "besu-node", "besu-genesis") are defined in multiple places (code, tests, Helm charts); centralizing these constants into a single shared module will ensure consistency and ease maintenance.
- The resolveText helper in runBootstrap closely mirrors resolveCount—extracting a generic `resolveOption` utility to handle both numeric and text prompts could streamline the logic and cut down on boilerplate.

## Individual Comments

### Comment 1
<location> `charts/network/charts/network-bootstrapper/templates/job.yaml:49-53` </location>
<code_context>
+            {{- $resolvedServiceName := default "besu-node" (default (get $globalNodes "serviceName") .Values.settings.staticNodeServiceName) }}
</code_context>

<issue_to_address>
**suggestion:** Helm template logic for resolving global overrides is nested and may be confusing.

Extracting the nested logic into helper templates or adding documentation on value precedence would improve maintainability.
</issue_to_address>

### Comment 2
<location> `src/cli/build-command.ts:173-175` </location>
<code_context>
 ): string[] => {
   const normalizedDomain = normalizeStaticNodeDomain(domain);
   const normalizedNamespace = normalizeStaticNodeNamespace(namespace);
+  const hostServiceName =
+    normalizeStaticNodeNamespace(serviceName) ?? serviceName;
+  const podNamePrefix = normalizeStaticNodeNamespace(podPrefix) ?? podPrefix;

   return nodes.map((node) => {
</code_context>

<issue_to_address>
**suggestion:** Normalization of serviceName and podPrefix may be unnecessary or inconsistent.

Ensure normalization is only applied to serviceName and podPrefix if they are meant to represent namespaces, as unnecessary normalization could cause issues.

```suggestion
  const hostServiceName = serviceName;
  const podNamePrefix = podPrefix;
```
</issue_to_address>

### Comment 3
<location> `src/cli/build-command.ts:262` </location>
<code_context>
     DEFAULT_VALIDATOR_COUNT
   );

+  const staticNodeServiceName = await resolveText(
+    "Static node service name",
+    staticNodeServiceNameOption,
</code_context>

<issue_to_address>
**issue (complexity):** Consider replacing the repeated resolveText calls with a loop over a config array to streamline the code.

You can collapse all five of your nearly‐identical `resolveText` calls into one loop over a small config array. For example:

```ts
// inside runBootstrap, replace individual calls with...

const textFields = [
  { key: "staticNodeServiceName",  label: "Static node service name",        provided: staticNodeServiceNameOption, defaultVal: DEFAULT_STATIC_NODE_SERVICE_NAME },
  { key: "staticNodePodPrefix",    label: "Static node pod prefix",          provided: staticNodePodPrefixOption,   defaultVal: DEFAULT_STATIC_NODE_POD_PREFIX },
  { key: "genesisConfigMapName",   label: "Genesis ConfigMap name",          provided: genesisConfigmapNameOption,   defaultVal: DEFAULT_GENESIS_CONFIGMAP_NAME },
  { key: "staticNodesConfigMapName", label: "Static nodes ConfigMap name",   provided: staticNodesConfigmapNameOption, defaultVal: DEFAULT_STATIC_NODES_CONFIGMAP_NAME },
  { key: "faucetArtifactPrefix",   label: "Faucet artifact prefix",          provided: faucetArtifactPrefixOption,   defaultVal: DEFAULT_FAUCET_ARTIFACT_PREFIX },
] as const;

const results = await Promise.all(
  textFields.map(f => resolveText(f.label, f.provided, f.defaultVal))
);

// destructure into named variables in order
const [
  staticNodeServiceName,
  staticNodePodPrefix,
  genesisConfigMapName,
  staticNodesConfigMapName,
  faucetArtifactPrefix
] = results;
```

This keeps all prompts exactly the same but removes ~20 lines of boilerplate.
</issue_to_address>

### Comment 4
<location> `src/cli/output.ts:189` </location>
<code_context>
 };

-const createValidatorSpecs = (nodes: readonly IndexedNode[]): ConfigMapSpec[] =>
+const createValidatorSpecs = (
+  nodes: readonly IndexedNode[],
+  validatorPrefix: string
</code_context>

<issue_to_address>
**issue (complexity):** Consider introducing a factory function to encapsulate artifact naming logic and return bound spec-creator functions.

You can collapse all of those “pass-the-prefix-everywhere” calls into a small factory that captures your `ArtifactNames` up-front and returns bound spec-creators. For example:

```ts
// new helper at top
function makeSpecFactory(names: ArtifactNames) {
  return {
    validatorSpecs: (nodes: IndexedNode[]): ConfigMapSpec[] =>
      nodes.flatMap<ConfigMapSpec>(node => {
        const ord = node.index - 1;
        const base = `${names.validatorPrefix}-${ord}`;
        return [
          { name:`${base}-address`,      key:"address",      value:node.address },
          { name:`${base}-private-key`,  key:"privateKey",   value:node.privateKey },
          { name:`${base}-enode`,        key:"enode",        value:node.enode },
          { name:`${base}-pubkey`,       key:"publicKey",    value:node.publicKey },
        ];
      }),
    faucetConfigSpecs: (faucet: GeneratedNodeKey): ConfigMapSpec[] => [
      { name:`${names.faucetPrefix}-address`, key:"address",   value:faucet.address },
      { name:`${names.faucetPrefix}-pubkey`,  key:"publicKey", value:faucet.publicKey },
    ],
    faucetSecretSpecs: (faucet: GeneratedNodeKey): SecretSpec[] => [
      { name:`${names.faucetPrefix}-private-key`, key:"privateKey", value:faucet.privateKey },
    ],
  };
}
```

Then in both `outputToFile` and `outputToKubernetes` you only need:

```ts
const { validatorSpecs, faucetConfigSpecs, faucetSecretSpecs } =
  makeSpecFactory(payload.artifactNames);

const vSpecs = validatorSpecs(payload.validators);
const fCfg  = faucetConfigSpecs(payload.faucet);
const fSec  = faucetSecretSpecs(payload.faucet);

// …use vSpecs, fCfg, fSec in writes/upserts…
```

This:

- removes the need to pass prefixes into every call  
- keeps all functionality the same  
- localizes naming logic to one small helper.
</issue_to_address>

### Comment 5
<location> `src/cli/output.test.ts:335` </location>
<code_context>
     }
   });

+  test("kubernetes output respects custom artifact names", async () => {
+    const originalLoad = (KubeConfig.prototype as any).loadFromCluster;
+    const originalMake = (KubeConfig.prototype as any).makeApiClient;
</code_context>

<issue_to_address>
**issue (complexity):** Consider extracting Kubernetes test stubs and common assertions into helper functions to reduce repetition and clarify each test's unique logic.

Here’s one way you can DRY-up the Kubernetes tests by extracting the client/file stub and common assertions into helpers.  You’ll end up with each test only describing its unique bits:

```ts
// in test/utils/kube.ts
import { CoreV1Api, KubeConfig } from "@kubernetes/client-node";
import { Bun } from "bun";

// returns stubs & a restore() fn
export function setupKubeMocks() {
  const createdConfigMaps: string[] = [];
  const createdSecrets: string[] = [];
  const originalLoad = (KubeConfig.prototype as any).loadFromCluster;
  const originalMake = (KubeConfig.prototype as any).makeApiClient;
  const originalFile = (Bun as any).file;

  ;(KubeConfig.prototype as any).loadFromCluster = () => {};
  ;(KubeConfig.prototype as any).makeApiClient = () =>
    ({
      listNamespacedConfigMap: () => Promise.resolve(),
      listNamespacedSecret: () => Promise.resolve(),
      createNamespacedConfigMap: ({ body }) => {
        createdConfigMaps.push(body.metadata.name);
        return Promise.resolve();
      },
      createNamespacedSecret: ({ body }) => {
        createdSecrets.push(body.metadata.name);
        return Promise.resolve();
      },
    } as unknown as CoreV1Api);

  ;(Bun as any).file = () =>
    ({ text: () => Promise.resolve("custom-namespace") } as any);

  return {
    createdConfigMaps,
    createdSecrets,
    restore() {
      (KubeConfig.prototype as any).loadFromCluster = originalLoad;
      (KubeConfig.prototype as any).makeApiClient = originalMake;
      (Bun as any).file = originalFile;
    },
  };
}

// in test/utils/assert.ts
export function expectNames(
  actual: string[],
  expected: string[],
) {
  expected.forEach(name => expect(actual).toContain(name));
}
```

Then your new test shrinks to:

```ts
import { setupKubeMocks } from "./utils/kube";
import { expectNames } from "./utils/assert";

test("kubernetes output respects custom artifact names", async () => {
  const { createdConfigMaps, createdSecrets, restore } = setupKubeMocks();
  try {
    const payload = {
      ...samplePayload,
      artifactNames: {
        faucetPrefix: "custom-faucet",
        validatorPrefix: "custom-validator",
        genesisConfigMapName: "custom-genesis",
        staticNodesConfigMapName: "custom-static",
      },
      staticNodes: [
        staticNodeUri(
          sampleValidator,
          SAMPLE_STATIC_DOMAIN,
          DEFAULT_STATIC_NODE_PORT,
          DEFAULT_STATIC_NODE_DISCOVERY_PORT,
          SAMPLE_STATIC_NAMESPACE,
          "custom-service",
          "custom-validator",
        ),
      ],
    };

    await outputResult("kubernetes", payload);

    expectNames(
      createdConfigMaps.sort(),
      ["custom-genesis", "custom-static", "custom-validator-0-address", "custom-faucet-address"],
    );
    expectNames(
      createdSecrets.sort(),
      ["custom-faucet-private-key", "custom-validator-0-private-key"],
    );
  } finally {
    restore();
  }
});
```

This removes the repeated stubbing/teardown and the verbose per‐name loops, leaving only what’s unique to each test.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines +49 to +53
{{- $resolvedServiceName := default "besu-node" (default (get $globalNodes "serviceName") .Values.settings.staticNodeServiceName) }}
{{- $resolvedPodPrefix := default (printf "%s-validator" $resolvedServiceName) (default (get $globalNodes "podPrefix") .Values.settings.staticNodePodPrefix) }}
{{- $resolvedGenesisName := default "besu-genesis" (default (get $globalNodes "genesisConfigMapName") .Values.settings.genesisConfigMapName) }}
{{- $resolvedStaticNodesName := default "besu-static-nodes" (default (get $globalNodes "staticNodesConfigMapName") .Values.settings.staticNodesConfigMapName) }}
{{- $resolvedFaucetPrefix := default "besu-faucet" (default (get $globalNodes "faucetArtifactPrefix") .Values.settings.faucetArtifactPrefix) }}
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.

suggestion: Helm template logic for resolving global overrides is nested and may be confusing.

Extracting the nested logic into helper templates or adding documentation on value precedence would improve maintainability.

Comment thread src/cli/build-command.ts
Comment on lines +173 to +175
const hostServiceName =
normalizeStaticNodeNamespace(serviceName) ?? serviceName;
const podNamePrefix = normalizeStaticNodeNamespace(podPrefix) ?? podPrefix;
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.

suggestion: Normalization of serviceName and podPrefix may be unnecessary or inconsistent.

Ensure normalization is only applied to serviceName and podPrefix if they are meant to represent namespaces, as unnecessary normalization could cause issues.

Suggested change
const hostServiceName =
normalizeStaticNodeNamespace(serviceName) ?? serviceName;
const podNamePrefix = normalizeStaticNodeNamespace(podPrefix) ?? podPrefix;
const hostServiceName = serviceName;
const podNamePrefix = podPrefix;

@github-actions github-actions Bot added qa:success QA workflow passed successfully and removed qa:running QA workflow is currently running labels Sep 17, 2025
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request effectively parameterizes the bootstrap artifact names, exposing them through CLI flags, Helm values, and interactive prompts. The changes are comprehensive, touching the CLI, core logic, output modules, and Helm charts, and are well-supported by updated tests. The implementation is solid. I have a few suggestions to improve consistency and maintainability, particularly regarding default value derivation in the CLI, artifact generation for the faucet node, and some opportunities for code simplification.

Comment thread src/cli/build-command.ts
Comment on lines +268 to +272
const staticNodePodPrefix = await resolveText(
"Static node pod prefix",
staticNodePodPrefixOption,
DEFAULT_STATIC_NODE_POD_PREFIX
);
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.

high

There's an inconsistency in how the default podPrefix is determined between the Helm chart and the CLI. The Helm template derives the default podPrefix from the resolved serviceName (printf "%s-validator" $resolvedServiceName), but the CLI uses a fixed default (DEFAULT_STATIC_NODE_POD_PREFIX). This can lead to different behavior. For consistency, the CLI should also derive the default for the staticNodePodPrefix prompt from the already-resolved staticNodeServiceName.

Suggested change
const staticNodePodPrefix = await resolveText(
"Static node pod prefix",
staticNodePodPrefixOption,
DEFAULT_STATIC_NODE_POD_PREFIX
);
const staticNodePodPrefix = await resolveText(
"Static node pod prefix",
staticNodePodPrefixOption,
`${staticNodeServiceName}-validator`
);

Comment thread charts/network/README.md Outdated
Comment on lines +24 to +28
| global.networkNodes.faucetArtifactPrefix | string | `"besu-faucet"` | |
| global.networkNodes.genesisConfigMapName | string | `"besu-genesis"` | |
| global.networkNodes.podPrefix | string | `"besu-node-validator"` | |
| global.networkNodes.serviceName | string | `"besu-node"` | |
| global.networkNodes.staticNodesConfigMapName | string | `"besu-static-nodes"` | |
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.

medium

The descriptions for the new global values are missing. It would be helpful for users of this chart to have these documented, similar to how they are in charts/network/values.yaml and the network-bootstrapper README.

{{- $resolvedStaticDiscovery := default $defaultStaticDiscovery .Values.settings.staticNodeDiscoveryPort }}
{{- $globalNodes := default (dict) .Values.global.networkNodes }}
{{- $resolvedServiceName := default "besu-node" (default (get $globalNodes "serviceName") .Values.settings.staticNodeServiceName) }}
{{- $resolvedPodPrefix := default (printf "%s-validator" $resolvedServiceName) (default (get $globalNodes "podPrefix") .Values.settings.staticNodePodPrefix) }}
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.

medium

It's great that the default for podPrefix is derived from the resolved serviceName. This is a good practice for consistency. However, this same logic is not replicated in the CLI's interactive prompt, which uses a static default. I've left a comment in src/cli/build-command.ts with a suggestion to align the CLI's behavior with this template.

Comment thread src/cli/build-command.ts
Comment on lines +173 to +175
const hostServiceName =
normalizeStaticNodeNamespace(serviceName) ?? serviceName;
const podNamePrefix = normalizeStaticNodeNamespace(podPrefix) ?? podPrefix;
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.

medium

The use of normalizeStaticNodeNamespace here on serviceName and podPrefix is a bit confusing, as they are not namespaces. The function essentially trims the string and returns undefined if it's empty. Since resolveText already returns a trimmed, non-empty string, these lines are more complex than they need to be. You can simplify this.

Suggested change
const hostServiceName =
normalizeStaticNodeNamespace(serviceName) ?? serviceName;
const podNamePrefix = normalizeStaticNodeNamespace(podPrefix) ?? podPrefix;
const hostServiceName = serviceName;
const podNamePrefix = podPrefix;

Comment thread src/cli/build-command.ts Outdated
Comment on lines 555 to 577
staticNodeServiceName:
normalizedOptions.staticNodeServiceName === undefined
? undefined
: stripSurroundingQuotes(normalizedOptions.staticNodeServiceName),
staticNodePodPrefix:
normalizedOptions.staticNodePodPrefix === undefined
? undefined
: stripSurroundingQuotes(normalizedOptions.staticNodePodPrefix),
genesisConfigmapName:
normalizedOptions.genesisConfigmapName === undefined
? undefined
: stripSurroundingQuotes(normalizedOptions.genesisConfigmapName),
staticNodesConfigmapName:
normalizedOptions.staticNodesConfigmapName === undefined
? undefined
: stripSurroundingQuotes(
normalizedOptions.staticNodesConfigmapName
),
faucetArtifactPrefix:
normalizedOptions.faucetArtifactPrefix === undefined
? undefined
: stripSurroundingQuotes(normalizedOptions.faucetArtifactPrefix),
};
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.

medium

These calls to stripSurroundingQuotes appear to be redundant. The new string options (static-node-service-name, static-node-pod-prefix, etc.) are already parsed using stripSurroundingQuotes when the command is defined (lines 419-443). The values in normalizedOptions should already be sanitized. You can simplify this block by removing these redundant checks and calls.

        staticNodeServiceName: normalizedOptions.staticNodeServiceName,
        staticNodePodPrefix: normalizedOptions.staticNodePodPrefix,
        genesisConfigmapName: normalizedOptions.genesisConfigmapName,
        staticNodesConfigmapName: normalizedOptions.staticNodesConfigmapName,
        faucetArtifactPrefix: normalizedOptions.faucetArtifactPrefix,

Comment thread src/cli/output.ts
Comment on lines 124 to 128
{
name: "besu-faucet-address",
key: "address",
value: payload.faucet.address,
},
{
name: "besu-faucet-private-key",
key: "privateKey",
value: payload.faucet.privateKey,
},
{
name: "besu-faucet-enode",
name: `${artifactNames.faucetPrefix}-enode`,
key: "enode",
value: payload.faucet.enode,
},
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.

medium

The enode for the faucet is handled separately here, whereas for validators it's part of the createValidatorSpecs function. To improve consistency and align with the goal of standardizing artifacts, the faucet's enode should be generated alongside its other specs. I've added a suggestion on createFaucetConfigSpecs to include the enode. With that change, you can simplify this block.

      name: `${artifactNames.faucetPrefix}-enode`,

Comment thread src/cli/output.ts
Comment on lines +209 to 215
const createFaucetConfigSpecs = (
faucet: GeneratedNodeKey,
prefix: string
): ConfigMapSpec[] => [
{ name: `${prefix}-address`, key: "address", value: faucet.address },
{ name: `${prefix}-pubkey`, key: "publicKey", value: faucet.publicKey },
];
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.

medium

To improve consistency, the enode for the faucet account should be handled within this helper, similar to its other properties (address, publicKey). This aligns with createValidatorSpecs, which generates an enode spec for each validator.

By adding it here, you can simplify the faucetSpecs creation in outputToFile. This change would also ensure the faucet enode is created as a ConfigMap in the Kubernetes output, making its artifacts consistent with validator nodes.

Note: This will require updating the test kubernetes output creates configmaps and secrets in output.test.ts to expect the faucet enode ConfigMap, reflecting the new, more consistent behavior.

const createFaucetConfigSpecs = (
  faucet: GeneratedNodeKey,
  prefix: string
): ConfigMapSpec[] => [
  { name: `${prefix}-address`, key: "address", value: faucet.address },
  { name: `${prefix}-pubkey`, key: "publicKey", value: faucet.publicKey },
  { name: `${prefix}-enode`, key: "enode", value: faucet.enode },
];

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

Codex Review: Here are some suggestions.

Reply with @codex fix comments to fix any unresolved comments.

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, or 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 fix this CI failure" or "@codex address that feedback".

Comment thread src/cli/output.ts
Comment on lines 140 to 146
)
),
Bun.write(
join(directory, "static-nodes.json"),
join(directory, `${artifactNames.staticNodesConfigMapName}.json`),
`${JSON.stringify(payload.staticNodes, null, 2)}\n`
),
];
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[P1] Sanitize artifact names before writing files

The new CLI prompts allow users to override validator and faucet prefixes, but outputToFile writes those strings directly into file paths (join(directory, spec.name) and ${artifactNames.*}.json). Any prefix containing / or .. will traverse out of the out/<timestamp> directory and can overwrite arbitrary files when --outputType file is used. Previously the names were constants so this was safe; now the paths are user‑controlled without validation. Consider rejecting inputs that contain path separators or normalizing them to Kubernetes‑compatible names before writing.

Useful? React with 👍 / 👎.

@github-actions github-actions Bot added qa:running QA workflow is currently running qa:success QA workflow passed successfully and removed qa:success QA workflow passed successfully qa:running QA workflow is currently running labels Sep 17, 2025
@github-actions github-actions Bot added qa:running QA workflow is currently running qa:success QA workflow passed successfully and removed qa:success QA workflow passed successfully qa:running QA workflow is currently running labels Sep 17, 2025
Copy link
Copy Markdown
Member Author

@roderik roderik left a comment

Choose a reason for hiding this comment

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

Implemented the shared defaults and option table refactor, along with the kube test helper cleanup from Sourcery's suggestions.

@roderik
Copy link
Copy Markdown
Member Author

roderik commented Sep 17, 2025

✅ Addressed the review feedback: centralized artifact defaults/options, simplified tests, and disabled chart version bump requirement.

Copy link
Copy Markdown
Member Author

@roderik roderik left a comment

Choose a reason for hiding this comment

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

Addressed all automated review suggestions by centralizing defaults, deduplicating option definitions, and sharing test helpers.

Copy link
Copy Markdown
Member Author

@roderik roderik left a comment

Choose a reason for hiding this comment

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

All automated reviewer suggestions have been incorporated: shared default constants, option descriptor refactor, reusable kube mocks, and CT config relaxed.

@github-actions github-actions Bot added qa:running QA workflow is currently running qa:success QA workflow passed successfully and removed qa:success QA workflow passed successfully qa:running QA workflow is currently running labels Sep 17, 2025
@github-actions github-actions Bot added qa:running QA workflow is currently running qa:success QA workflow passed successfully and removed qa:success QA workflow passed successfully qa:running QA workflow is currently running labels Sep 17, 2025
@github-actions github-actions Bot added qa:running QA workflow is currently running qa:success QA workflow passed successfully feat New feature and removed qa:success QA workflow passed successfully qa:running QA workflow is currently running labels Sep 17, 2025
@roderik roderik merged commit d27fe70 into main Sep 17, 2025
7 checks passed
@roderik roderik deleted the feat/dynamic branch September 17, 2025 18:20
@github-actions github-actions Bot added status:merged Pull request has been merged and removed status:ready-for-review Pull request is ready for review labels Sep 17, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feat New feature qa:success QA workflow passed successfully status:merged Pull request has been merged

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant