Skip to content

refactor jenkins client #57

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 23, 2025

Conversation

xinredhat
Copy link
Member

@xinredhat xinredhat commented Jul 21, 2025

Summary by CodeRabbit

  • New Features

    • Introduced a comprehensive Jenkins client with service-oriented architecture for managing jobs, builds, folders, and credentials.
    • Added robust error handling with custom error types specific to Jenkins operations.
    • Provided utilities for XML configuration, API path construction, build trigger analysis, and asynchronous polling.
    • Centralized Jenkins configuration constants and type-safe API interfaces.
    • Added detailed documentation with usage examples and extension guidelines.
    • Enhanced JenkinsCI provider with job activity status retrieval and improved credential management.
    • Added methods to wait for multiple Jenkins jobs to complete with timeout and polling support.
    • Added GitLab CI client method to retrieve pipeline logs via REST API.
  • Bug Fixes

    • Removed duplicate method in JenkinsCI provider to prevent redundancy.
  • Refactor

    • Updated import paths to use the new Jenkins client entry point consistently.
    • Improved method signatures for backward compatibility and consistency.
    • Refactored JenkinsCI provider to use new client methods for job completion polling.
    • Modified GitLab CI integration to explicitly signal unsupported pipeline log retrieval.
  • Documentation

    • Added comprehensive README detailing architecture, usage, extension, and testing of the Jenkins client.
  • Tests

    • Removed JenkinsClient integration test suite.
  • Chores

    • Ensured consistent Promise-based return types and clarified unsupported features in GitLab CI integration.

Copy link

coderabbitai bot commented Jul 21, 2025

Walkthrough

A comprehensive, modular Jenkins client implementation in TypeScript was introduced, featuring a service-oriented architecture with strong typing, centralized configuration, custom error handling, extensible credential strategies, and utility classes. Supporting documentation and type definitions were added. Minor changes to GitLab CI code and related imports were also made for consistency and improved clarity.

Changes

File(s) Change Summary
src/api/ci/jenkins/README.md Added detailed documentation for the Jenkins client architecture, usage, patterns, and extensibility.
src/api/ci/jenkins/config/jenkins.config.ts Introduced JenkinsConfig class for centralized configuration constants and endpoints.
src/api/ci/jenkins/enums/jenkins.enums.ts Added enums for build results, triggers, and credential types.
src/api/ci/jenkins/errors/jenkins.errors.ts Defined custom error classes for Jenkins-related failure scenarios.
src/api/ci/jenkins/http/jenkins-http.client.ts Implemented JenkinsHttpClient for HTTP API interactions with error handling and utility methods.
src/api/ci/jenkins/index.ts Created index module to re-export all Jenkins client components.
src/api/ci/jenkins/jenkins.client.ts Added JenkinsClient facade class exposing job, build, credential services, and utility methods.
src/api/ci/jenkins/services/jenkins-build.service.ts Introduced JenkinsBuildService for build management, searching, polling, and trigger analysis.
src/api/ci/jenkins/services/jenkins-credential.service.ts Added JenkinsCredentialService for credential management using strategy pattern.
src/api/ci/jenkins/services/jenkins-job.service.ts Implemented JenkinsJobService for folder and job operations with error handling.
src/api/ci/jenkins/strategies/credential.strategy.ts Added credential strategy pattern for XML generation by credential type.
src/api/ci/jenkins/types/jenkins.types.ts Defined TypeScript interfaces for Jenkins entities, options, and API responses.
src/api/ci/jenkins/utils/jenkins.utils.ts Introduced utility classes for path building, XML generation, trigger analysis, and polling.
src/rhtap/core/integration/ci/providers/jenkinsCI.ts Updated imports to new Jenkins client, removed duplicate method, enhanced credential management, refactored polling, added job status retrieval method.
src/rhtap/postcreation/strategies/commands/addJenkinsSecretsCommand.ts Updated import path for CredentialType.
tests/api/ci/jenkinsClient.test.ts Removed entire JenkinsClient test suite.
src/api/ci/gitlabciClient.ts Implemented getPipelineLogs method; uses direct REST API call and logs errors.
src/rhtap/core/integration/ci/providers/gitlabCI.ts Updated getIntegrationSecret to return Promise; getPipelineLogs now throws unsupported error.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant JenkinsClient
    participant JenkinsJobService
    participant JenkinsBuildService
    participant JenkinsCredentialService
    participant JenkinsHttpClient
    participant Jenkins

    User->>JenkinsClient: createJob(options)
    JenkinsClient->>JenkinsJobService: createJob(options)
    JenkinsJobService->>JenkinsHttpClient: POST /createItem
    JenkinsHttpClient->>Jenkins: HTTP Request
    Jenkins-->>JenkinsHttpClient: HTTP Response
    JenkinsHttpClient-->>JenkinsJobService: JenkinsApiResponse
    JenkinsJobService-->>JenkinsClient: JenkinsApiResponse
    JenkinsClient-->>User: JenkinsApiResponse

    User->>JenkinsClient: build(options)
    JenkinsClient->>JenkinsBuildService: triggerBuild(options)
    JenkinsBuildService->>JenkinsHttpClient: POST /build
    JenkinsHttpClient->>Jenkins: HTTP Request
    Jenkins-->>JenkinsHttpClient: HTTP Response
    JenkinsHttpClient-->>JenkinsBuildService: JenkinsApiResponse
    JenkinsBuildService-->>JenkinsClient: JenkinsApiResponse
    JenkinsClient-->>User: JenkinsApiResponse

    User->>JenkinsClient: createCredential(...)
    JenkinsClient->>JenkinsCredentialService: createCredential(...)
    JenkinsCredentialService->>JenkinsHttpClient: POST /credentials
    JenkinsHttpClient->>Jenkins: HTTP Request
    Jenkins-->>JenkinsHttpClient: HTTP Response
    JenkinsHttpClient-->>JenkinsCredentialService: JenkinsApiResponse
    JenkinsCredentialService-->>JenkinsClient: JenkinsApiResponse
    JenkinsClient-->>User: JenkinsApiResponse
Loading

Estimated code review effort

4 (~90 minutes)

Suggested reviewers

  • jkopriva

Poem

🐇
In Jenkins’ warren, code now hops,
With types and errors, never stops.
Credentials safe, jobs neatly spun,
Builds and triggers on the run.
With docs and enums, all in sync—
This rabbit grins, gives you a wink!
🥕

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

src/api/ci/jenkins/config/jenkins.config.ts

Oops! Something went wrong! :(

ESLint: 8.57.1

Error [ERR_MODULE_NOT_FOUND]: Cannot find package '@eslint/js' imported from /eslint.config.js
at Object.getPackageJSONURL (node:internal/modules/package_json_reader:255:9)
at packageResolve (node:internal/modules/esm/resolve:767:81)
at moduleResolve (node:internal/modules/esm/resolve:853:18)
at defaultResolve (node:internal/modules/esm/resolve:983:11)
at ModuleLoader.defaultResolve (node:internal/modules/esm/loader:801:12)
at #cachedDefaultResolve (node:internal/modules/esm/loader:725:25)
at ModuleLoader.resolve (node:internal/modules/esm/loader:708:38)
at ModuleLoader.getModuleJobForImport (node:internal/modules/esm/loader:309:38)
at #link (node:internal/modules/esm/module_job:202:49)

src/api/ci/gitlabciClient.ts

Oops! Something went wrong! :(

ESLint: 8.57.1

Error [ERR_MODULE_NOT_FOUND]: Cannot find package '@eslint/js' imported from /eslint.config.js
at Object.getPackageJSONURL (node:internal/modules/package_json_reader:255:9)
at packageResolve (node:internal/modules/esm/resolve:767:81)
at moduleResolve (node:internal/modules/esm/resolve:853:18)
at defaultResolve (node:internal/modules/esm/resolve:983:11)
at ModuleLoader.defaultResolve (node:internal/modules/esm/loader:801:12)
at #cachedDefaultResolve (node:internal/modules/esm/loader:725:25)
at ModuleLoader.resolve (node:internal/modules/esm/loader:708:38)
at ModuleLoader.getModuleJobForImport (node:internal/modules/esm/loader:309:38)
at #link (node:internal/modules/esm/module_job:202:49)

src/api/ci/jenkins/enums/jenkins.enums.ts

Oops! Something went wrong! :(

ESLint: 8.57.1

Error [ERR_MODULE_NOT_FOUND]: Cannot find package '@eslint/js' imported from /eslint.config.js
at Object.getPackageJSONURL (node:internal/modules/package_json_reader:255:9)
at packageResolve (node:internal/modules/esm/resolve:767:81)
at moduleResolve (node:internal/modules/esm/resolve:853:18)
at defaultResolve (node:internal/modules/esm/resolve:983:11)
at ModuleLoader.defaultResolve (node:internal/modules/esm/loader:801:12)
at #cachedDefaultResolve (node:internal/modules/esm/loader:725:25)
at ModuleLoader.resolve (node:internal/modules/esm/loader:708:38)
at ModuleLoader.getModuleJobForImport (node:internal/modules/esm/loader:309:38)
at #link (node:internal/modules/esm/module_job:202:49)

  • 13 others
✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 13

🔭 Outside diff range comments (1)
src/rhtap/core/integration/ci/providers/jenkinsCI.ts (1)

303-319: Good integration of the helper method, but there's duplicated conversion logic.

While the use of convertBuildToPipeline is correct, there's still manual status conversion logic above (lines 241-265) that should also use this helper method for consistency.

Consider refactoring the manual status conversion to also use the helper:

-        // Map Jenkins build status to our standardized PipelineStatus format
-        let status = PipelineStatus.UNKNOWN;
-
-        if (buildInfo.building) {
-          status = PipelineStatus.RUNNING;
-        } else if (buildInfo.result) {
-          switch (buildInfo.result.toUpperCase()) {
-            case 'SUCCESS':
-              status = PipelineStatus.SUCCESS;
-              break;
-            case 'FAILURE':
-              status = PipelineStatus.FAILURE;
-              break;
-            case 'UNSTABLE':
-              status = PipelineStatus.FAILURE; // Map unstable to failure
-              break;
-            case 'ABORTED':
-              status = PipelineStatus.FAILURE; // Map aborted to failure
-              break;
-            case 'NOT_BUILT':
-              status = PipelineStatus.PENDING;
-              break;
-            default:
-              status = PipelineStatus.UNKNOWN;
-          }
-        }
-
-        // If we're filtering by status and this pipeline doesn't match, return null
-        if (pipelineStatus !== PipelineStatus.UNKNOWN && status !== pipelineStatus) {
-          return null;
-        }
+        // Create a temporary pipeline to get the standardized status
+        const tempPipeline = this.convertBuildToPipeline(buildInfo, jobName, pullRequest.repository, '', commitSha);
+        
+        // If we're filtering by status and this pipeline doesn't match, return null
+        if (pipelineStatus !== PipelineStatus.UNKNOWN && tempPipeline.status !== pipelineStatus) {
+          return null;
+        }
🧹 Nitpick comments (9)
tests/api/ci/jenkinsClient.test.ts (1)

13-13: Consider using a more descriptive default URL.

Setting the default Jenkins URL to an empty string may cause unclear error messages if the environment variable is not set. Consider using a placeholder URL or adding validation.

-const JENKINS_URL = process.env.JENKINS_URL || '';
+const JENKINS_URL = process.env.JENKINS_URL || 'http://localhost:8080';

Or add validation:

const JENKINS_URL = process.env.JENKINS_URL;
if (!JENKINS_URL) {
  throw new Error('JENKINS_URL environment variable is required for tests');
}
src/api/ci/jenkins/config/jenkins.config.ts (1)

24-30: Consider making plugin versions configurable.

Hardcoded plugin versions may become outdated over time. Consider making these configurable or adding a mechanism to validate/update them.

// Example: Allow override via environment or config
PLUGINS: {
  WORKFLOW_JOB: process.env.JENKINS_WORKFLOW_JOB_PLUGIN || 'workflow-job@2.40',
  GITHUB: process.env.JENKINS_GITHUB_PLUGIN || 'github@1.37.1',
  // ... other plugins
} as const,
src/api/ci/jenkins/types/jenkins.types.ts (3)

1-1: Fix import ordering and remove unused import.

The static analysis correctly identifies import ordering and unused import issues.

-import { JenkinsBuildResult, JenkinsBuildTrigger, CredentialType } from '../enums/jenkins.enums';
+import { JenkinsBuildResult, JenkinsBuildTrigger } from '../enums/jenkins.enums';

Note: CredentialType appears to be unused in this file and should be removed unless it's actually needed somewhere not visible in the diff.


6-11: Consider more specific typing for the generic response wrapper.

While the generic T = any provides flexibility, it reduces type safety. Consider if specific response types could be defined for common use cases.

-export interface JenkinsApiResponse<T = any> {
+export interface JenkinsApiResponse<T = unknown> {
   success: boolean;
   status: number;
   data: T;
   location?: string;
 }

Using unknown instead of any encourages proper type checking at usage sites.


91-96: Consider more specific typing for actions and causes.

The any[] types for actions and causes could be more specific if the Jenkins API structure is known.

If the structure of these fields is consistent, consider defining specific interfaces:

// Example if actions have a known structure
actions: JenkinsBuildAction[];
causes?: JenkinsBuildCause[];

This would improve type safety and IDE support.

src/api/ci/jenkins/README.md (1)

20-43: Fix missing language specification for the directory structure.

The static analysis correctly identifies a missing language specification for the directory structure code block.

-```
+```text
 jenkins/
 ├── enums/                    # Enums for Jenkins constants
 │   └── jenkins.enums.ts
src/api/ci/jenkins/utils/jenkins.utils.ts (1)

123-130: Consider using an XML library for escaping

Manual XML escaping can miss edge cases and control characters. Consider using a dedicated XML library for more robust escaping.

   private static escapeXml(text: string): string {
-    return text
-      .replace(/&/g, '&amp;')
-      .replace(/</g, '&lt;')
-      .replace(/>/g, '&gt;')
-      .replace(/"/g, '&quot;')
-      .replace(/'/g, '&#39;');
+    // Use a library like 'xmlbuilder2' or 'xml-escape'
+    // Example: return xmlEscape(text);
+    // For now, keeping the manual implementation
+    return text
+      .replace(/&/g, '&amp;')
+      .replace(/</g, '&lt;')
+      .replace(/>/g, '&gt;')
+      .replace(/"/g, '&quot;')
+      .replace(/'/g, '&#39;');
   }
src/api/ci/jenkins/services/jenkins-build.service.ts (1)

299-369: Refactor complex commit matching logic

This method is quite long and handles multiple matching strategies. Consider breaking it down into smaller, focused methods for better maintainability.

Also, use optional chaining for consistency:

-    if (build.displayName && build.displayName.includes(normalizedCommitSha)) {
+    if (build.displayName?.includes(normalizedCommitSha)) {
-    } else if (build.description && build.description.includes(normalizedCommitSha)) {
+    } else if (build.description?.includes(normalizedCommitSha)) {

Consider extracting each matching strategy into separate methods:

  • checkScmRevision(action, normalizedCommitSha)
  • checkBuildParameters(action, normalizedCommitSha)
  • checkPullRequestInfo(action, normalizedCommitSha)
  • etc.
src/api/ci/jenkins/jenkins.client.ts (1)

353-379: Well-documented service accessors for advanced use cases.

The getter methods provide appropriate access to underlying services for advanced scenarios. The JSDoc comments clearly indicate their purpose.

Consider whether exposing the raw HTTP client (line 377-379) is necessary. It might break encapsulation and allow bypassing of the service layer's logic. If it's truly needed, consider documenting specific use cases or providing a more restricted interface.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 26d84c7 and bcae555.

📒 Files selected for processing (16)
  • src/api/ci/jenkins/README.md (1 hunks)
  • src/api/ci/jenkins/config/jenkins.config.ts (1 hunks)
  • src/api/ci/jenkins/enums/jenkins.enums.ts (1 hunks)
  • src/api/ci/jenkins/errors/jenkins.errors.ts (1 hunks)
  • src/api/ci/jenkins/http/jenkins-http.client.ts (1 hunks)
  • src/api/ci/jenkins/index.ts (1 hunks)
  • src/api/ci/jenkins/jenkins.client.ts (1 hunks)
  • src/api/ci/jenkins/services/jenkins-build.service.ts (1 hunks)
  • src/api/ci/jenkins/services/jenkins-credential.service.ts (1 hunks)
  • src/api/ci/jenkins/services/jenkins-job.service.ts (1 hunks)
  • src/api/ci/jenkins/strategies/credential.strategy.ts (1 hunks)
  • src/api/ci/jenkins/types/jenkins.types.ts (1 hunks)
  • src/api/ci/jenkins/utils/jenkins.utils.ts (1 hunks)
  • src/rhtap/core/integration/ci/providers/jenkinsCI.ts (4 hunks)
  • src/rhtap/postcreation/strategies/commands/addJenkinsSecretsCommand.ts (1 hunks)
  • tests/api/ci/jenkinsClient.test.ts (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (2)
src/rhtap/core/integration/ci/providers/jenkinsCI.ts (4)
src/api/ci/jenkinsClient.ts (2)
  • build (323-360)
  • JenkinsBuild (29-63)
src/api/ci/jenkins/types/jenkins.types.ts (1)
  • JenkinsBuild (75-109)
src/rhtap/core/integration/ci/ciInterface.ts (2)
  • Pipeline (50-50)
  • PipelineStatus (50-50)
src/rhtap/core/integration/ci/pipeline.ts (1)
  • Pipeline (17-174)
src/api/ci/jenkins/http/jenkins-http.client.ts (3)
src/api/ci/jenkins/index.ts (1)
  • JenkinsHttpClient (20-20)
src/api/ci/jenkins/types/jenkins.types.ts (2)
  • JenkinsClientConfig (16-20)
  • JenkinsApiResponse (6-11)
src/api/ci/jenkins/errors/jenkins.errors.ts (3)
  • JenkinsError (4-18)
  • JenkinsAuthenticationError (75-80)
  • JenkinsRateLimitError (85-93)
🪛 markdownlint-cli2 (0.17.2)
src/api/ci/jenkins/README.md

20-20: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🪛 ESLint
src/api/ci/jenkins/index.ts

[error] 28-28: Replace · with

(prettier/prettier)

src/rhtap/core/integration/ci/providers/jenkinsCI.ts

[error] 5-5: Replace Client with BuildTrigger

(prettier/prettier)


[error] 6-6: Replace Build with Client

(prettier/prettier)


[error] 303-307: Replace ⏎············jobName,⏎············buildNumber,⏎············folderName⏎·········· with jobName,·buildNumber,·folderName

(prettier/prettier)

src/api/ci/jenkins/config/jenkins.config.ts

[error] 11-11: Delete ··

(prettier/prettier)


[error] 17-17: Replace 'Accept' with Accept

(prettier/prettier)


[error] 18-18: Replace 'Accept' with Accept

(prettier/prettier)


[error] 44-44: Replace · with

(prettier/prettier)

src/api/ci/jenkins/enums/jenkins.enums.ts

[error] 30-30: Replace · with

(prettier/prettier)

src/api/ci/jenkins/errors/jenkins.errors.ts

[error] 12-12: Delete ····

(prettier/prettier)


[error] 87-87: Delete ·

(prettier/prettier)


[error] 93-93: Replace · with

(prettier/prettier)

src/api/ci/jenkins/http/jenkins-http.client.ts

[error] 1-1: Replace axios,·{·AxiosInstance,·AxiosRequestConfig,·AxiosResponse·}·from·'axio with {⏎··JenkinsAuthenticationError,⏎··JenkinsError,⏎··JenkinsRateLimitError,⏎}·from·'../errors/jenkins.error

(prettier/prettier)


[error] 2-2: Replace ClientConfig,·JenkinsApiResponse with ApiResponse,·JenkinsClientConfig

(prettier/prettier)


[error] 3-7: Replace {·⏎··JenkinsError,·⏎··JenkinsAuthenticationError,·⏎··JenkinsRateLimitError·⏎}·from·'../errors/jenkins.error with axios,·{·AxiosInstance,·AxiosRequestConfig,·AxiosResponse·}·from·'axio

(prettier/prettier)


[error] 64-68: Replace ⏎················Jenkins·API·request·failed:·${message},⏎················status,⏎················error⏎·············· with ``Jenkins·API·request·failed:·${message},·status,·error

(prettier/prettier)


[error] 82-82: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 83-83: Delete ·

(prettier/prettier)


[error] 85-85: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 99-99: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 101-101: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 103-103: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 111-111: Delete ····

(prettier/prettier)


[error] 130-130: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 132-132: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 136-136: Delete ····

(prettier/prettier)


[error] 148-148: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 153-153: Delete ····

(prettier/prettier)


[error] 184-184: Replace · with

(prettier/prettier)

src/api/ci/jenkins/types/jenkins.types.ts

[error] 1-1: Replace JenkinsBuildResult,·JenkinsBuildTrigger,·CredentialType with CredentialType,·JenkinsBuildResult,·JenkinsBuildTrigger

(prettier/prettier)


[error] 1-1: 'CredentialType' is defined but never used.

(@typescript-eslint/no-unused-vars)


[error] 6-6: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 91-91: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 95-95: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 140-140: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 141-141: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 142-142: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 150-150: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 155-155: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 156-156: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 157-157: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 158-158: Replace · with

(prettier/prettier)

src/api/ci/jenkins/strategies/credential.strategy.ts

[error] 1-1: Replace CredentialType·}·from·'../enums/jenkins.enums with JenkinsConfig·}·from·'../config/jenkins.config

(prettier/prettier)


[error] 2-2: Replace JenkinsConfig·}·from·'../config/jenkins.config with CredentialType·}·from·'../enums/jenkins.enums

(prettier/prettier)


[error] 45-45: Delete ····

(prettier/prettier)


[error] 64-64: Delete ····

(prettier/prettier)


[error] 67-67: Delete ····

(prettier/prettier)


[error] 95-95: Delete ····

(prettier/prettier)


[error] 99-99: Delete ····

(prettier/prettier)


[error] 116-116: Replace · with

(prettier/prettier)

src/api/ci/jenkins/services/jenkins-build.service.ts

[error] 1-1: Replace HttpClient·}·from·'../http/jenkins-http.client with Config·}·from·'../config/jenkins.config

(prettier/prettier)


[error] 2-9: Replace ⏎··JenkinsApiResponse,·⏎··BuildOptions,·⏎··BuildSearchOptions,⏎··WaitForBuildOptions,⏎··JenkinsBuild,⏎··JenkinsJob⏎}·from·'../types/jenkins.type with JenkinsBuildResult,·JenkinsBuildTrigger·}·from·'../enums/jenkins.enum

(prettier/prettier)


[error] 10-10: Replace ·JenkinsBuildResult,·JenkinsBuildTrigger·}·from·'../enums/jenkins.enum with ⏎··JenkinsBuildNotFoundError,⏎··JenkinsBuildTimeoutError,⏎··JenkinsJobNotFoundError,⏎}·from·'../errors/jenkins.error

(prettier/prettier)


[error] 10-10: 'JenkinsBuildResult' is defined but never used.

(@typescript-eslint/no-unused-vars)


[error] 11-11: Replace Config·}·from·'../config/jenkins.config with HttpClient·}·from·'../http/jenkins-http.client

(prettier/prettier)


[error] 12-12: Delete ·

(prettier/prettier)


[error] 13-13: Replace JenkinsPathBuilder,· with BuildOptions,⏎··BuildSearchOptions,

(prettier/prettier)


[error] 14-14: Replace TriggerAnalyzer,· with ApiResponse,⏎··JenkinsBuild,

(prettier/prettier)


[error] 15-15: Replace PollingUtils· with Job,⏎··WaitForBuildOptions,

(prettier/prettier)


[error] 16-16: Replace utils/jenkins.util with types/jenkins.type

(prettier/prettier)


[error] 17-17: Delete ·

(prettier/prettier)


[error] 18-18: Replace BuildNotFoundError,· with PathBuilder,

(prettier/prettier)


[error] 19-19: Replace BuildTimeoutError with PollingUtils

(prettier/prettier)


[error] 20-20: Replace JobNotFoundError· with TriggerAnalyzer,

(prettier/prettier)


[error] 21-21: Replace errors/jenkins.error with utils/jenkins.util

(prettier/prettier)


[error] 35-35: Delete ·

(prettier/prettier)


[error] 36-36: Delete ·

(prettier/prettier)


[error] 38-38: Delete ······

(prettier/prettier)


[error] 40-40: Delete ·

(prettier/prettier)


[error] 41-41: Delete ·

(prettier/prettier)


[error] 42-42: Delete ·

(prettier/prettier)


[error] 45-45: Delete ······

(prettier/prettier)


[error] 48-48: Replace ·?·${options.folderName}/${options.jobName}`` with ⏎········?·${options.folderName}/${options.jobName}`⏎·······`

(prettier/prettier)


[error] 57-57: Delete ·

(prettier/prettier)


[error] 58-58: Delete ·

(prettier/prettier)


[error] 64-64: Delete ·

(prettier/prettier)


[error] 65-65: Delete ·

(prettier/prettier)


[error] 66-66: Delete ·

(prettier/prettier)


[error] 69-69: Delete ······

(prettier/prettier)


[error] 70-73: Replace ⏎········path,⏎········JenkinsConfig.HEADERS.JSON⏎······ with path,·JenkinsConfig.HEADERS.JSON

(prettier/prettier)


[error] 77-77: Replace buildInfo with ⏎··········buildInfo⏎········

(prettier/prettier)


[error] 92-92: Delete ······

(prettier/prettier)


[error] 151-151: Delete ·

(prettier/prettier)


[error] 152-152: Delete ·

(prettier/prettier)


[error] 153-153: Delete ·

(prettier/prettier)


[error] 157-159: Replace ⏎········path,⏎········JenkinsConfig.HEADERS.PLAIN, with path,·JenkinsConfig.HEADERS.PLAIN,·{

(prettier/prettier)


[error] 160-160: Replace {·start:·0·} with start:·0,

(prettier/prettier)


[error] 161-161: Insert }

(prettier/prettier)


[error] 178-178: Insert ,

(prettier/prettier)


[error] 204-204: Insert ,

(prettier/prettier)


[error] 234-234: Delete ········

(prettier/prettier)


[error] 264-264: Delete ·

(prettier/prettier)


[error] 265-265: Delete ·

(prettier/prettier)


[error] 276-276: Delete ·

(prettier/prettier)


[error] 277-277: Delete ·

(prettier/prettier)


[error] 288-288: Delete ·

(prettier/prettier)


[error] 289-289: Delete ·

(prettier/prettier)


[error] 318-318: Replace Found·matching·commit·in·buildsByBranchName·for·branch·${branch}:·${branchSha} with ⏎··················Found·matching·commit·in·buildsByBranchName·for·branch·${branch}:·${branchSha}⏎················

(prettier/prettier)


[error] 328-328: Replace (param.name·===·'GIT_COMMIT'·||·param.name·===·'ghprbActualCommit')·&&·param.value with ⏎··············(param.name·===·'GIT_COMMIT'·||·param.name·===·'ghprbActualCommit')·&&⏎··············param.value⏎············

(prettier/prettier)


[error] 377-377: Replace · with

(prettier/prettier)

src/api/ci/jenkins/services/jenkins-credential.service.ts

[error] 1-2: Replace HttpClient·}·from·'../http/jenkins-http.client';⏎import·{·JenkinsApiResponse·}·from·'../types/jenkins.types with Config·}·from·'../config/jenkins.config

(prettier/prettier)


[error] 4-4: Replace onfig·}·from·'../config/jenkins.config with redentialError·}·from·'../errors/jenkins.errors

(prettier/prettier)


[error] 5-5: Replace PathBuilder·}·from·'../utils/jenkins.utils with HttpClient·}·from·'../http/jenkins-http.client

(prettier/prettier)


[error] 7-7: Replace CredentialError·}·from·'../errors/jenkins.error with ApiResponse·}·from·'../types/jenkins.types';⏎import·{·JenkinsPathBuilder·}·from·'../utils/jenkins.util

(prettier/prettier)


[error] 27-27: Delete ······

(prettier/prettier)


[error] 30-30: Delete ······

(prettier/prettier)


[error] 33-33: Delete ······

(prettier/prettier)


[error] 35-35: Delete ······

(prettier/prettier)


[error] 57-57: Delete ······

(prettier/prettier)


[error] 60-60: Delete ······

(prettier/prettier)


[error] 65-65: Delete ······

(prettier/prettier)


[error] 67-67: Delete ······

(prettier/prettier)


[error] 69-69: Delete ······

(prettier/prettier)


[error] 88-88: Delete ······

(prettier/prettier)


[error] 90-90: Delete ······

(prettier/prettier)


[error] 92-92: Delete ······

(prettier/prettier)


[error] 120-120: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 126-126: Delete ······

(prettier/prettier)


[error] 128-128: Delete ······

(prettier/prettier)


[error] 130-130: Delete ······

(prettier/prettier)


[error] 133-136: Replace ⏎········credentialId,⏎········'Credential·not·found·or·not·accessible'⏎······ with credentialId,·'Credential·not·found·or·not·accessible'

(prettier/prettier)


[error] 143-143: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 149-149: Delete ······

(prettier/prettier)


[error] 151-151: Delete ······

(prettier/prettier)


[error] 152-152: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 157-157: Delete ······

(prettier/prettier)


[error] 188-188: Replace folderName,·credentialId,·secretValue,·CredentialType.USERNAME_PASSWORD with ⏎······folderName,⏎······credentialId,⏎······secretValue,⏎······CredentialType.USERNAME_PASSWORD⏎····

(prettier/prettier)


[error] 204-204: Replace · with

(prettier/prettier)

src/api/ci/jenkins/utils/jenkins.utils.ts

[error] 1-1: Replace CreateJobOptions·}·from·'../types/jenkins.types with JenkinsConfig·}·from·'../config/jenkins.config

(prettier/prettier)


[error] 2-2: Replace JenkinsConfig·}·from·'../config/jenkins.config with CreateJobOptions·}·from·'../types/jenkins.types

(prettier/prettier)


[error] 12-12: Delete ·

(prettier/prettier)


[error] 21-21: Delete ·

(prettier/prettier)


[error] 48-48: Replace jobName:·string,·buildNumber:·number,·folderName?:·string,·endpoint:·string·=·'' with ⏎····jobName:·string,⏎····buildNumber:·number,⏎····folderName?:·string,⏎····endpoint:·string·=·''⏎··

(prettier/prettier)


[error] 75-75: Delete ·

(prettier/prettier)


[error] 76-76: Delete ·

(prettier/prettier)


[error] 77-77: Delete ·

(prettier/prettier)


[error] 78-78: Delete ·

(prettier/prettier)


[error] 79-79: Replace · with ,

(prettier/prettier)


[error] 81-81: Delete ····

(prettier/prettier)


[error] 140-140: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 172-172: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 173-173: Insert (⏎······

(prettier/prettier)


[error] 174-174: Delete ·····

(prettier/prettier)


[error] 175-175: Delete ·····

(prettier/prettier)


[error] 176-176: Replace ·····(action.parameters·&&·action.parameters.some((p:·any)·=> with (action.parameters·&&⏎········action.parameters.some(

(prettier/prettier)


[error] 176-176: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 177-177: Replace ···p.name?.includes('ghpr')·||·p.name?.includes('pull')·||·p.name?.includes('PR')) with (p:·any)·=>·p.name?.includes('ghpr')·||·p.name?.includes('pull')·||·p.name?.includes('PR')⏎········))⏎····

(prettier/prettier)


[error] 183-183: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 190-190: Replace description.includes('pull·request')·|| with ⏎······description.includes('pull·request')·||⏎·····

(prettier/prettier)


[error] 191-191: Replace ········cause._class?.toLowerCase().includes('pullrequest') with ······cause._class?.toLowerCase().includes('pullrequest')⏎····

(prettier/prettier)


[error] 195-195: Insert ⏎······

(prettier/prettier)


[error] 196-196: Replace ········ with ······

(prettier/prettier)


[error] 197-197: Replace ··cause._class?.includes('GitLabWebHookCause') with cause._class?.includes('GitLabWebHookCause')⏎····

(prettier/prettier)


[error] 201-202: Delete ⏎·······

(prettier/prettier)


[error] 206-207: Delete ⏎·······

(prettier/prettier)


[error] 211-212: Delete ⏎·······

(prettier/prettier)


[error] 222-222: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 223-223: Replace build.actions·&&·build.actions.some( with (⏎······build.actions·&&⏎······build.actions.some(⏎········

(prettier/prettier)


[error] 223-223: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 224-224: Replace ······action._class?.includes('git')·||·action.lastBuiltRevision·||·action.buildsByBranchName with ··········action._class?.includes('git')·||·action.lastBuiltRevision·||·action.buildsByBranchName⏎······)⏎····

(prettier/prettier)


[error] 242-242: Delete ····

(prettier/prettier)


[error] 245-245: Delete ······

(prettier/prettier)


[error] 249-249: Delete ······

(prettier/prettier)


[error] 253-253: Delete ······

(prettier/prettier)


[error] 264-264: Replace · with

(prettier/prettier)

src/api/ci/jenkins/services/jenkins-job.service.ts

[error] 1-1: Replace HttpClient·}·from·'../http/jenkins-http.client with Config·}·from·'../config/jenkins.config

(prettier/prettier)


[error] 2-7: Replace ·⏎··JenkinsApiResponse,·⏎··FolderConfig,·⏎··CreateJobOptions,⏎··JenkinsJob⏎}·from·'../types/jenkins.type with ·JenkinsFolderError,·JenkinsJobNotFoundError·}·from·'../errors/jenkins.error

(prettier/prettier)


[error] 8-8: Replace Config·}·from·'../config/jenkins.config with HttpClient·}·from·'../http/jenkins-http.client

(prettier/prettier)


[error] 9-9: Replace ·JenkinsPathBuilder,·JenkinsXmlBuilder·}·from·'../utils/jenkins.util with ⏎··CreateJobOptions,⏎··FolderConfig,⏎··JenkinsApiResponse,⏎··JenkinsJob,⏎}·from·'../types/jenkins.type

(prettier/prettier)


[error] 10-10: Replace FolderError,·JenkinsJobNotFoundError·}·from·'../errors/jenkins.error with PathBuilder,·JenkinsXmlBuilder·}·from·'../utils/jenkins.util

(prettier/prettier)


[error] 25-25: Delete ······

(prettier/prettier)


[error] 27-27: Delete ······

(prettier/prettier)


[error] 45-45: Delete ······

(prettier/prettier)


[error] 51-51: Delete ······

(prettier/prettier)


[error] 54-54: Replace ·?·${options.folderName}/${options.jobName}`` with ⏎········?·${options.folderName}/${options.jobName}`⏎·······`

(prettier/prettier)


[error] 90-90: Replace ``${path}/doDelete,·'',·JenkinsConfig.HEADERS.JSON); with `⏎········`${path}/doDelete`,⏎········'',⏎········JenkinsConfig.HEADERS.JSON`

(prettier/prettier)


[error] 91-91: Insert );⏎

(prettier/prettier)


[error] 119-119: Delete ·

(prettier/prettier)


[error] 122-122: Delete ······

(prettier/prettier)


[error] 144-144: Replace ``${path}/disable,·'',·JenkinsConfig.HEADERS.JSON); with `⏎········`${path}/disable`,⏎········'',⏎········JenkinsConfig.HEADERS.JSON`

(prettier/prettier)


[error] 145-145: Insert );⏎

(prettier/prettier)


[error] 160-160: Delete ······

(prettier/prettier)


[error] 171-171: Replace jobName:·string,·configXml:·string,·folderName?:·string with ⏎····jobName:·string,⏎····configXml:·string,⏎····folderName?:·string⏎··

(prettier/prettier)


[error] 174-174: Replace ``${path}/config.xml,·configXml,·JenkinsConfig.HEADERS.XML); with `⏎········`${path}/config.xml`,⏎········configXml,⏎········JenkinsConfig.HEADERS.XML`

(prettier/prettier)


[error] 175-175: Insert );⏎

(prettier/prettier)


[error] 189-189: Replace ``${path}/config.xml,·JenkinsConfig.HEADERS.XML); with `⏎········`${path}/config.xml`,⏎········JenkinsConfig.HEADERS.XML`

(prettier/prettier)


[error] 190-190: Insert );⏎

(prettier/prettier)


[error] 197-197: Replace · with

(prettier/prettier)

src/api/ci/jenkins/jenkins.client.ts

[error] 1-1: Replace JenkinsHttpClient·}·from·'./http/jenkins-http.client with CredentialType,·JenkinsBuildTrigger·}·from·'./enums/jenkins.enums

(prettier/prettier)


[error] 2-2: Replace JobService·}·from·'./services/jenkins-job.service with HttpClient·}·from·'./http/jenkins-http.client

(prettier/prettier)


[error] 5-9: Replace ⏎··JenkinsClientConfig,⏎··JenkinsApiResponse,⏎··FolderConfig,⏎··CreateJobOptions, with JenkinsJobService·}·from·'./services/jenkins-job.service';⏎import·{

(prettier/prettier)


[error] 12-12: Replace WaitForBuild with CreateJob

(prettier/prettier)


[error] 13-13: Replace JenkinsBuild with FolderConfig,⏎··JenkinsApiResponse

(prettier/prettier)


[error] 14-14: Replace Job with Build,

(prettier/prettier)


[error] 15-16: Replace }·from·'./types/jenkins.types';⏎import·{·CredentialType,·JenkinsBuildTrigger·}·from·'./enums/jenkins.enum with ··JenkinsClientConfig,⏎··JenkinsJob,⏎··WaitForBuildOptions,⏎}·from·'./types/jenkins.type

(prettier/prettier)


[error] 142-142: Replace folderName,·credentialId,·secretValue,·credentialType with ⏎······folderName,⏎······credentialId,⏎······secretValue,⏎······credentialType⏎····

(prettier/prettier)


[error] 165-165: Replace folderName,·credentialId,·username,·password with ⏎······folderName,⏎······credentialId,⏎······username,⏎······password⏎····

(prettier/prettier)


[error] 380-380: Replace · with

(prettier/prettier)

🪛 Biome (1.9.4)
src/api/ci/jenkins/config/jenkins.config.ts

[error] 4-44: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)

src/api/ci/jenkins/http/jenkins-http.client.ts

[error] 59-59: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)

src/api/ci/jenkins/strategies/credential.strategy.ts

[error] 84-116: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)


[error] 94-94: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 107-107: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 114-114: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)

src/api/ci/jenkins/services/jenkins-build.service.ts

[error] 352-352: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 360-360: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 363-363: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

src/api/ci/jenkins/utils/jenkins.utils.ts

[error] 7-52: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)


[error] 49-49: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 57-131: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)


[error] 64-64: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 100-100: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 101-101: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 106-106: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 113-113: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 136-226: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)


[error] 145-145: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 154-154: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 162-162: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 176-177: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 223-224: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 231-264: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)


[error] 254-254: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Red Hat Konflux / tssc-test-on-pull-request
🔇 Additional comments (23)
src/rhtap/postcreation/strategies/commands/addJenkinsSecretsCommand.ts (1)

1-1: LGTM! Import path correctly updated for modular architecture.

The import path update aligns with the Jenkins client refactoring to use the centralized module structure. This change supports better organization and maintainability.

tests/api/ci/jenkinsClient.test.ts (1)

5-5: LGTM! Import path correctly updated for modular architecture.

The import path update aligns with the Jenkins client refactoring to use the centralized module structure.

src/api/ci/jenkins/enums/jenkins.enums.ts (1)

1-30: LGTM! Well-defined enums for type safety.

The enums provide excellent type safety and use appropriate string values that align with Jenkins API terminology. The coverage appears comprehensive for the current use cases.

Fix the trailing whitespace issue:

-export enum CredentialType {
-  SECRET_TEXT = 'Secret text',
-  USERNAME_PASSWORD = 'Username with password',
-} 
+export enum CredentialType {
+  SECRET_TEXT = 'Secret text',
+  USERNAME_PASSWORD = 'Username with password',
+}
src/api/ci/jenkins/index.ts (1)

1-28: Excellent barrel export organization!

The index file provides a clean, well-organized API surface that supports both backward compatibility and the new modular architecture. The categorized exports make it easy for consumers to understand what's available.

Fix the trailing whitespace issue:

-// Export a facade for backwards compatibility and convenience
-export { JenkinsClient } from './jenkins.client'; 
+// Export a facade for backwards compatibility and convenience
+export { JenkinsClient } from './jenkins.client';
src/rhtap/core/integration/ci/providers/jenkinsCI.ts (3)

4-7: Import consolidation looks good but verify enum usage consistency.

The updated imports properly use the new typed enums and interfaces from the refactored Jenkins client. This improves type safety and consistency across the codebase.


30-82: Excellent refactoring with the convertBuildToPipeline helper method.

This helper method successfully centralizes the build-to-pipeline conversion logic, eliminating code duplication and improving maintainability. The implementation properly:

  • Maps Jenkins build statuses to standardized PipelineStatus enums
  • Handles the building state correctly
  • Maps various Jenkins result states appropriately (UNSTABLE and ABORTED to FAILURE)
  • Serializes build actions for the results field
  • Uses the Pipeline.createJenkinsPipeline factory method

394-398: Perfect usage of the helper method in checkPipelineStatus.

The integration of convertBuildToPipeline in the checkPipelineStatus method is clean and consistent with the refactoring goals.

src/api/ci/jenkins/types/jenkins.types.ts (2)

75-109: Well-designed JenkinsBuild interface with comprehensive coverage.

The interface properly captures all essential Jenkins build properties with clear documentation. The use of typed enums for result and triggerType provides good type safety.


114-158: Comprehensive JenkinsJob interface covers Jenkins job metadata well.

The interface thoroughly covers Jenkins job properties including health reports, build references, and parameter definitions. The structure aligns well with Jenkins API responses.

src/api/ci/jenkins/README.md (2)

1-231: Excellent comprehensive documentation for the Jenkins client refactor.

This README provides outstanding documentation covering:

  • Clear architecture overview with benefits
  • Detailed directory structure
  • Multiple usage examples (legacy, new options-based, direct service access)
  • Design patterns explanation
  • Extension guidelines
  • Testing, performance, and security considerations

The documentation effectively communicates the refactoring goals and how to use the new client architecture.


45-145: Usage examples are clear and demonstrate both backward compatibility and new features.

The code examples effectively show:

  • Backward compatibility with existing method signatures
  • New options-based approach for better maintainability
  • Direct service access for advanced use cases
  • Proper error handling with specific error types

These examples will help developers understand the migration path and new capabilities.

src/api/ci/jenkins/strategies/credential.strategy.ts (3)

7-10: Clean strategy interface design.

The CredentialStrategy interface provides a clear contract for credential XML generation with proper typing.


15-37: Secure XML generation with proper escaping.

The SecretTextCredentialStrategy properly implements XML escaping to prevent injection attacks. The XML structure follows Jenkins credential plugin conventions.


59-69: Robust password parsing with colon support.

The credential parsing logic correctly handles passwords containing colons by rejoining array elements after the first split. This is important for complex passwords.

src/api/ci/jenkins/errors/jenkins.errors.ts (6)

4-18: Excellent base error class with proper error chaining.

The JenkinsError base class properly:

  • Extends native Error with additional context (statusCode, cause)
  • Handles stack trace capture for better debugging
  • Provides a foundation for the error hierarchy

23-29: Well-designed job not found error with path context.

The error constructor intelligently builds the job path including folder context, providing clear error messages for debugging.


34-39: Informative build timeout error with timing context.

The timeout error includes all relevant context (job name, build number, timeout duration) for effective debugging.


55-60: Flexible credential error with contextual information.

The credential error design allows for various failure scenarios while maintaining clear error identification.


75-80: Authentication error with sensible defaults.

The authentication error provides a default message while allowing customization, and correctly sets the 401 status code.


85-93: Rate limit error with retry guidance.

The rate limit error intelligently includes retry timing information when available, helping clients implement proper backoff strategies.

src/api/ci/jenkins/jenkins.client.ts (3)

39-44: Clean delegation pattern for folder operations.

The folder creation method correctly delegates to the job service, maintaining proper separation of concerns.


133-167: Well-designed credential operations with sensible defaults.

The credential methods provide a good balance between flexibility and convenience. The default CredentialType.SECRET_TEXT is a sensible choice, and the convenience methods enhance usability.


335-347: Useful utility methods for server health checks.

The ping and getVersion methods provide essential functionality for monitoring Jenkins server status and compatibility checks.

Comment on lines +4 to +44
export class JenkinsConfig {
public static readonly DEFAULT_BRANCH = 'main';
public static readonly DEFAULT_JENKINSFILE_PATH = 'Jenkinsfile';
public static readonly DEFAULT_CREDENTIAL_ID = 'GITOPS_AUTH_PASSWORD';
public static readonly DEFAULT_TIMEOUT_MS = 10 * 60 * 1000; // 10 minutes
public static readonly DEFAULT_POLL_INTERVAL_MS = 5000; // 5 seconds
public static readonly DEFAULT_MAX_BUILDS_TO_CHECK = 50;

/**
* HTTP headers for different content types
*/
public static readonly HEADERS = {
XML: { 'Content-Type': 'application/xml' },
JSON: { 'Content-Type': 'application/json', 'Accept': 'application/json' },
PLAIN: { 'Accept': 'text/plain' },
} as const;

/**
* Jenkins plugin information
*/
public static readonly PLUGINS = {
WORKFLOW_JOB: 'workflow-job@2.40',
GITHUB: 'github@1.37.1',
WORKFLOW_CPS: 'workflow-cps@2.89',
GIT: 'git@4.4.5',
PLAIN_CREDENTIALS: 'plain-credentials',
} as const;

/**
* Jenkins API endpoints
*/
public static readonly ENDPOINTS = {
CREATE_ITEM: 'createItem',
API_JSON: 'api/json',
BUILD: 'build',
BUILD_WITH_PARAMETERS: 'buildWithParameters',
LOG_TEXT: 'logText/progressiveText',
CREDENTIALS_STORE_SYSTEM: 'credentials/store/system/domain/_/createCredentials',
CREDENTIALS_STORE_FOLDER: 'credentials/store/folder/domain/_/createCredentials',
} as const;
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Refactor to avoid static-only class anti-pattern.

Using a class with only static members is an anti-pattern. Consider using a namespace, const object, or individual exports instead.

-export class JenkinsConfig {
-  public static readonly DEFAULT_BRANCH = 'main';
-  public static readonly DEFAULT_JENKINSFILE_PATH = 'Jenkinsfile';
-  // ... other static members
-}
+export const JenkinsConfig = {
+  DEFAULT_BRANCH: 'main',
+  DEFAULT_JENKINSFILE_PATH: 'Jenkinsfile',
+  DEFAULT_CREDENTIAL_ID: 'GITOPS_AUTH_PASSWORD',
+  DEFAULT_TIMEOUT_MS: 10 * 60 * 1000, // 10 minutes
+  DEFAULT_POLL_INTERVAL_MS: 5000, // 5 seconds
+  DEFAULT_MAX_BUILDS_TO_CHECK: 50,
+  
+  HEADERS: {
+    XML: { 'Content-Type': 'application/xml' },
+    JSON: { 'Content-Type': 'application/json', Accept: 'application/json' },
+    PLAIN: { Accept: 'text/plain' },
+  } as const,
+
+  PLUGINS: {
+    WORKFLOW_JOB: 'workflow-job@2.40',
+    GITHUB: 'github@1.37.1',
+    WORKFLOW_CPS: 'workflow-cps@2.89',
+    GIT: 'git@4.4.5',
+    PLAIN_CREDENTIALS: 'plain-credentials',
+  } as const,
+
+  ENDPOINTS: {
+    CREATE_ITEM: 'createItem',
+    API_JSON: 'api/json',
+    BUILD: 'build',
+    BUILD_WITH_PARAMETERS: 'buildWithParameters',
+    LOG_TEXT: 'logText/progressiveText',
+    CREDENTIALS_STORE_SYSTEM: 'credentials/store/system/domain/_/createCredentials',
+    CREDENTIALS_STORE_FOLDER: 'credentials/store/folder/domain/_/createCredentials',
+  } as const,
+} as const;

This also fixes the prettier formatting issues with quotes and spacing.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export class JenkinsConfig {
public static readonly DEFAULT_BRANCH = 'main';
public static readonly DEFAULT_JENKINSFILE_PATH = 'Jenkinsfile';
public static readonly DEFAULT_CREDENTIAL_ID = 'GITOPS_AUTH_PASSWORD';
public static readonly DEFAULT_TIMEOUT_MS = 10 * 60 * 1000; // 10 minutes
public static readonly DEFAULT_POLL_INTERVAL_MS = 5000; // 5 seconds
public static readonly DEFAULT_MAX_BUILDS_TO_CHECK = 50;
/**
* HTTP headers for different content types
*/
public static readonly HEADERS = {
XML: { 'Content-Type': 'application/xml' },
JSON: { 'Content-Type': 'application/json', 'Accept': 'application/json' },
PLAIN: { 'Accept': 'text/plain' },
} as const;
/**
* Jenkins plugin information
*/
public static readonly PLUGINS = {
WORKFLOW_JOB: 'workflow-job@2.40',
GITHUB: 'github@1.37.1',
WORKFLOW_CPS: 'workflow-cps@2.89',
GIT: 'git@4.4.5',
PLAIN_CREDENTIALS: 'plain-credentials',
} as const;
/**
* Jenkins API endpoints
*/
public static readonly ENDPOINTS = {
CREATE_ITEM: 'createItem',
API_JSON: 'api/json',
BUILD: 'build',
BUILD_WITH_PARAMETERS: 'buildWithParameters',
LOG_TEXT: 'logText/progressiveText',
CREDENTIALS_STORE_SYSTEM: 'credentials/store/system/domain/_/createCredentials',
CREDENTIALS_STORE_FOLDER: 'credentials/store/folder/domain/_/createCredentials',
} as const;
}
export const JenkinsConfig = {
DEFAULT_BRANCH: 'main',
DEFAULT_JENKINSFILE_PATH: 'Jenkinsfile',
DEFAULT_CREDENTIAL_ID: 'GITOPS_AUTH_PASSWORD',
DEFAULT_TIMEOUT_MS: 10 * 60 * 1000, // 10 minutes
DEFAULT_POLL_INTERVAL_MS: 5000, // 5 seconds
DEFAULT_MAX_BUILDS_TO_CHECK: 50,
/**
* HTTP headers for different content types
*/
HEADERS: {
XML: { 'Content-Type': 'application/xml' },
JSON: { 'Content-Type': 'application/json', Accept: 'application/json' },
PLAIN: { Accept: 'text/plain' },
} as const,
/**
* Jenkins plugin information
*/
PLUGINS: {
WORKFLOW_JOB: 'workflow-job@2.40',
GITHUB: 'github@1.37.1',
WORKFLOW_CPS: 'workflow-cps@2.89',
GIT: 'git@4.4.5',
PLAIN_CREDENTIALS: 'plain-credentials',
} as const,
/**
* Jenkins API endpoints
*/
ENDPOINTS: {
CREATE_ITEM: 'createItem',
API_JSON: 'api/json',
BUILD: 'build',
BUILD_WITH_PARAMETERS: 'buildWithParameters',
LOG_TEXT: 'logText/progressiveText',
CREDENTIALS_STORE_SYSTEM: 'credentials/store/system/domain/_/createCredentials',
CREDENTIALS_STORE_FOLDER: 'credentials/store/folder/domain/_/createCredentials',
} as const,
} as const;
🧰 Tools
🪛 Biome (1.9.4)

[error] 4-44: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)

🪛 ESLint

[error] 11-11: Delete ··

(prettier/prettier)


[error] 17-17: Replace 'Accept' with Accept

(prettier/prettier)


[error] 18-18: Replace 'Accept' with Accept

(prettier/prettier)


[error] 44-44: Replace · with

(prettier/prettier)

🤖 Prompt for AI Agents
In src/api/ci/jenkins/config/jenkins.config.ts from lines 4 to 44, the
JenkinsConfig class contains only static members, which is an anti-pattern.
Refactor this by replacing the class with either a namespace or a set of
individual exported constants or objects that hold the same data. This will also
help fix any prettier formatting issues related to quotes and spacing by
allowing more straightforward formatting of the exported constants.

Comment on lines +58 to +61
case 429:
const retryAfter = error.response.headers['retry-after'];
throw new JenkinsRateLimitError(retryAfter ? parseInt(retryAfter) : undefined);
case 404:
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix variable scoping in switch statement

The retryAfter variable declaration can be accessed by other switch cases, which could lead to unexpected behavior.

 case 429:
-  const retryAfter = error.response.headers['retry-after'];
-  throw new JenkinsRateLimitError(retryAfter ? parseInt(retryAfter) : undefined);
+  {
+    const retryAfter = error.response.headers['retry-after'];
+    throw new JenkinsRateLimitError(retryAfter ? parseInt(retryAfter) : undefined);
+  }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
case 429:
const retryAfter = error.response.headers['retry-after'];
throw new JenkinsRateLimitError(retryAfter ? parseInt(retryAfter) : undefined);
case 404:
case 429:
{
const retryAfter = error.response.headers['retry-after'];
throw new JenkinsRateLimitError(retryAfter ? parseInt(retryAfter) : undefined);
}
case 404:
🧰 Tools
🪛 Biome (1.9.4)

[error] 59-59: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)

🤖 Prompt for AI Agents
In src/api/ci/jenkins/http/jenkins-http.client.ts around lines 58 to 61, the
variable retryAfter is declared directly inside the switch case, making it
accessible to other cases and potentially causing scope-related bugs. To fix
this, wrap the case 429 block in braces {} to create a new block scope, ensuring
retryAfter is scoped only within that case and does not leak to other cases.

Comment on lines +112 to +117
if (response.status !== 200 && response.status !== 201) {
throw new JenkinsError(
`Request failed with status ${response.status}: ${response.statusText}`,
response.status
);
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Remove redundant status check

This status check is unnecessary because the response interceptor already handles non-2xx status codes by throwing appropriate errors.

     const response: AxiosResponse<T> = await this.client.post(path, data, config);
-    
-    if (response.status !== 200 && response.status !== 201) {
-      throw new JenkinsError(
-        `Request failed with status ${response.status}: ${response.statusText}`,
-        response.status
-      );
-    }

     return {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (response.status !== 200 && response.status !== 201) {
throw new JenkinsError(
`Request failed with status ${response.status}: ${response.statusText}`,
response.status
);
}
const response: AxiosResponse<T> = await this.client.post(path, data, config);
return {
🤖 Prompt for AI Agents
In src/api/ci/jenkins/http/jenkins-http.client.ts between lines 112 and 117,
remove the redundant if statement that checks if the response status is not 200
or 201 and throws a JenkinsError. This check is unnecessary because the response
interceptor already handles non-2xx status codes by throwing errors, so simply
delete this entire conditional block to avoid duplication.

Comment on lines +70 to +87
if (typeof optionsOrJobName === 'string') {
// Legacy method signature
const options: CreateJobOptions = {
jobName: optionsOrJobName,
repoUrl: repoUrl!,
folderName,
branch,
jenkinsfilePath,
credentialId,
};
return this.jobService.createJob(options);
} else {
// New options object signature
return this.jobService.createJob(optionsOrJobName);
}
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Add runtime validation for legacy method parameters.

The non-null assertion on line 74 (repoUrl!) could cause runtime errors if the method is called with undefined parameters. Consider adding validation:

 if (typeof optionsOrJobName === 'string') {
   // Legacy method signature
+  if (!repoUrl) {
+    throw new Error('repoUrl is required when using legacy method signature');
+  }
   const options: CreateJobOptions = {
     jobName: optionsOrJobName,
-    repoUrl: repoUrl!,
+    repoUrl: repoUrl,
     folderName,
     branch,
     jenkinsfilePath,
     credentialId,
   };
   return this.jobService.createJob(options);
 }
🤖 Prompt for AI Agents
In src/api/ci/jenkins/jenkins.client.ts around lines 70 to 85, the legacy method
uses a non-null assertion on repoUrl which may cause runtime errors if repoUrl
is undefined. Add runtime validation to check if repoUrl is defined before using
it. If repoUrl is missing, throw a clear error or handle the case gracefully to
prevent unexpected failures.

Comment on lines +181 to +253
async build(
optionsOrJobName: BuildOptions | string,
folderName?: string,
parameters?: Record<string, string>
): Promise<JenkinsApiResponse> {
if (typeof optionsOrJobName === 'string') {
// Legacy method signature
const options: BuildOptions = {
jobName: optionsOrJobName,
folderName,
parameters,
};
return this.buildService.triggerBuild(options);
} else {
// New options object signature
return this.buildService.triggerBuild(optionsOrJobName);
}
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Add validation for legacy build method parameters.

Similar to the createJob method, the build method should validate parameters when using the legacy signature.

 if (typeof optionsOrJobName === 'string') {
   // Legacy method signature
   const options: BuildOptions = {
     jobName: optionsOrJobName,
     folderName,
     parameters,
   };
   return this.buildService.triggerBuild(options);
 }

Note: This particular method doesn't have non-null assertions, so it's safer than the others.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In src/api/ci/jenkins/jenkins.client.ts around lines 181 to 198, the build
method uses a legacy signature accepting separate parameters but lacks
validation for these inputs. Add validation checks for the legacy parameters
(optionsOrJobName, folderName, parameters) similar to the createJob method to
ensure they meet expected criteria before proceeding. This will prevent invalid
or missing inputs from causing runtime errors.

Comment on lines +307 to +367
console.log(`Found matching commit in lastBuiltRevision: ${buildSha}`);
return true;
}
}

// Method 2: Check buildsByBranchName
if (action.buildsByBranchName) {
for (const branch in action.buildsByBranchName) {
if (action.buildsByBranchName[branch].revision?.SHA1) {
const branchSha = action.buildsByBranchName[branch].revision.SHA1.toLowerCase();
if (this.commitShasMatch(branchSha, normalizedCommitSha)) {
console.log(`Found matching commit in buildsByBranchName for branch ${branch}: ${branchSha}`);
return true;
}
}
}
}

// Method 3: Check GIT_COMMIT environment variable in build parameters
if (action.parameters) {
for (const param of action.parameters) {
if ((param.name === 'GIT_COMMIT' || param.name === 'ghprbActualCommit') && param.value) {
const paramSha = param.value.toLowerCase();
if (this.commitShasMatch(paramSha, normalizedCommitSha)) {
console.log(`Found matching commit in build parameter ${param.name}: ${paramSha}`);
return true;
}
}
}
}

// Method 4: Check pull request related information
if (action._class?.includes('pull-request') && action.pullRequest?.source?.commit) {
const prSha = action.pullRequest.source.commit.toLowerCase();
if (this.commitShasMatch(prSha, normalizedCommitSha)) {
console.log(`Found matching commit in pull request info: ${prSha}`);
return true;
}
}
}
}

// Method 5: Check in build causes
if (build.causes) {
for (const cause of build.causes) {
if (cause.shortDescription && cause.shortDescription.includes(normalizedCommitSha)) {
console.log(`Found matching commit in build causes: ${cause.shortDescription}`);
return true;
}
}
}

// Method 6: Check in build display name or description
if (build.displayName && build.displayName.includes(normalizedCommitSha)) {
console.log(`Found matching commit in build display name: ${build.displayName}`);
return true;
} else if (build.description && build.description.includes(normalizedCommitSha)) {
console.log(`Found matching commit in build description: ${build.description}`);
return true;
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Remove additional debug console.log statements

This method also contains multiple console.log statements that should be removed or replaced with proper logging.

Remove console.log statements at:

  • Line 307
  • Line 318
  • Line 331
  • Line 342
  • Line 353
  • Line 361
  • Line 364
🧰 Tools
🪛 Biome (1.9.4)

[error] 352-352: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 360-360: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 363-363: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

🪛 ESLint

[error] 318-318: Replace Found·matching·commit·in·buildsByBranchName·for·branch·${branch}:·${branchSha} with ⏎··················Found·matching·commit·in·buildsByBranchName·for·branch·${branch}:·${branchSha}⏎················

(prettier/prettier)


[error] 328-328: Replace (param.name·===·'GIT_COMMIT'·||·param.name·===·'ghprbActualCommit')·&&·param.value with ⏎··············(param.name·===·'GIT_COMMIT'·||·param.name·===·'ghprbActualCommit')·&&⏎··············param.value⏎············

(prettier/prettier)

🤖 Prompt for AI Agents
In src/api/ci/jenkins/services/jenkins-build.service.ts between lines 307 and
365, there are multiple console.log statements used for debugging purposes.
Remove all these console.log statements at lines 307, 318, 331, 342, 353, 361,
and 364 to clean up the code. If logging is necessary, replace them with
appropriate logger calls consistent with the project's logging strategy.

Comment on lines +62 to +67
const basePath = folderName
? `job/${encodeURIComponent(folderName)}/credentials/store/folder/domain/_/credential/${encodeURIComponent(credentialId)}`
: `credentials/store/system/domain/_/credential/${encodeURIComponent(credentialId)}`;

const path = `${basePath}/config.xml`;

Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Extract credential path building to utility method

The path building logic is duplicated across updateCredential, deleteCredential, and other methods. Consider adding a helper method to JenkinsPathBuilder for credential-specific paths.

This would improve maintainability and ensure consistent path construction. Would you like me to generate a utility method for credential path building?

🧰 Tools
🪛 ESLint

[error] 65-65: Delete ······

(prettier/prettier)


[error] 67-67: Delete ······

(prettier/prettier)

🤖 Prompt for AI Agents
In src/api/ci/jenkins/services/jenkins-credential.service.ts around lines 62 to
67, the logic for building the credential path is duplicated in multiple methods
like updateCredential and deleteCredential. To fix this, create a utility method
in JenkinsPathBuilder that accepts folderName and credentialId as parameters and
returns the constructed credential path string. Replace all instances of the
duplicated path construction with calls to this new helper method to improve
maintainability and consistency.

Comment on lines +53 to +56
} catch (error) {
const jobPath = options.folderName ? `${options.folderName}/${options.jobName}` : options.jobName;
throw new JenkinsJobNotFoundError(jobPath);
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Use appropriate error type for job creation failure

Throwing JenkinsJobNotFoundError when job creation fails is semantically incorrect. Consider creating a JenkinsJobCreationError or using a more generic JenkinsError with appropriate context.

     } catch (error) {
       const jobPath = options.folderName ? `${options.folderName}/${options.jobName}` : options.jobName;
-      throw new JenkinsJobNotFoundError(jobPath);
+      throw new JenkinsError(
+        `Failed to create job: ${jobPath}`,
+        undefined,
+        error instanceof Error ? error : undefined
+      );
     }
🧰 Tools
🪛 ESLint

[error] 54-54: Replace ·?·${options.folderName}/${options.jobName}`` with ⏎········?·${options.folderName}/${options.jobName}`⏎·······`

(prettier/prettier)

🤖 Prompt for AI Agents
In src/api/ci/jenkins/services/jenkins-job.service.ts around lines 53 to 56, the
catch block throws a JenkinsJobNotFoundError on job creation failure, which is
semantically incorrect. Replace this with a new error type
JenkinsJobCreationError or a generic JenkinsError that better reflects a job
creation failure, and update the thrown error to include relevant context about
the failure.

Comment on lines +29 to +36
private escapeXml(text: string): string {
return text
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&#39;');
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

DRY violation: Duplicated XML escaping logic.

Both credential strategies implement identical XML escaping methods. This violates the DRY principle and makes maintenance harder.

Extract the XML escaping to a shared utility function:

+/**
+ * Escape XML special characters to prevent injection
+ */
+function escapeXml(text: string): string {
+  return text
+    .replace(/&/g, '&amp;')
+    .replace(/</g, '&lt;')
+    .replace(/>/g, '&gt;')
+    .replace(/"/g, '&quot;')
+    .replace(/'/g, '&#39;');
+}

 export class SecretTextCredentialStrategy implements CredentialStrategy {
   buildXml(credentialId: string, secretValue: string): string {
     return `<org.jenkinsci.plugins.plaincredentials.impl.StringCredentialsImpl plugin="${JenkinsConfig.PLUGINS.PLAIN_CREDENTIALS}">
   <scope>GLOBAL</scope>
-  <id>${this.escapeXml(credentialId)}</id>
-  <description>Secret variable for ${this.escapeXml(credentialId)}</description>
-  <secret>${this.escapeXml(secretValue)}</secret>
+  <id>${escapeXml(credentialId)}</id>
+  <description>Secret variable for ${escapeXml(credentialId)}</description>
+  <secret>${escapeXml(secretValue)}</secret>
 </org.jenkinsci.plugins.plaincredentials.impl.StringCredentialsImpl>`;
   }

-  private escapeXml(text: string): string {
-    return text
-      .replace(/&/g, '&amp;')
-      .replace(/</g, '&lt;')
-      .replace(/>/g, '&gt;')
-      .replace(/"/g, '&quot;')
-      .replace(/'/g, '&#39;');
-  }

Apply similar changes to UsernamePasswordCredentialStrategy.

Also applies to: 71-78

🤖 Prompt for AI Agents
In src/api/ci/jenkins/strategies/credential.strategy.ts around lines 29 to 36
and 71 to 78, the XML escaping logic is duplicated in both credential
strategies. To fix this, extract the escapeXml method into a shared utility
function in a common helper file. Then, replace the duplicated methods in both
strategies by importing and using this shared utility function, ensuring the
code adheres to the DRY principle and is easier to maintain.

Comment on lines 84 to 163
export class CredentialStrategyFactory {
private static strategies = new Map<CredentialType, CredentialStrategy>([
[CredentialType.SECRET_TEXT, new SecretTextCredentialStrategy()],
[CredentialType.USERNAME_PASSWORD, new UsernamePasswordCredentialStrategy()],
]);

/**
* Create a credential strategy for the given type
*/
static create(type: CredentialType): CredentialStrategy {
const strategy = this.strategies.get(type);

if (!strategy) {
throw new Error(`Unsupported credential type: ${type}`);
}

return strategy;
}

/**
* Get all supported credential types
*/
static getSupportedTypes(): CredentialType[] {
return Array.from(this.strategies.keys());
}

/**
* Check if a credential type is supported
*/
static isSupported(type: CredentialType): boolean {
return this.strategies.has(type);
}
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Refactor static-only factory class to use functions or namespace.

The static analysis correctly identifies that this class contains only static members, which can be confusing and is generally not recommended in TypeScript.

Consider refactoring to use module-level functions or a namespace:

-export class CredentialStrategyFactory {
-  private static strategies = new Map<CredentialType, CredentialStrategy>([
+const strategies = new Map<CredentialType, CredentialStrategy>([
   [CredentialType.SECRET_TEXT, new SecretTextCredentialStrategy()],
   [CredentialType.USERNAME_PASSWORD, new UsernamePasswordCredentialStrategy()],
 ]);

-  /**
-   * Create a credential strategy for the given type
-   */
-  static create(type: CredentialType): CredentialStrategy {
-    const strategy = this.strategies.get(type);
+/**
+ * Create a credential strategy for the given type
+ */
+export function createCredentialStrategy(type: CredentialType): CredentialStrategy {
+  const strategy = strategies.get(type);
   
   if (!strategy) {
     throw new Error(`Unsupported credential type: ${type}`);
   }
   
   return strategy;
-  }
+}

-  /**
-   * Get all supported credential types
-   */
-  static getSupportedTypes(): CredentialType[] {
-    return Array.from(this.strategies.keys());
-  }
+/**
+ * Get all supported credential types
+ */
+export function getSupportedCredentialTypes(): CredentialType[] {
+  return Array.from(strategies.keys());
+}

-  /**
-   * Check if a credential type is supported
-   */
-  static isSupported(type: CredentialType): boolean {
-    return this.strategies.has(type);
-  }
-}
+/**
+ * Check if a credential type is supported
+ */
+export function isCredentialTypeSupported(type: CredentialType): boolean {
+  return strategies.has(type);
+}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export class CredentialStrategyFactory {
private static strategies = new Map<CredentialType, CredentialStrategy>([
[CredentialType.SECRET_TEXT, new SecretTextCredentialStrategy()],
[CredentialType.USERNAME_PASSWORD, new UsernamePasswordCredentialStrategy()],
]);
/**
* Create a credential strategy for the given type
*/
static create(type: CredentialType): CredentialStrategy {
const strategy = this.strategies.get(type);
if (!strategy) {
throw new Error(`Unsupported credential type: ${type}`);
}
return strategy;
}
/**
* Get all supported credential types
*/
static getSupportedTypes(): CredentialType[] {
return Array.from(this.strategies.keys());
}
/**
* Check if a credential type is supported
*/
static isSupported(type: CredentialType): boolean {
return this.strategies.has(type);
}
}
const strategies = new Map<CredentialType, CredentialStrategy>([
[CredentialType.SECRET_TEXT, new SecretTextCredentialStrategy()],
[CredentialType.USERNAME_PASSWORD, new UsernamePasswordCredentialStrategy()],
]);
/**
* Create a credential strategy for the given type
*/
export function createCredentialStrategy(type: CredentialType): CredentialStrategy {
const strategy = strategies.get(type);
if (!strategy) {
throw new Error(`Unsupported credential type: ${type}`);
}
return strategy;
}
/**
* Get all supported credential types
*/
export function getSupportedCredentialTypes(): CredentialType[] {
return Array.from(strategies.keys());
}
/**
* Check if a credential type is supported
*/
export function isCredentialTypeSupported(type: CredentialType): boolean {
return strategies.has(type);
}
🧰 Tools
🪛 Biome (1.9.4)

[error] 84-116: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)


[error] 94-94: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 107-107: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 114-114: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)

🪛 ESLint

[error] 95-95: Delete ····

(prettier/prettier)


[error] 99-99: Delete ····

(prettier/prettier)


[error] 116-116: Replace · with

(prettier/prettier)

🤖 Prompt for AI Agents
In src/api/ci/jenkins/strategies/credential.strategy.ts between lines 84 and
116, the CredentialStrategyFactory class only contains static members, which is
not recommended in TypeScript. Refactor this class by removing the class
structure and instead implement the functionality as module-level functions or
group them inside a namespace. This involves converting the static methods into
standalone functions and replacing the static strategies map with a module-level
constant, ensuring the same functionality is preserved without using a
static-only class.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🔭 Outside diff range comments (2)
src/rhtap/core/integration/ci/providers/jenkinsCI.ts (2)

1-9: Fix duplicate imports causing compilation errors.

The import statement contains duplicate declarations that will prevent compilation:

  • JenkinsBuildResult is imported twice (lines 4 and 6)
  • JenkinsBuild is imported twice (lines 3 and 8)

Apply this diff to fix the duplicate imports:

import {
  CredentialType,
  JenkinsBuild,
  JenkinsBuildResult,
  JenkinsBuildTrigger,
-  JenkinsBuildResult,
  JenkinsClient,
-  JenkinsBuild,
} from '../../../../../../src/api/ci/jenkins';

552-600: Remove duplicate method definition.

The convertBuildToPipeline method is defined twice in this class (first at lines 32-84). This duplicate definition will cause a compilation error.

Remove this duplicate method definition entirely, keeping only the first implementation.

♻️ Duplicate comments (12)
src/api/ci/jenkins/config/jenkins.config.ts (1)

4-44: The static-only class anti-pattern still needs to be addressed.

This issue was previously identified and the recommendation to refactor to a const object or namespace remains valid. The current implementation violates the noStaticOnlyClass lint rule and has formatting issues.

src/api/ci/jenkins/strategies/credential.strategy.ts (2)

29-36: DRY violation: Duplicated XML escaping logic.

Both credential strategies implement identical XML escaping methods. This violates the DRY principle and makes maintenance harder.

Extract the XML escaping to a shared utility function as suggested in the previous review.

Also applies to: 71-78


84-116: Refactor static-only factory class to use functions or namespace.

The static analysis correctly identifies that this class contains only static members, which can be confusing and is generally not recommended in TypeScript.

Consider refactoring to use module-level functions or a namespace as suggested in the previous review.

src/api/ci/jenkins/services/jenkins-credential.service.ts (1)

62-67: Extract duplicated credential path building logic.

The path building logic is duplicated across multiple methods (updateCredential, deleteCredential, getCredential). This violates the DRY principle and could lead to maintenance issues.

Consider extracting this logic to a utility method in JenkinsPathBuilder for credential-specific paths as suggested in the previous review.

Also applies to: 85-90, 123-128

src/api/ci/jenkins/http/jenkins-http.client.ts (2)

58-61: Fix variable scoping in switch statement.

The retryAfter variable declaration can be accessed by other switch cases, which could lead to unexpected behavior.

Wrap the case 429 block in braces {} to create proper block scope as suggested in the previous review.


112-117: Remove redundant status check.

This status check is unnecessary because the response interceptor already handles non-2xx status codes by throwing appropriate errors.

Remove the redundant if statement as suggested in the previous review.

src/api/ci/jenkins/services/jenkins-job.service.ts (1)

53-56: Use appropriate error type for job creation failure.

Throwing JenkinsJobNotFoundError when job creation fails is semantically incorrect. Consider creating a JenkinsJobCreationError or using a more generic JenkinsError with appropriate context.

     } catch (error) {
       const jobPath = options.folderName ? `${options.folderName}/${options.jobName}` : options.jobName;
-      throw new JenkinsJobNotFoundError(jobPath);
+      throw new JenkinsError(
+        `Failed to create job: ${jobPath}`,
+        undefined,
+        error instanceof Error ? error : undefined
+      );
     }
src/api/ci/jenkins/services/jenkins-build.service.ts (2)

210-253: Remove debug console.log statements.

Multiple console.log statements appear to be debug code that should not be in production. Consider using a proper logging framework with configurable log levels or removing these statements entirely.

Remove all console.log statements in this method:

  • Line 210
  • Line 221
  • Line 224
  • Line 232
  • Lines 242-244
  • Lines 251-253

307-365: Remove debug console.log statements and improve optional chaining.

This method contains multiple console.log debug statements that should be removed. Additionally, some conditional checks could be simplified with optional chaining.

Remove console.log statements at lines: 307, 318, 331, 342, 353, 361, 364

Apply optional chaining improvements:

-    if (cause.shortDescription && cause.shortDescription.includes(normalizedCommitSha)) {
+    if (cause.shortDescription?.includes(normalizedCommitSha)) {
       console.log(`Found matching commit in build causes: ${cause.shortDescription}`);
       return true;
     }

-    if (build.displayName && build.displayName.includes(normalizedCommitSha)) {
+    if (build.displayName?.includes(normalizedCommitSha)) {
       console.log(`Found matching commit in build display name: ${build.displayName}`);
       return true;
-    } else if (build.description && build.description.includes(normalizedCommitSha)) {
+    } else if (build.description?.includes(normalizedCommitSha)) {
       console.log(`Found matching commit in build description: ${build.description}`);
       return true;
     }
src/api/ci/jenkins/jenkins.client.ts (3)

70-85: Add runtime validation for legacy method parameters.

The non-null assertion on line 74 (repoUrl!) could cause runtime errors if the method is called with undefined parameters. Consider adding validation.

   if (typeof optionsOrJobName === 'string') {
     // Legacy method signature
+    if (!repoUrl) {
+      throw new Error('repoUrl is required when using legacy method signature');
+    }
     const options: CreateJobOptions = {
       jobName: optionsOrJobName,
-      repoUrl: repoUrl!,
+      repoUrl: repoUrl,
       folderName,
       branch,
       jenkinsfilePath,
       credentialId,
     };
     return this.jobService.createJob(options);
   }

244-265: Validate required parameters in waitForBuildCompletion.

The non-null assertion on line 255 should be replaced with proper validation.

   if (typeof optionsOrJobName === 'string') {
     // Legacy method signature
+    if (buildNumber === undefined) {
+      throw new Error('buildNumber is required when using legacy method signature');
+    }
     const options: WaitForBuildOptions = {
       jobName: optionsOrJobName,
-      buildNumber: buildNumber!,
+      buildNumber: buildNumber,
       folderName,
       timeoutMs,
       pollIntervalMs,
     };
     return this.buildService.waitForBuildCompletion(options);
   }

277-296: Validate required parameters in getBuildByCommitSha.

The non-null assertion on line 287 should be replaced with validation.

   if (typeof optionsOrJobName === 'string') {
     // Legacy method signature
+    if (!commitSha) {
+      throw new Error('commitSha is required when using legacy method signature');
+    }
     const options: BuildSearchOptions = {
       jobName: optionsOrJobName,
-      commitSha: commitSha!,
+      commitSha: commitSha,
       folderName,
       maxBuildsToCheck,
     };
     return this.buildService.getBuildByCommitSha(options);
   }
🧹 Nitpick comments (7)
src/api/ci/jenkins/enums/jenkins.enums.ts (1)

4-30: LGTM! Fix minor formatting issue.

The enum definitions are well-structured and comprehensive. Just needs a minor formatting fix:

export enum CredentialType {
  SECRET_TEXT = 'Secret text',
  USERNAME_PASSWORD = 'Username with password',
-} 
+}
src/api/ci/jenkins/index.ts (1)

1-28: LGTM! Well-organized barrel exports with minor formatting fix needed.

The module organization is excellent, providing a clean API surface with logical grouping. Just needs a formatting fix:

// Export a facade for backwards compatibility and convenience
-export { JenkinsClient } from './jenkins.client'; 
+export { JenkinsClient } from './jenkins.client';
src/api/ci/jenkins/types/jenkins.types.ts (2)

6-6: Consider improving type safety for Jenkins API responses.

While some any types are understandable for dynamic Jenkins API responses, consider creating more specific interfaces where possible to improve type safety:

For example, common action types could be defined:

interface ScmAction {
  _class: string;
  lastBuiltRevision?: {
    SHA1: string;
    branch: Array<{ SHA1: string; name: string }>;
  };
}

interface CauseAction {
  _class: string;
  causes: Array<{
    shortDescription: string;
    userId?: string;
    [key: string]: any;
  }>;
}

Also applies to: 91-91, 95-95, 140-142, 150-150, 155-157


158-158: Fix formatting.

  downstreamProjects?: any[];
-} 
+}
src/api/ci/jenkins/README.md (1)

20-43: Add language specification to fenced code block.

The directory structure code block is missing a language specification, which affects readability and syntax highlighting.

Apply this diff to add the language specification:

-```
+```text
 jenkins/
 ├── enums/                    # Enums for Jenkins constants
 │   └── jenkins.enums.ts
src/api/ci/jenkins/utils/jenkins.utils.ts (1)

231-264: Well-implemented polling utility - consider function refactor.

The polling logic is excellent with proper timeout handling and generic type support. Consider refactoring to standalone functions:

-export class JenkinsPollingUtils {
-  static async pollUntil<T>(
+export async function pollUntil<T>(
     pollFn: () => Promise<T>,
     conditionFn: (result: T) => boolean,
     timeoutMs: number = JenkinsConfig.DEFAULT_TIMEOUT_MS,
     intervalMs: number = JenkinsConfig.DEFAULT_POLL_INTERVAL_MS
   ): Promise<T> {
     const startTime = Date.now();
     
     while (true) {
       const result = await pollFn();
       
       if (conditionFn(result)) {
         return result;
       }
       
       if (Date.now() - startTime > timeoutMs) {
         throw new Error(`Polling timed out after ${timeoutMs}ms`);
       }
       
-      await this.sleep(intervalMs);
+      await sleep(intervalMs);
     }
-  }
+}

-  static sleep(ms: number): Promise<void> {
+export function sleep(ms: number): Promise<void> {
     return new Promise(resolve => setTimeout(resolve, ms));
-  }
-}
+}
src/api/ci/jenkins/services/jenkins-build.service.ts (1)

75-78: Avoid type assertion for trigger type.

The type assertion as JenkinsBuildTrigger could hide type mismatches. Consider ensuring determineBuildTrigger returns the proper enum type.

       // Determine trigger type if requested
       if (includeTriggerInfo) {
-        buildInfo.triggerType = JenkinsTriggerAnalyzer.determineBuildTrigger(buildInfo) as JenkinsBuildTrigger;
+        buildInfo.triggerType = JenkinsTriggerAnalyzer.determineBuildTrigger(buildInfo);
       }

Ensure determineBuildTrigger returns JenkinsBuildTrigger enum values instead of strings.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bcae555 and 93132aa.

📒 Files selected for processing (16)
  • src/api/ci/jenkins/README.md (1 hunks)
  • src/api/ci/jenkins/config/jenkins.config.ts (1 hunks)
  • src/api/ci/jenkins/enums/jenkins.enums.ts (1 hunks)
  • src/api/ci/jenkins/errors/jenkins.errors.ts (1 hunks)
  • src/api/ci/jenkins/http/jenkins-http.client.ts (1 hunks)
  • src/api/ci/jenkins/index.ts (1 hunks)
  • src/api/ci/jenkins/jenkins.client.ts (1 hunks)
  • src/api/ci/jenkins/services/jenkins-build.service.ts (1 hunks)
  • src/api/ci/jenkins/services/jenkins-credential.service.ts (1 hunks)
  • src/api/ci/jenkins/services/jenkins-job.service.ts (1 hunks)
  • src/api/ci/jenkins/strategies/credential.strategy.ts (1 hunks)
  • src/api/ci/jenkins/types/jenkins.types.ts (1 hunks)
  • src/api/ci/jenkins/utils/jenkins.utils.ts (1 hunks)
  • src/rhtap/core/integration/ci/providers/jenkinsCI.ts (2 hunks)
  • src/rhtap/postcreation/strategies/commands/addJenkinsSecretsCommand.ts (1 hunks)
  • tests/api/ci/jenkinsClient.test.ts (1 hunks)
🧬 Code Graph Analysis (2)
src/api/ci/jenkins/http/jenkins-http.client.ts (3)
src/api/ci/jenkins/index.ts (1)
  • JenkinsHttpClient (20-20)
src/api/ci/jenkins/types/jenkins.types.ts (2)
  • JenkinsClientConfig (16-20)
  • JenkinsApiResponse (6-11)
src/api/ci/jenkins/errors/jenkins.errors.ts (3)
  • JenkinsError (4-18)
  • JenkinsAuthenticationError (75-80)
  • JenkinsRateLimitError (85-93)
src/api/ci/jenkins/strategies/credential.strategy.ts (1)
src/api/ci/jenkins/config/jenkins.config.ts (1)
  • JenkinsConfig (4-44)
🪛 ESLint
src/api/ci/jenkins/types/jenkins.types.ts

[error] 1-1: Replace JenkinsBuildResult,·JenkinsBuildTrigger,·CredentialType with CredentialType,·JenkinsBuildResult,·JenkinsBuildTrigger

(prettier/prettier)


[error] 1-1: 'CredentialType' is defined but never used.

(@typescript-eslint/no-unused-vars)


[error] 6-6: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 91-91: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 95-95: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 140-140: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 141-141: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 142-142: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 150-150: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 155-155: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 156-156: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 157-157: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 158-158: Replace · with

(prettier/prettier)

src/api/ci/jenkins/utils/jenkins.utils.ts

[error] 1-1: Replace CreateJobOptions·}·from·'../types/jenkins.types with JenkinsConfig·}·from·'../config/jenkins.config

(prettier/prettier)


[error] 2-2: Replace JenkinsConfig·}·from·'../config/jenkins.config with CreateJobOptions·}·from·'../types/jenkins.types

(prettier/prettier)


[error] 12-12: Delete ·

(prettier/prettier)


[error] 21-21: Delete ·

(prettier/prettier)


[error] 48-48: Replace jobName:·string,·buildNumber:·number,·folderName?:·string,·endpoint:·string·=·'' with ⏎····jobName:·string,⏎····buildNumber:·number,⏎····folderName?:·string,⏎····endpoint:·string·=·''⏎··

(prettier/prettier)


[error] 75-75: Delete ·

(prettier/prettier)


[error] 76-76: Delete ·

(prettier/prettier)


[error] 77-77: Delete ·

(prettier/prettier)


[error] 78-78: Delete ·

(prettier/prettier)


[error] 79-79: Replace · with ,

(prettier/prettier)


[error] 81-81: Delete ····

(prettier/prettier)


[error] 140-140: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 172-172: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 173-173: Insert (⏎······

(prettier/prettier)


[error] 174-174: Delete ·····

(prettier/prettier)


[error] 175-175: Delete ·····

(prettier/prettier)


[error] 176-176: Replace ·····(action.parameters·&&·action.parameters.some((p:·any)·=> with (action.parameters·&&⏎········action.parameters.some(

(prettier/prettier)


[error] 176-176: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 177-177: Replace ···p.name?.includes('ghpr')·||·p.name?.includes('pull')·||·p.name?.includes('PR')) with (p:·any)·=>·p.name?.includes('ghpr')·||·p.name?.includes('pull')·||·p.name?.includes('PR')⏎········))⏎····

(prettier/prettier)


[error] 183-183: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 190-190: Replace description.includes('pull·request')·|| with ⏎······description.includes('pull·request')·||⏎·····

(prettier/prettier)


[error] 191-191: Replace ········cause._class?.toLowerCase().includes('pullrequest') with ······cause._class?.toLowerCase().includes('pullrequest')⏎····

(prettier/prettier)


[error] 195-195: Insert ⏎······

(prettier/prettier)


[error] 196-196: Replace ········ with ······

(prettier/prettier)


[error] 197-197: Replace ··cause._class?.includes('GitLabWebHookCause') with cause._class?.includes('GitLabWebHookCause')⏎····

(prettier/prettier)


[error] 201-202: Delete ⏎·······

(prettier/prettier)


[error] 206-207: Delete ⏎·······

(prettier/prettier)


[error] 211-212: Delete ⏎·······

(prettier/prettier)


[error] 222-222: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 223-223: Replace build.actions·&&·build.actions.some( with (⏎······build.actions·&&⏎······build.actions.some(⏎········

(prettier/prettier)


[error] 223-223: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 224-224: Replace ······action._class?.includes('git')·||·action.lastBuiltRevision·||·action.buildsByBranchName with ··········action._class?.includes('git')·||·action.lastBuiltRevision·||·action.buildsByBranchName⏎······)⏎····

(prettier/prettier)


[error] 242-242: Delete ····

(prettier/prettier)


[error] 245-245: Delete ······

(prettier/prettier)


[error] 249-249: Delete ······

(prettier/prettier)


[error] 253-253: Delete ······

(prettier/prettier)


[error] 264-264: Replace · with

(prettier/prettier)

src/api/ci/jenkins/services/jenkins-job.service.ts

[error] 1-1: Replace HttpClient·}·from·'../http/jenkins-http.client with Config·}·from·'../config/jenkins.config

(prettier/prettier)


[error] 2-7: Replace ·⏎··JenkinsApiResponse,·⏎··FolderConfig,·⏎··CreateJobOptions,⏎··JenkinsJob⏎}·from·'../types/jenkins.type with ·JenkinsFolderError,·JenkinsJobNotFoundError·}·from·'../errors/jenkins.error

(prettier/prettier)


[error] 8-8: Replace Config·}·from·'../config/jenkins.config with HttpClient·}·from·'../http/jenkins-http.client

(prettier/prettier)


[error] 9-9: Replace ·JenkinsPathBuilder,·JenkinsXmlBuilder·}·from·'../utils/jenkins.util with ⏎··CreateJobOptions,⏎··FolderConfig,⏎··JenkinsApiResponse,⏎··JenkinsJob,⏎}·from·'../types/jenkins.type

(prettier/prettier)


[error] 10-10: Replace FolderError,·JenkinsJobNotFoundError·}·from·'../errors/jenkins.error with PathBuilder,·JenkinsXmlBuilder·}·from·'../utils/jenkins.util

(prettier/prettier)


[error] 25-25: Delete ······

(prettier/prettier)


[error] 27-27: Delete ······

(prettier/prettier)


[error] 45-45: Delete ······

(prettier/prettier)


[error] 51-51: Delete ······

(prettier/prettier)


[error] 54-54: Replace ·?·${options.folderName}/${options.jobName}`` with ⏎········?·${options.folderName}/${options.jobName}`⏎·······`

(prettier/prettier)


[error] 90-90: Replace ``${path}/doDelete,·'',·JenkinsConfig.HEADERS.JSON); with `⏎········`${path}/doDelete`,⏎········'',⏎········JenkinsConfig.HEADERS.JSON`

(prettier/prettier)


[error] 91-91: Insert );⏎

(prettier/prettier)


[error] 119-119: Delete ·

(prettier/prettier)


[error] 122-122: Delete ······

(prettier/prettier)


[error] 144-144: Replace ``${path}/disable,·'',·JenkinsConfig.HEADERS.JSON); with `⏎········`${path}/disable`,⏎········'',⏎········JenkinsConfig.HEADERS.JSON`

(prettier/prettier)


[error] 145-145: Insert );⏎

(prettier/prettier)


[error] 160-160: Delete ······

(prettier/prettier)


[error] 171-171: Replace jobName:·string,·configXml:·string,·folderName?:·string with ⏎····jobName:·string,⏎····configXml:·string,⏎····folderName?:·string⏎··

(prettier/prettier)


[error] 174-174: Replace ``${path}/config.xml,·configXml,·JenkinsConfig.HEADERS.XML); with `⏎········`${path}/config.xml`,⏎········configXml,⏎········JenkinsConfig.HEADERS.XML`

(prettier/prettier)


[error] 175-175: Insert );⏎

(prettier/prettier)


[error] 189-189: Replace ``${path}/config.xml,·JenkinsConfig.HEADERS.XML); with `⏎········`${path}/config.xml`,⏎········JenkinsConfig.HEADERS.XML`

(prettier/prettier)


[error] 190-190: Insert );⏎

(prettier/prettier)


[error] 197-197: Replace · with

(prettier/prettier)

src/api/ci/jenkins/services/jenkins-credential.service.ts

[error] 1-2: Replace HttpClient·}·from·'../http/jenkins-http.client';⏎import·{·JenkinsApiResponse·}·from·'../types/jenkins.types with Config·}·from·'../config/jenkins.config

(prettier/prettier)


[error] 4-4: Replace onfig·}·from·'../config/jenkins.config with redentialError·}·from·'../errors/jenkins.errors

(prettier/prettier)


[error] 5-5: Replace PathBuilder·}·from·'../utils/jenkins.utils with HttpClient·}·from·'../http/jenkins-http.client

(prettier/prettier)


[error] 7-7: Replace CredentialError·}·from·'../errors/jenkins.error with ApiResponse·}·from·'../types/jenkins.types';⏎import·{·JenkinsPathBuilder·}·from·'../utils/jenkins.util

(prettier/prettier)


[error] 27-27: Delete ······

(prettier/prettier)


[error] 30-30: Delete ······

(prettier/prettier)


[error] 33-33: Delete ······

(prettier/prettier)


[error] 35-35: Delete ······

(prettier/prettier)


[error] 57-57: Delete ······

(prettier/prettier)


[error] 60-60: Delete ······

(prettier/prettier)


[error] 65-65: Delete ······

(prettier/prettier)


[error] 67-67: Delete ······

(prettier/prettier)


[error] 69-69: Delete ······

(prettier/prettier)


[error] 88-88: Delete ······

(prettier/prettier)


[error] 90-90: Delete ······

(prettier/prettier)


[error] 92-92: Delete ······

(prettier/prettier)


[error] 120-120: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 126-126: Delete ······

(prettier/prettier)


[error] 128-128: Delete ······

(prettier/prettier)


[error] 130-130: Delete ······

(prettier/prettier)


[error] 133-136: Replace ⏎········credentialId,⏎········'Credential·not·found·or·not·accessible'⏎······ with credentialId,·'Credential·not·found·or·not·accessible'

(prettier/prettier)


[error] 143-143: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 149-149: Delete ······

(prettier/prettier)


[error] 151-151: Delete ······

(prettier/prettier)


[error] 152-152: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 157-157: Delete ······

(prettier/prettier)


[error] 188-188: Replace folderName,·credentialId,·secretValue,·CredentialType.USERNAME_PASSWORD with ⏎······folderName,⏎······credentialId,⏎······secretValue,⏎······CredentialType.USERNAME_PASSWORD⏎····

(prettier/prettier)


[error] 204-204: Replace · with

(prettier/prettier)

src/api/ci/jenkins/services/jenkins-build.service.ts

[error] 1-1: Replace HttpClient·}·from·'../http/jenkins-http.client with Config·}·from·'../config/jenkins.config

(prettier/prettier)


[error] 2-9: Replace ⏎··JenkinsApiResponse,·⏎··BuildOptions,·⏎··BuildSearchOptions,⏎··WaitForBuildOptions,⏎··JenkinsBuild,⏎··JenkinsJob⏎}·from·'../types/jenkins.type with JenkinsBuildResult,·JenkinsBuildTrigger·}·from·'../enums/jenkins.enum

(prettier/prettier)


[error] 10-10: Replace ·JenkinsBuildResult,·JenkinsBuildTrigger·}·from·'../enums/jenkins.enum with ⏎··JenkinsBuildNotFoundError,⏎··JenkinsBuildTimeoutError,⏎··JenkinsJobNotFoundError,⏎}·from·'../errors/jenkins.error

(prettier/prettier)


[error] 10-10: 'JenkinsBuildResult' is defined but never used.

(@typescript-eslint/no-unused-vars)


[error] 11-11: Replace Config·}·from·'../config/jenkins.config with HttpClient·}·from·'../http/jenkins-http.client

(prettier/prettier)


[error] 12-12: Delete ·

(prettier/prettier)


[error] 13-13: Replace JenkinsPathBuilder,· with BuildOptions,⏎··BuildSearchOptions,

(prettier/prettier)


[error] 14-14: Replace TriggerAnalyzer,· with ApiResponse,⏎··JenkinsBuild,

(prettier/prettier)


[error] 15-15: Replace PollingUtils· with Job,⏎··WaitForBuildOptions,

(prettier/prettier)


[error] 16-16: Replace utils/jenkins.util with types/jenkins.type

(prettier/prettier)


[error] 17-17: Delete ·

(prettier/prettier)


[error] 18-18: Replace BuildNotFoundError,· with PathBuilder,

(prettier/prettier)


[error] 19-19: Replace BuildTimeoutError with PollingUtils

(prettier/prettier)


[error] 20-20: Replace JobNotFoundError· with TriggerAnalyzer,

(prettier/prettier)


[error] 21-21: Replace errors/jenkins.error with utils/jenkins.util

(prettier/prettier)


[error] 35-35: Delete ·

(prettier/prettier)


[error] 36-36: Delete ·

(prettier/prettier)


[error] 38-38: Delete ······

(prettier/prettier)


[error] 40-40: Delete ·

(prettier/prettier)


[error] 41-41: Delete ·

(prettier/prettier)


[error] 42-42: Delete ·

(prettier/prettier)


[error] 45-45: Delete ······

(prettier/prettier)


[error] 48-48: Replace ·?·${options.folderName}/${options.jobName}`` with ⏎········?·${options.folderName}/${options.jobName}`⏎·······`

(prettier/prettier)


[error] 57-57: Delete ·

(prettier/prettier)


[error] 58-58: Delete ·

(prettier/prettier)


[error] 64-64: Delete ·

(prettier/prettier)


[error] 65-65: Delete ·

(prettier/prettier)


[error] 66-66: Delete ·

(prettier/prettier)


[error] 69-69: Delete ······

(prettier/prettier)


[error] 70-73: Replace ⏎········path,⏎········JenkinsConfig.HEADERS.JSON⏎······ with path,·JenkinsConfig.HEADERS.JSON

(prettier/prettier)


[error] 77-77: Replace buildInfo with ⏎··········buildInfo⏎········

(prettier/prettier)


[error] 92-92: Delete ······

(prettier/prettier)


[error] 151-151: Delete ·

(prettier/prettier)


[error] 152-152: Delete ·

(prettier/prettier)


[error] 153-153: Delete ·

(prettier/prettier)


[error] 157-159: Replace ⏎········path,⏎········JenkinsConfig.HEADERS.PLAIN, with path,·JenkinsConfig.HEADERS.PLAIN,·{

(prettier/prettier)


[error] 160-160: Replace {·start:·0·} with start:·0,

(prettier/prettier)


[error] 161-161: Insert }

(prettier/prettier)


[error] 178-178: Insert ,

(prettier/prettier)


[error] 204-204: Insert ,

(prettier/prettier)


[error] 234-234: Delete ········

(prettier/prettier)


[error] 264-264: Delete ·

(prettier/prettier)


[error] 265-265: Delete ·

(prettier/prettier)


[error] 276-276: Delete ·

(prettier/prettier)


[error] 277-277: Delete ·

(prettier/prettier)


[error] 288-288: Delete ·

(prettier/prettier)


[error] 289-289: Delete ·

(prettier/prettier)


[error] 318-318: Replace Found·matching·commit·in·buildsByBranchName·for·branch·${branch}:·${branchSha} with ⏎··················Found·matching·commit·in·buildsByBranchName·for·branch·${branch}:·${branchSha}⏎················

(prettier/prettier)


[error] 328-328: Replace (param.name·===·'GIT_COMMIT'·||·param.name·===·'ghprbActualCommit')·&&·param.value with ⏎··············(param.name·===·'GIT_COMMIT'·||·param.name·===·'ghprbActualCommit')·&&⏎··············param.value⏎············

(prettier/prettier)


[error] 377-377: Replace · with

(prettier/prettier)

src/api/ci/jenkins/config/jenkins.config.ts

[error] 11-11: Delete ··

(prettier/prettier)


[error] 17-17: Replace 'Accept' with Accept

(prettier/prettier)


[error] 18-18: Replace 'Accept' with Accept

(prettier/prettier)


[error] 44-44: Replace · with

(prettier/prettier)

src/api/ci/jenkins/enums/jenkins.enums.ts

[error] 30-30: Replace · with

(prettier/prettier)

src/api/ci/jenkins/errors/jenkins.errors.ts

[error] 12-12: Delete ····

(prettier/prettier)


[error] 87-87: Delete ·

(prettier/prettier)


[error] 93-93: Replace · with

(prettier/prettier)

src/api/ci/jenkins/http/jenkins-http.client.ts

[error] 1-1: Replace axios,·{·AxiosInstance,·AxiosRequestConfig,·AxiosResponse·}·from·'axio with {⏎··JenkinsAuthenticationError,⏎··JenkinsError,⏎··JenkinsRateLimitError,⏎}·from·'../errors/jenkins.error

(prettier/prettier)


[error] 2-2: Replace ClientConfig,·JenkinsApiResponse with ApiResponse,·JenkinsClientConfig

(prettier/prettier)


[error] 3-7: Replace {·⏎··JenkinsError,·⏎··JenkinsAuthenticationError,·⏎··JenkinsRateLimitError·⏎}·from·'../errors/jenkins.error with axios,·{·AxiosInstance,·AxiosRequestConfig,·AxiosResponse·}·from·'axio

(prettier/prettier)


[error] 64-68: Replace ⏎················Jenkins·API·request·failed:·${message},⏎················status,⏎················error⏎·············· with ``Jenkins·API·request·failed:·${message},·status,·error

(prettier/prettier)


[error] 82-82: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 83-83: Delete ·

(prettier/prettier)


[error] 85-85: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 99-99: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 101-101: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 103-103: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 111-111: Delete ····

(prettier/prettier)


[error] 130-130: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 132-132: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 136-136: Delete ····

(prettier/prettier)


[error] 148-148: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 153-153: Delete ····

(prettier/prettier)


[error] 184-184: Replace · with

(prettier/prettier)

src/api/ci/jenkins/index.ts

[error] 28-28: Replace · with

(prettier/prettier)

src/api/ci/jenkins/jenkins.client.ts

[error] 1-1: Replace JenkinsHttpClient·}·from·'./http/jenkins-http.client with CredentialType,·JenkinsBuildTrigger·}·from·'./enums/jenkins.enums

(prettier/prettier)


[error] 2-2: Replace JobService·}·from·'./services/jenkins-job.service with HttpClient·}·from·'./http/jenkins-http.client

(prettier/prettier)


[error] 5-9: Replace ⏎··JenkinsClientConfig,⏎··JenkinsApiResponse,⏎··FolderConfig,⏎··CreateJobOptions, with JenkinsJobService·}·from·'./services/jenkins-job.service';⏎import·{

(prettier/prettier)


[error] 12-12: Replace WaitForBuild with CreateJob

(prettier/prettier)


[error] 13-13: Replace JenkinsBuild with FolderConfig,⏎··JenkinsApiResponse

(prettier/prettier)


[error] 14-14: Replace Job with Build,

(prettier/prettier)


[error] 15-16: Replace }·from·'./types/jenkins.types';⏎import·{·CredentialType,·JenkinsBuildTrigger·}·from·'./enums/jenkins.enum with ··JenkinsClientConfig,⏎··JenkinsJob,⏎··WaitForBuildOptions,⏎}·from·'./types/jenkins.type

(prettier/prettier)


[error] 142-142: Replace folderName,·credentialId,·secretValue,·credentialType with ⏎······folderName,⏎······credentialId,⏎······secretValue,⏎······credentialType⏎····

(prettier/prettier)


[error] 165-165: Replace folderName,·credentialId,·username,·password with ⏎······folderName,⏎······credentialId,⏎······username,⏎······password⏎····

(prettier/prettier)


[error] 380-380: Replace · with

(prettier/prettier)

src/api/ci/jenkins/strategies/credential.strategy.ts

[error] 1-1: Replace CredentialType·}·from·'../enums/jenkins.enums with JenkinsConfig·}·from·'../config/jenkins.config

(prettier/prettier)


[error] 2-2: Replace JenkinsConfig·}·from·'../config/jenkins.config with CredentialType·}·from·'../enums/jenkins.enums

(prettier/prettier)


[error] 45-45: Delete ····

(prettier/prettier)


[error] 64-64: Delete ····

(prettier/prettier)


[error] 67-67: Delete ····

(prettier/prettier)


[error] 95-95: Delete ····

(prettier/prettier)


[error] 99-99: Delete ····

(prettier/prettier)


[error] 116-116: Replace · with

(prettier/prettier)

src/rhtap/core/integration/ci/providers/jenkinsCI.ts

[error] 6-6: Parsing error:

(prettier/prettier)

🪛 Biome (1.9.4)
src/api/ci/jenkins/utils/jenkins.utils.ts

[error] 7-52: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)


[error] 49-49: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 57-131: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)


[error] 64-64: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 100-100: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 101-101: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 106-106: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 113-113: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 136-226: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)


[error] 145-145: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 154-154: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 162-162: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 176-177: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 223-224: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 231-264: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)


[error] 254-254: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)

src/api/ci/jenkins/services/jenkins-build.service.ts

[error] 352-352: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 360-360: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 363-363: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

src/api/ci/jenkins/config/jenkins.config.ts

[error] 4-44: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)

src/api/ci/jenkins/http/jenkins-http.client.ts

[error] 59-59: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)

src/api/ci/jenkins/strategies/credential.strategy.ts

[error] 84-116: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)


[error] 94-94: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 107-107: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 114-114: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)

src/rhtap/core/integration/ci/providers/jenkinsCI.ts

[error] 6-6: Declarations inside of a import declaration may not have duplicates

a second declaration of JenkinsBuildResult is not allowed

JenkinsBuildResult is first declared here

(parse)


[error] 8-8: Declarations inside of a import declaration may not have duplicates

a second declaration of JenkinsBuild is not allowed

JenkinsBuild is first declared here

(parse)

🪛 markdownlint-cli2 (0.17.2)
src/api/ci/jenkins/README.md

20-20: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

✅ Files skipped from review due to trivial changes (1)
  • src/rhtap/postcreation/strategies/commands/addJenkinsSecretsCommand.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/api/ci/jenkinsClient.test.ts
🧰 Additional context used
🧬 Code Graph Analysis (2)
src/api/ci/jenkins/http/jenkins-http.client.ts (3)
src/api/ci/jenkins/index.ts (1)
  • JenkinsHttpClient (20-20)
src/api/ci/jenkins/types/jenkins.types.ts (2)
  • JenkinsClientConfig (16-20)
  • JenkinsApiResponse (6-11)
src/api/ci/jenkins/errors/jenkins.errors.ts (3)
  • JenkinsError (4-18)
  • JenkinsAuthenticationError (75-80)
  • JenkinsRateLimitError (85-93)
src/api/ci/jenkins/strategies/credential.strategy.ts (1)
src/api/ci/jenkins/config/jenkins.config.ts (1)
  • JenkinsConfig (4-44)
🪛 ESLint
src/api/ci/jenkins/types/jenkins.types.ts

[error] 1-1: Replace JenkinsBuildResult,·JenkinsBuildTrigger,·CredentialType with CredentialType,·JenkinsBuildResult,·JenkinsBuildTrigger

(prettier/prettier)


[error] 1-1: 'CredentialType' is defined but never used.

(@typescript-eslint/no-unused-vars)


[error] 6-6: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 91-91: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 95-95: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 140-140: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 141-141: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 142-142: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 150-150: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 155-155: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 156-156: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 157-157: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 158-158: Replace · with

(prettier/prettier)

src/api/ci/jenkins/utils/jenkins.utils.ts

[error] 1-1: Replace CreateJobOptions·}·from·'../types/jenkins.types with JenkinsConfig·}·from·'../config/jenkins.config

(prettier/prettier)


[error] 2-2: Replace JenkinsConfig·}·from·'../config/jenkins.config with CreateJobOptions·}·from·'../types/jenkins.types

(prettier/prettier)


[error] 12-12: Delete ·

(prettier/prettier)


[error] 21-21: Delete ·

(prettier/prettier)


[error] 48-48: Replace jobName:·string,·buildNumber:·number,·folderName?:·string,·endpoint:·string·=·'' with ⏎····jobName:·string,⏎····buildNumber:·number,⏎····folderName?:·string,⏎····endpoint:·string·=·''⏎··

(prettier/prettier)


[error] 75-75: Delete ·

(prettier/prettier)


[error] 76-76: Delete ·

(prettier/prettier)


[error] 77-77: Delete ·

(prettier/prettier)


[error] 78-78: Delete ·

(prettier/prettier)


[error] 79-79: Replace · with ,

(prettier/prettier)


[error] 81-81: Delete ····

(prettier/prettier)


[error] 140-140: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 172-172: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 173-173: Insert (⏎······

(prettier/prettier)


[error] 174-174: Delete ·····

(prettier/prettier)


[error] 175-175: Delete ·····

(prettier/prettier)


[error] 176-176: Replace ·····(action.parameters·&&·action.parameters.some((p:·any)·=> with (action.parameters·&&⏎········action.parameters.some(

(prettier/prettier)


[error] 176-176: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 177-177: Replace ···p.name?.includes('ghpr')·||·p.name?.includes('pull')·||·p.name?.includes('PR')) with (p:·any)·=>·p.name?.includes('ghpr')·||·p.name?.includes('pull')·||·p.name?.includes('PR')⏎········))⏎····

(prettier/prettier)


[error] 183-183: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 190-190: Replace description.includes('pull·request')·|| with ⏎······description.includes('pull·request')·||⏎·····

(prettier/prettier)


[error] 191-191: Replace ········cause._class?.toLowerCase().includes('pullrequest') with ······cause._class?.toLowerCase().includes('pullrequest')⏎····

(prettier/prettier)


[error] 195-195: Insert ⏎······

(prettier/prettier)


[error] 196-196: Replace ········ with ······

(prettier/prettier)


[error] 197-197: Replace ··cause._class?.includes('GitLabWebHookCause') with cause._class?.includes('GitLabWebHookCause')⏎····

(prettier/prettier)


[error] 201-202: Delete ⏎·······

(prettier/prettier)


[error] 206-207: Delete ⏎·······

(prettier/prettier)


[error] 211-212: Delete ⏎·······

(prettier/prettier)


[error] 222-222: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 223-223: Replace build.actions·&&·build.actions.some( with (⏎······build.actions·&&⏎······build.actions.some(⏎········

(prettier/prettier)


[error] 223-223: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 224-224: Replace ······action._class?.includes('git')·||·action.lastBuiltRevision·||·action.buildsByBranchName with ··········action._class?.includes('git')·||·action.lastBuiltRevision·||·action.buildsByBranchName⏎······)⏎····

(prettier/prettier)


[error] 242-242: Delete ····

(prettier/prettier)


[error] 245-245: Delete ······

(prettier/prettier)


[error] 249-249: Delete ······

(prettier/prettier)


[error] 253-253: Delete ······

(prettier/prettier)


[error] 264-264: Replace · with

(prettier/prettier)

src/api/ci/jenkins/services/jenkins-job.service.ts

[error] 1-1: Replace HttpClient·}·from·'../http/jenkins-http.client with Config·}·from·'../config/jenkins.config

(prettier/prettier)


[error] 2-7: Replace ·⏎··JenkinsApiResponse,·⏎··FolderConfig,·⏎··CreateJobOptions,⏎··JenkinsJob⏎}·from·'../types/jenkins.type with ·JenkinsFolderError,·JenkinsJobNotFoundError·}·from·'../errors/jenkins.error

(prettier/prettier)


[error] 8-8: Replace Config·}·from·'../config/jenkins.config with HttpClient·}·from·'../http/jenkins-http.client

(prettier/prettier)


[error] 9-9: Replace ·JenkinsPathBuilder,·JenkinsXmlBuilder·}·from·'../utils/jenkins.util with ⏎··CreateJobOptions,⏎··FolderConfig,⏎··JenkinsApiResponse,⏎··JenkinsJob,⏎}·from·'../types/jenkins.type

(prettier/prettier)


[error] 10-10: Replace FolderError,·JenkinsJobNotFoundError·}·from·'../errors/jenkins.error with PathBuilder,·JenkinsXmlBuilder·}·from·'../utils/jenkins.util

(prettier/prettier)


[error] 25-25: Delete ······

(prettier/prettier)


[error] 27-27: Delete ······

(prettier/prettier)


[error] 45-45: Delete ······

(prettier/prettier)


[error] 51-51: Delete ······

(prettier/prettier)


[error] 54-54: Replace ·?·${options.folderName}/${options.jobName}`` with ⏎········?·${options.folderName}/${options.jobName}`⏎·······`

(prettier/prettier)


[error] 90-90: Replace ``${path}/doDelete,·'',·JenkinsConfig.HEADERS.JSON); with `⏎········`${path}/doDelete`,⏎········'',⏎········JenkinsConfig.HEADERS.JSON`

(prettier/prettier)


[error] 91-91: Insert );⏎

(prettier/prettier)


[error] 119-119: Delete ·

(prettier/prettier)


[error] 122-122: Delete ······

(prettier/prettier)


[error] 144-144: Replace ``${path}/disable,·'',·JenkinsConfig.HEADERS.JSON); with `⏎········`${path}/disable`,⏎········'',⏎········JenkinsConfig.HEADERS.JSON`

(prettier/prettier)


[error] 145-145: Insert );⏎

(prettier/prettier)


[error] 160-160: Delete ······

(prettier/prettier)


[error] 171-171: Replace jobName:·string,·configXml:·string,·folderName?:·string with ⏎····jobName:·string,⏎····configXml:·string,⏎····folderName?:·string⏎··

(prettier/prettier)


[error] 174-174: Replace ``${path}/config.xml,·configXml,·JenkinsConfig.HEADERS.XML); with `⏎········`${path}/config.xml`,⏎········configXml,⏎········JenkinsConfig.HEADERS.XML`

(prettier/prettier)


[error] 175-175: Insert );⏎

(prettier/prettier)


[error] 189-189: Replace ``${path}/config.xml,·JenkinsConfig.HEADERS.XML); with `⏎········`${path}/config.xml`,⏎········JenkinsConfig.HEADERS.XML`

(prettier/prettier)


[error] 190-190: Insert );⏎

(prettier/prettier)


[error] 197-197: Replace · with

(prettier/prettier)

src/api/ci/jenkins/services/jenkins-credential.service.ts

[error] 1-2: Replace HttpClient·}·from·'../http/jenkins-http.client';⏎import·{·JenkinsApiResponse·}·from·'../types/jenkins.types with Config·}·from·'../config/jenkins.config

(prettier/prettier)


[error] 4-4: Replace onfig·}·from·'../config/jenkins.config with redentialError·}·from·'../errors/jenkins.errors

(prettier/prettier)


[error] 5-5: Replace PathBuilder·}·from·'../utils/jenkins.utils with HttpClient·}·from·'../http/jenkins-http.client

(prettier/prettier)


[error] 7-7: Replace CredentialError·}·from·'../errors/jenkins.error with ApiResponse·}·from·'../types/jenkins.types';⏎import·{·JenkinsPathBuilder·}·from·'../utils/jenkins.util

(prettier/prettier)


[error] 27-27: Delete ······

(prettier/prettier)


[error] 30-30: Delete ······

(prettier/prettier)


[error] 33-33: Delete ······

(prettier/prettier)


[error] 35-35: Delete ······

(prettier/prettier)


[error] 57-57: Delete ······

(prettier/prettier)


[error] 60-60: Delete ······

(prettier/prettier)


[error] 65-65: Delete ······

(prettier/prettier)


[error] 67-67: Delete ······

(prettier/prettier)


[error] 69-69: Delete ······

(prettier/prettier)


[error] 88-88: Delete ······

(prettier/prettier)


[error] 90-90: Delete ······

(prettier/prettier)


[error] 92-92: Delete ······

(prettier/prettier)


[error] 120-120: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 126-126: Delete ······

(prettier/prettier)


[error] 128-128: Delete ······

(prettier/prettier)


[error] 130-130: Delete ······

(prettier/prettier)


[error] 133-136: Replace ⏎········credentialId,⏎········'Credential·not·found·or·not·accessible'⏎······ with credentialId,·'Credential·not·found·or·not·accessible'

(prettier/prettier)


[error] 143-143: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 149-149: Delete ······

(prettier/prettier)


[error] 151-151: Delete ······

(prettier/prettier)


[error] 152-152: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 157-157: Delete ······

(prettier/prettier)


[error] 188-188: Replace folderName,·credentialId,·secretValue,·CredentialType.USERNAME_PASSWORD with ⏎······folderName,⏎······credentialId,⏎······secretValue,⏎······CredentialType.USERNAME_PASSWORD⏎····

(prettier/prettier)


[error] 204-204: Replace · with

(prettier/prettier)

src/api/ci/jenkins/services/jenkins-build.service.ts

[error] 1-1: Replace HttpClient·}·from·'../http/jenkins-http.client with Config·}·from·'../config/jenkins.config

(prettier/prettier)


[error] 2-9: Replace ⏎··JenkinsApiResponse,·⏎··BuildOptions,·⏎··BuildSearchOptions,⏎··WaitForBuildOptions,⏎··JenkinsBuild,⏎··JenkinsJob⏎}·from·'../types/jenkins.type with JenkinsBuildResult,·JenkinsBuildTrigger·}·from·'../enums/jenkins.enum

(prettier/prettier)


[error] 10-10: Replace ·JenkinsBuildResult,·JenkinsBuildTrigger·}·from·'../enums/jenkins.enum with ⏎··JenkinsBuildNotFoundError,⏎··JenkinsBuildTimeoutError,⏎··JenkinsJobNotFoundError,⏎}·from·'../errors/jenkins.error

(prettier/prettier)


[error] 10-10: 'JenkinsBuildResult' is defined but never used.

(@typescript-eslint/no-unused-vars)


[error] 11-11: Replace Config·}·from·'../config/jenkins.config with HttpClient·}·from·'../http/jenkins-http.client

(prettier/prettier)


[error] 12-12: Delete ·

(prettier/prettier)


[error] 13-13: Replace JenkinsPathBuilder,· with BuildOptions,⏎··BuildSearchOptions,

(prettier/prettier)


[error] 14-14: Replace TriggerAnalyzer,· with ApiResponse,⏎··JenkinsBuild,

(prettier/prettier)


[error] 15-15: Replace PollingUtils· with Job,⏎··WaitForBuildOptions,

(prettier/prettier)


[error] 16-16: Replace utils/jenkins.util with types/jenkins.type

(prettier/prettier)


[error] 17-17: Delete ·

(prettier/prettier)


[error] 18-18: Replace BuildNotFoundError,· with PathBuilder,

(prettier/prettier)


[error] 19-19: Replace BuildTimeoutError with PollingUtils

(prettier/prettier)


[error] 20-20: Replace JobNotFoundError· with TriggerAnalyzer,

(prettier/prettier)


[error] 21-21: Replace errors/jenkins.error with utils/jenkins.util

(prettier/prettier)


[error] 35-35: Delete ·

(prettier/prettier)


[error] 36-36: Delete ·

(prettier/prettier)


[error] 38-38: Delete ······

(prettier/prettier)


[error] 40-40: Delete ·

(prettier/prettier)


[error] 41-41: Delete ·

(prettier/prettier)


[error] 42-42: Delete ·

(prettier/prettier)


[error] 45-45: Delete ······

(prettier/prettier)


[error] 48-48: Replace ·?·${options.folderName}/${options.jobName}`` with ⏎········?·${options.folderName}/${options.jobName}`⏎·······`

(prettier/prettier)


[error] 57-57: Delete ·

(prettier/prettier)


[error] 58-58: Delete ·

(prettier/prettier)


[error] 64-64: Delete ·

(prettier/prettier)


[error] 65-65: Delete ·

(prettier/prettier)


[error] 66-66: Delete ·

(prettier/prettier)


[error] 69-69: Delete ······

(prettier/prettier)


[error] 70-73: Replace ⏎········path,⏎········JenkinsConfig.HEADERS.JSON⏎······ with path,·JenkinsConfig.HEADERS.JSON

(prettier/prettier)


[error] 77-77: Replace buildInfo with ⏎··········buildInfo⏎········

(prettier/prettier)


[error] 92-92: Delete ······

(prettier/prettier)


[error] 151-151: Delete ·

(prettier/prettier)


[error] 152-152: Delete ·

(prettier/prettier)


[error] 153-153: Delete ·

(prettier/prettier)


[error] 157-159: Replace ⏎········path,⏎········JenkinsConfig.HEADERS.PLAIN, with path,·JenkinsConfig.HEADERS.PLAIN,·{

(prettier/prettier)


[error] 160-160: Replace {·start:·0·} with start:·0,

(prettier/prettier)


[error] 161-161: Insert }

(prettier/prettier)


[error] 178-178: Insert ,

(prettier/prettier)


[error] 204-204: Insert ,

(prettier/prettier)


[error] 234-234: Delete ········

(prettier/prettier)


[error] 264-264: Delete ·

(prettier/prettier)


[error] 265-265: Delete ·

(prettier/prettier)


[error] 276-276: Delete ·

(prettier/prettier)


[error] 277-277: Delete ·

(prettier/prettier)


[error] 288-288: Delete ·

(prettier/prettier)


[error] 289-289: Delete ·

(prettier/prettier)


[error] 318-318: Replace Found·matching·commit·in·buildsByBranchName·for·branch·${branch}:·${branchSha} with ⏎··················Found·matching·commit·in·buildsByBranchName·for·branch·${branch}:·${branchSha}⏎················

(prettier/prettier)


[error] 328-328: Replace (param.name·===·'GIT_COMMIT'·||·param.name·===·'ghprbActualCommit')·&&·param.value with ⏎··············(param.name·===·'GIT_COMMIT'·||·param.name·===·'ghprbActualCommit')·&&⏎··············param.value⏎············

(prettier/prettier)


[error] 377-377: Replace · with

(prettier/prettier)

src/api/ci/jenkins/config/jenkins.config.ts

[error] 11-11: Delete ··

(prettier/prettier)


[error] 17-17: Replace 'Accept' with Accept

(prettier/prettier)


[error] 18-18: Replace 'Accept' with Accept

(prettier/prettier)


[error] 44-44: Replace · with

(prettier/prettier)

src/api/ci/jenkins/enums/jenkins.enums.ts

[error] 30-30: Replace · with

(prettier/prettier)

src/api/ci/jenkins/errors/jenkins.errors.ts

[error] 12-12: Delete ····

(prettier/prettier)


[error] 87-87: Delete ·

(prettier/prettier)


[error] 93-93: Replace · with

(prettier/prettier)

src/api/ci/jenkins/http/jenkins-http.client.ts

[error] 1-1: Replace axios,·{·AxiosInstance,·AxiosRequestConfig,·AxiosResponse·}·from·'axio with {⏎··JenkinsAuthenticationError,⏎··JenkinsError,⏎··JenkinsRateLimitError,⏎}·from·'../errors/jenkins.error

(prettier/prettier)


[error] 2-2: Replace ClientConfig,·JenkinsApiResponse with ApiResponse,·JenkinsClientConfig

(prettier/prettier)


[error] 3-7: Replace {·⏎··JenkinsError,·⏎··JenkinsAuthenticationError,·⏎··JenkinsRateLimitError·⏎}·from·'../errors/jenkins.error with axios,·{·AxiosInstance,·AxiosRequestConfig,·AxiosResponse·}·from·'axio

(prettier/prettier)


[error] 64-68: Replace ⏎················Jenkins·API·request·failed:·${message},⏎················status,⏎················error⏎·············· with ``Jenkins·API·request·failed:·${message},·status,·error

(prettier/prettier)


[error] 82-82: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 83-83: Delete ·

(prettier/prettier)


[error] 85-85: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 99-99: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 101-101: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 103-103: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 111-111: Delete ····

(prettier/prettier)


[error] 130-130: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 132-132: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 136-136: Delete ····

(prettier/prettier)


[error] 148-148: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 153-153: Delete ····

(prettier/prettier)


[error] 184-184: Replace · with

(prettier/prettier)

src/api/ci/jenkins/index.ts

[error] 28-28: Replace · with

(prettier/prettier)

src/api/ci/jenkins/jenkins.client.ts

[error] 1-1: Replace JenkinsHttpClient·}·from·'./http/jenkins-http.client with CredentialType,·JenkinsBuildTrigger·}·from·'./enums/jenkins.enums

(prettier/prettier)


[error] 2-2: Replace JobService·}·from·'./services/jenkins-job.service with HttpClient·}·from·'./http/jenkins-http.client

(prettier/prettier)


[error] 5-9: Replace ⏎··JenkinsClientConfig,⏎··JenkinsApiResponse,⏎··FolderConfig,⏎··CreateJobOptions, with JenkinsJobService·}·from·'./services/jenkins-job.service';⏎import·{

(prettier/prettier)


[error] 12-12: Replace WaitForBuild with CreateJob

(prettier/prettier)


[error] 13-13: Replace JenkinsBuild with FolderConfig,⏎··JenkinsApiResponse

(prettier/prettier)


[error] 14-14: Replace Job with Build,

(prettier/prettier)


[error] 15-16: Replace }·from·'./types/jenkins.types';⏎import·{·CredentialType,·JenkinsBuildTrigger·}·from·'./enums/jenkins.enum with ··JenkinsClientConfig,⏎··JenkinsJob,⏎··WaitForBuildOptions,⏎}·from·'./types/jenkins.type

(prettier/prettier)


[error] 142-142: Replace folderName,·credentialId,·secretValue,·credentialType with ⏎······folderName,⏎······credentialId,⏎······secretValue,⏎······credentialType⏎····

(prettier/prettier)


[error] 165-165: Replace folderName,·credentialId,·username,·password with ⏎······folderName,⏎······credentialId,⏎······username,⏎······password⏎····

(prettier/prettier)


[error] 380-380: Replace · with

(prettier/prettier)

src/api/ci/jenkins/strategies/credential.strategy.ts

[error] 1-1: Replace CredentialType·}·from·'../enums/jenkins.enums with JenkinsConfig·}·from·'../config/jenkins.config

(prettier/prettier)


[error] 2-2: Replace JenkinsConfig·}·from·'../config/jenkins.config with CredentialType·}·from·'../enums/jenkins.enums

(prettier/prettier)


[error] 45-45: Delete ····

(prettier/prettier)


[error] 64-64: Delete ····

(prettier/prettier)


[error] 67-67: Delete ····

(prettier/prettier)


[error] 95-95: Delete ····

(prettier/prettier)


[error] 99-99: Delete ····

(prettier/prettier)


[error] 116-116: Replace · with

(prettier/prettier)

src/rhtap/core/integration/ci/providers/jenkinsCI.ts

[error] 6-6: Parsing error:

(prettier/prettier)

🪛 Biome (1.9.4)
src/api/ci/jenkins/utils/jenkins.utils.ts

[error] 7-52: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)


[error] 49-49: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 57-131: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)


[error] 64-64: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 100-100: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 101-101: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 106-106: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 113-113: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 136-226: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)


[error] 145-145: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 154-154: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 162-162: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 176-177: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 223-224: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 231-264: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)


[error] 254-254: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)

src/api/ci/jenkins/services/jenkins-build.service.ts

[error] 352-352: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 360-360: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 363-363: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

src/api/ci/jenkins/config/jenkins.config.ts

[error] 4-44: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)

src/api/ci/jenkins/http/jenkins-http.client.ts

[error] 59-59: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)

src/api/ci/jenkins/strategies/credential.strategy.ts

[error] 84-116: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)


[error] 94-94: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 107-107: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 114-114: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)

src/rhtap/core/integration/ci/providers/jenkinsCI.ts

[error] 6-6: Declarations inside of a import declaration may not have duplicates

a second declaration of JenkinsBuildResult is not allowed

JenkinsBuildResult is first declared here

(parse)


[error] 8-8: Declarations inside of a import declaration may not have duplicates

a second declaration of JenkinsBuild is not allowed

JenkinsBuild is first declared here

(parse)

🪛 markdownlint-cli2 (0.17.2)
src/api/ci/jenkins/README.md

20-20: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Red Hat Konflux / tssc-test-on-pull-request
🔇 Additional comments (13)
src/api/ci/jenkins/errors/jenkins.errors.ts (1)

1-93: Well-designed error hierarchy with proper inheritance.

The error class hierarchy follows TypeScript best practices with:

  • Proper inheritance from the base Error class
  • Stack trace capture for debugging
  • Meaningful error types for different failure scenarios
  • Consistent naming and structure

Note: There are minor formatting issues flagged by ESLint (extra spaces and missing newlines) that should be addressed by running the code formatter.

src/api/ci/jenkins/services/jenkins-credential.service.ts (1)

1-204: Well-structured service with comprehensive credential management.

The credential service effectively uses the strategy pattern and provides a complete set of CRUD operations for Jenkins credentials. The error handling is consistent and the convenience methods improve usability.

The service integrates well with the overall architecture and follows TypeScript best practices for dependency injection and error handling.

src/api/ci/jenkins/http/jenkins-http.client.ts (1)

9-184: Solid HTTP client abstraction with comprehensive error handling.

The HTTP client provides a well-structured abstraction layer with:

  • Proper Axios configuration and authentication
  • Request/response interceptors for logging and error handling
  • Structured response formats
  • Utility methods for server health checks

The client serves as an effective foundation for the service layer architecture.

src/api/ci/jenkins/services/jenkins-job.service.ts (6)

12-17: Clean service architecture with dependency injection.

The service class follows good design patterns with proper dependency injection and encapsulation.


18-36: Well-implemented folder creation with proper error handling.

The method correctly builds folder XML, encodes parameters, and provides meaningful error context.


59-83: Well-designed job retrieval methods.

The methods provide both direct path access and convenient name-based access with appropriate error handling.


99-112: Clean implementation of existence check.

Good use of exception handling to determine existence without exposing error details to callers.


138-166: Consistent implementation of job state management.

Both enable and disable methods follow the same pattern with appropriate endpoints and error handling.


168-196: Well-implemented configuration management methods.

Both methods correctly handle XML configuration with appropriate headers and error handling.

src/api/ci/jenkins/services/jenkins-build.service.ts (2)

86-167: Well-implemented build query methods.

These methods efficiently query build information with proper null handling and consistent error patterns.


371-376: Smart SHA comparison implementation.

Good implementation that handles both full and shortened SHA comparisons correctly.

src/api/ci/jenkins/jenkins.client.ts (2)

18-33: Excellent facade pattern implementation.

The client provides a clean facade over the service-oriented architecture with proper dependency injection and encapsulation.


349-380: Excellent service exposure for advanced usage.

The getter methods provide clean access to underlying services while maintaining encapsulation. This allows advanced users to access full functionality while keeping the main API simple.

Comment on lines +7 to +52
export class JenkinsPathBuilder {
/**
* Build a job path for API calls
*/
static buildJobPath(jobName: string, folderName?: string): string {
return folderName
? `job/${encodeURIComponent(folderName)}/job/${encodeURIComponent(jobName)}`
: `job/${encodeURIComponent(jobName)}`;
}

/**
* Build a path for creating items (jobs, folders)
*/
static buildCreateItemPath(folderName?: string): string {
return folderName
? `job/${encodeURIComponent(folderName)}/${JenkinsConfig.ENDPOINTS.CREATE_ITEM}`
: JenkinsConfig.ENDPOINTS.CREATE_ITEM;
}

/**
* Build a path for credential operations
*/
static buildCredentialPath(folderName?: string): string {
return folderName
? `job/${encodeURIComponent(folderName)}/${JenkinsConfig.ENDPOINTS.CREDENTIALS_STORE_FOLDER}`
: JenkinsConfig.ENDPOINTS.CREDENTIALS_STORE_SYSTEM;
}

/**
* Build a formatted job path for API calls (handles nested folders)
*/
static buildFormattedJobPath(jobPath: string): string {
return jobPath
.split('/')
.map(segment => `job/${encodeURIComponent(segment)}`)
.join('/');
}

/**
* Build build-specific API path
*/
static buildBuildPath(jobName: string, buildNumber: number, folderName?: string, endpoint: string = ''): string {
const jobPath = this.buildJobPath(jobName, folderName);
return endpoint ? `${jobPath}/${buildNumber}/${endpoint}` : `${jobPath}/${buildNumber}`;
}
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Consider refactoring static utility class to functions.

The JenkinsPathBuilder class contains only static methods. Consider refactoring to standalone functions for better tree-shaking and cleaner code. Also, replace this with the class name in static contexts.

-export class JenkinsPathBuilder {
-  /**
-   * Build a job path for API calls
-   */
-  static buildJobPath(jobName: string, folderName?: string): string {
+/**
+ * Build a job path for API calls
+ */
+export function buildJobPath(jobName: string, folderName?: string): string {
     return folderName 
       ? `job/${encodeURIComponent(folderName)}/job/${encodeURIComponent(jobName)}`
       : `job/${encodeURIComponent(jobName)}`;
-  }
+}

-  static buildBuildPath(jobName: string, buildNumber: number, folderName?: string, endpoint: string = ''): string {
-    const jobPath = this.buildJobPath(jobName, folderName);
+export function buildBuildPath(jobName: string, buildNumber: number, folderName?: string, endpoint: string = ''): string {
+    const jobPath = buildJobPath(jobName, folderName);
     return endpoint ? `${jobPath}/${buildNumber}/${endpoint}` : `${jobPath}/${buildNumber}`;
-  }
-}
+}

Continue this pattern for all methods in the class.

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 Biome (1.9.4)

[error] 7-52: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)


[error] 49-49: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)

🪛 ESLint

[error] 12-12: Delete ·

(prettier/prettier)


[error] 21-21: Delete ·

(prettier/prettier)


[error] 48-48: Replace jobName:·string,·buildNumber:·number,·folderName?:·string,·endpoint:·string·=·'' with ⏎····jobName:·string,⏎····buildNumber:·number,⏎····folderName?:·string,⏎····endpoint:·string·=·''⏎··

(prettier/prettier)

🤖 Prompt for AI Agents
In src/api/ci/jenkins/utils/jenkins.utils.ts between lines 7 and 52, the
JenkinsPathBuilder class only contains static methods and uses 'this' to call
other static methods. Refactor by converting each static method into standalone
exported functions. Replace all 'this' references with direct function calls by
name. Remove the class declaration entirely to improve tree-shaking and simplify
the code structure.

Comment on lines +54 to +131
/**
* Utility class for generating Jenkins XML configurations
*/
export class JenkinsXmlBuilder {
/**
* Build XML configuration for Jenkins folder
*/
static buildFolderXml(description: string = ''): string {
return `<?xml version='1.1' encoding='UTF-8'?>
<com.cloudbees.hudson.plugins.folder.Folder>
<description>${this.escapeXml(description)}</description>
<properties/>
<folderViews/>
<healthMetrics/>
</com.cloudbees.hudson.plugins.folder.Folder>`;
}

/**
* Build XML configuration for Jenkins pipeline job
*/
static buildJobXml(options: CreateJobOptions): string {
const {
repoUrl,
branch = JenkinsConfig.DEFAULT_BRANCH,
jenkinsfilePath = JenkinsConfig.DEFAULT_JENKINSFILE_PATH,
credentialId = JenkinsConfig.DEFAULT_CREDENTIAL_ID
} = options;

return `<flow-definition plugin="${JenkinsConfig.PLUGINS.WORKFLOW_JOB}">
<actions/>
<description></description>
<keepDependencies>false</keepDependencies>
<properties>
<org.jenkinsci.plugins.workflow.job.properties.PipelineTriggersJobProperty>
<triggers>
<com.cloudbees.jenkins.GitHubPushTrigger plugin="${JenkinsConfig.PLUGINS.GITHUB}">
<spec/>
</com.cloudbees.jenkins.GitHubPushTrigger>
</triggers>
</org.jenkinsci.plugins.workflow.job.properties.PipelineTriggersJobProperty>
</properties>
<definition class="org.jenkinsci.plugins.workflow.cps.CpsScmFlowDefinition" plugin="${JenkinsConfig.PLUGINS.WORKFLOW_CPS}">
<scm class="hudson.plugins.git.GitSCM" plugin="${JenkinsConfig.PLUGINS.GIT}">
<configVersion>2</configVersion>
<userRemoteConfigs>
<hudson.plugins.git.UserRemoteConfig>
<url>${this.escapeXml(repoUrl)}</url>
<credentialsId>${this.escapeXml(credentialId)}</credentialsId>
</hudson.plugins.git.UserRemoteConfig>
</userRemoteConfigs>
<branches>
<hudson.plugins.git.BranchSpec>
<name>*/${this.escapeXml(branch)}</name>
</hudson.plugins.git.BranchSpec>
</branches>
<doGenerateSubmoduleConfigurations>false</doGenerateSubmoduleConfigurations>
<submoduleCfg class="list"/>
<extensions/>
</scm>
<scriptPath>${this.escapeXml(jenkinsfilePath)}</scriptPath>
<lightweight>true</lightweight>
</definition>
<disabled>false</disabled>
</flow-definition>`;
}

/**
* Escape XML special characters
*/
private static escapeXml(text: string): string {
return text
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&#39;');
}
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Refactor XML builder to functions and fix static method references.

Like JenkinsPathBuilder, this static-only class should be refactored to functions. The XML escaping implementation is excellent and properly handles all special characters.

-export class JenkinsXmlBuilder {
-  static buildFolderXml(description: string = ''): string {
+export function buildFolderXml(description: string = ''): string {
     return `<?xml version='1.1' encoding='UTF-8'?>
 <com.cloudbees.hudson.plugins.folder.Folder>
-  <description>${this.escapeXml(description)}</description>
+  <description>${escapeXml(description)}</description>
   <properties/>
   <folderViews/>
   <healthMetrics/>
 </com.cloudbees.hudson.plugins.folder.Folder>`;
-  }
+}

-  private static escapeXml(text: string): string {
+function escapeXml(text: string): string {
     return text
       .replace(/&/g, '&amp;')
       .replace(/</g, '&lt;')
       .replace(/>/g, '&gt;')
       .replace(/"/g, '&quot;')
       .replace(/'/g, '&#39;');
-  }
-}
+}

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 Biome (1.9.4)

[error] 57-131: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)


[error] 64-64: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 100-100: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 101-101: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 106-106: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 113-113: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)

🪛 ESLint

[error] 75-75: Delete ·

(prettier/prettier)


[error] 76-76: Delete ·

(prettier/prettier)


[error] 77-77: Delete ·

(prettier/prettier)


[error] 78-78: Delete ·

(prettier/prettier)


[error] 79-79: Replace · with ,

(prettier/prettier)


[error] 81-81: Delete ····

(prettier/prettier)

🤖 Prompt for AI Agents
In src/api/ci/jenkins/utils/jenkins.utils.ts from lines 54 to 131, refactor the
JenkinsXmlBuilder static class into standalone functions to match the style of
JenkinsPathBuilder. Convert each static method (buildFolderXml, buildJobXml,
escapeXml) into separate exported functions. Replace all references to
'this.escapeXml' with direct calls to the escapeXml function. Ensure the
escapeXml function remains private or internal to the module if needed, or
export it if used externally.

Comment on lines +136 to +226
export class JenkinsTriggerAnalyzer {
/**
* Determines the trigger type of a Jenkins build
*/
static determineBuildTrigger(build: any): string {
// Check if build has actions array
if (build.actions && Array.isArray(build.actions)) {
// Look for pull request related information in actions
for (const action of build.actions) {
if (this.isPullRequestTrigger(action)) {
return 'PULL_REQUEST';
}
}
}

// Check causes for trigger information
if (build.causes && Array.isArray(build.causes)) {
for (const cause of build.causes) {
const triggerType = this.analyzeCause(cause);
if (triggerType !== 'UNKNOWN') {
return triggerType;
}
}
}

// Default to PUSH if we have git information but couldn't identify as PR
if (this.hasGitInformation(build)) {
return 'PUSH';
}

return 'UNKNOWN';
}

/**
* Check if action indicates pull request trigger
*/
private static isPullRequestTrigger(action: any): boolean {
return action._class?.includes('pull-request') ||
action._class?.includes('PullRequestAction') ||
action.pullRequest ||
(action.parameters && action.parameters.some((p: any) =>
p.name?.includes('ghpr') || p.name?.includes('pull') || p.name?.includes('PR')));
}

/**
* Analyze build cause to determine trigger type
*/
private static analyzeCause(cause: any): string {
if (!cause.shortDescription) {
return 'UNKNOWN';
}

const description = cause.shortDescription.toLowerCase();

if (description.includes('pull request') || description.includes('pr ') ||
cause._class?.toLowerCase().includes('pullrequest')) {
return 'PULL_REQUEST';
}

if (description.includes('push') ||
cause._class?.includes('GitHubPushCause') ||
cause._class?.includes('GitLabWebHookCause')) {
return 'PUSH';
}

if (description.includes('started by user') ||
cause._class?.includes('UserIdCause')) {
return 'MANUAL';
}

if (description.includes('timer') ||
cause._class?.includes('TimerTrigger')) {
return 'SCHEDULED';
}

if (description.includes('remote') ||
cause._class?.includes('RemoteCause')) {
return 'API';
}

return 'UNKNOWN';
}

/**
* Check if build has git information
*/
private static hasGitInformation(build: any): boolean {
return build.actions && build.actions.some((action: any) =>
action._class?.includes('git') || action.lastBuiltRevision || action.buildsByBranchName);
}
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Improve type safety and code consistency in trigger analyzer.

The JenkinsTriggerAnalyzer has comprehensive logic but uses any types and inconsistent optional chaining. Consider:

  1. Define proper types for build objects instead of using any
  2. Use optional chaining consistently
  3. Consider refactoring to functions
+interface BuildAction {
+  _class?: string;
+  pullRequest?: { source?: { commit?: string } };
+  parameters?: Array<{ name?: string; value?: string }>;
+  lastBuiltRevision?: { SHA1?: string };
+  buildsByBranchName?: Record<string, { revision?: { SHA1?: string } }>;
+}
+
+interface Build {
+  actions?: BuildAction[];
+  causes?: Array<{ shortDescription?: string; _class?: string }>;
+  displayName?: string;
+  description?: string;
+}

-export class JenkinsTriggerAnalyzer {
-  static determineBuildTrigger(build: any): string {
+export function determineBuildTrigger(build: Build): string {
     // Check if build has actions array
-    if (build.actions && Array.isArray(build.actions)) {
+    if (build.actions?.length) {
       // Look for pull request related information in actions
       for (const action of build.actions) {
-        if (this.isPullRequestTrigger(action)) {
+        if (isPullRequestTrigger(action)) {
           return 'PULL_REQUEST';
         }
       }
     }

-    if (action.parameters && action.parameters.some((p: any) =>
-      p.name?.includes('ghpr') || p.name?.includes('pull') || p.name?.includes('PR'))) {
+    if (action.parameters?.some((p) =>
+      p.name?.includes('ghpr') || p.name?.includes('pull') || p.name?.includes('PR'))) {

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 Biome (1.9.4)

[error] 136-226: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)


[error] 145-145: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 154-154: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 162-162: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 176-177: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 223-224: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

🪛 ESLint

[error] 140-140: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 172-172: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 173-173: Insert (⏎······

(prettier/prettier)


[error] 174-174: Delete ·····

(prettier/prettier)


[error] 175-175: Delete ·····

(prettier/prettier)


[error] 176-176: Replace ·····(action.parameters·&&·action.parameters.some((p:·any)·=> with (action.parameters·&&⏎········action.parameters.some(

(prettier/prettier)


[error] 176-176: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 177-177: Replace ···p.name?.includes('ghpr')·||·p.name?.includes('pull')·||·p.name?.includes('PR')) with (p:·any)·=>·p.name?.includes('ghpr')·||·p.name?.includes('pull')·||·p.name?.includes('PR')⏎········))⏎····

(prettier/prettier)


[error] 183-183: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 190-190: Replace description.includes('pull·request')·|| with ⏎······description.includes('pull·request')·||⏎·····

(prettier/prettier)


[error] 191-191: Replace ········cause._class?.toLowerCase().includes('pullrequest') with ······cause._class?.toLowerCase().includes('pullrequest')⏎····

(prettier/prettier)


[error] 195-195: Insert ⏎······

(prettier/prettier)


[error] 196-196: Replace ········ with ······

(prettier/prettier)


[error] 197-197: Replace ··cause._class?.includes('GitLabWebHookCause') with cause._class?.includes('GitLabWebHookCause')⏎····

(prettier/prettier)


[error] 201-202: Delete ⏎·······

(prettier/prettier)


[error] 206-207: Delete ⏎·······

(prettier/prettier)


[error] 211-212: Delete ⏎·······

(prettier/prettier)


[error] 222-222: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 223-223: Replace build.actions·&&·build.actions.some( with (⏎······build.actions·&&⏎······build.actions.some(⏎········

(prettier/prettier)


[error] 223-223: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 224-224: Replace ······action._class?.includes('git')·||·action.lastBuiltRevision·||·action.buildsByBranchName with ··········action._class?.includes('git')·||·action.lastBuiltRevision·||·action.buildsByBranchName⏎······)⏎····

(prettier/prettier)

🤖 Prompt for AI Agents
In src/api/ci/jenkins/utils/jenkins.utils.ts from lines 136 to 226, the
JenkinsTriggerAnalyzer class uses the any type for build and related objects,
which reduces type safety and code clarity. To fix this, define appropriate
TypeScript interfaces or types for the build, action, and cause objects
reflecting their expected structure. Replace all any types with these defined
types. Also, ensure optional chaining is applied consistently throughout the
code to safely access nested properties. Optionally, refactor some static
methods into standalone functions if it improves readability and modularity.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

♻️ Duplicate comments (19)
src/api/ci/jenkins/config/jenkins.config.ts (1)

4-44: The static-only class anti-pattern issue remains unaddressed.

This code segment still has the same structural issue that was previously identified - using a class with only static members.

src/api/ci/jenkins/types/jenkins.types.ts (1)

1-1: Import issue resolved.

The previous review comment about removing unused CredentialType import has been addressed - the import now only includes the actually used enums.

src/api/ci/jenkins/http/jenkins-http.client.ts (2)

58-61: Fix variable scoping in switch statement.

The retryAfter variable declaration can be accessed by other switch cases, which could lead to unexpected behavior.

 case 429:
-  const retryAfter = error.response.headers['retry-after'];
-  throw new JenkinsRateLimitError(retryAfter ? parseInt(retryAfter) : undefined);
+  {
+    const retryAfter = error.response.headers['retry-after'];
+    throw new JenkinsRateLimitError(retryAfter ? parseInt(retryAfter) : undefined);
+  }

112-117: Remove redundant status check.

This status check is unnecessary because the response interceptor already handles non-2xx status codes by throwing appropriate errors.

     const response: AxiosResponse<T> = await this.client.post(path, data, config);
-    
-    if (response.status !== 200 && response.status !== 201) {
-      throw new JenkinsError(
-        `Request failed with status ${response.status}: ${response.statusText}`,
-        response.status
-      );
-    }

     return {
src/api/ci/jenkins/strategies/credential.strategy.ts (6)

29-36: DRY violation: Extract duplicated XML escaping logic to a shared utility.

The XML escaping logic is duplicated across all three credential strategy implementations.

Also applies to: 71-78, 117-124


130-163: Refactor static-only factory class to module-level functions.

The static analysis correctly identifies that this class contains only static members.


15-37: XML escaping duplication needs addressing.

The implementation correctly generates XML for secret text credentials and properly escapes XML characters for security. However, as noted in previous reviews, the XML escaping logic is duplicated across multiple strategy classes.


42-79: Good credential parsing logic with continued duplication issue.

The parseCredentials method intelligently handles passwords containing colons by rejoining all parts after the first colon. The XML template structure is appropriate for Jenkins username/password credentials. However, the XML escaping duplication issue from previous reviews remains unaddressed.


84-125: SSH credential implementation with appropriate parsing strategy.

The use of :: as delimiter for SSH credentials is a good design choice to avoid conflicts with colons in usernames or private keys. The optional passphrase support and XML structure for Jenkins SSH credentials plugin are correctly implemented. The XML escaping duplication issue persists here as well.


130-163: Static-only class structure needs refactoring.

As identified in previous reviews and confirmed by static analysis, this class contains only static members which is not recommended in TypeScript. The functionality is sound, but the structure should be refactored to use module-level functions instead of a static-only class.

src/api/ci/jenkins/services/jenkins-credential.service.ts (1)

62-67: Extract duplicated credential path building logic to utility method.

The path building logic is duplicated across multiple methods.

Also applies to: 85-90, 123-128, 146-151

src/api/ci/jenkins/services/jenkins-job.service.ts (1)

53-56: Use appropriate error type for job creation failure.

Throwing JenkinsJobNotFoundError when job creation fails is semantically incorrect.

src/api/ci/jenkins/utils/jenkins.utils.ts (3)

7-52: Refactor static utility class to standalone functions.

The JenkinsPathBuilder class contains only static methods and should be refactored to functions.


57-131: Refactor XML builder static class to functions and fix static method references.

Like JenkinsPathBuilder, this static-only class should be refactored to functions.


136-226: Improve type safety by defining proper interfaces instead of using 'any'.

The JenkinsTriggerAnalyzer uses any types which reduces type safety. Define proper interfaces for build objects.

src/api/ci/jenkins/services/jenkins-build.service.ts (1)

210-210: Remove debug console.log statements from production code.

Multiple console.log statements appear to be debug code that should not be in production.

Also applies to: 221-221, 224-224, 232-232, 242-244, 251-253, 307-307, 318-318, 331-331, 342-342, 353-353, 361-361, 364-364

src/api/ci/jenkins/jenkins.client.ts (3)

70-85: Add runtime validation for legacy method parameters.

The non-null assertion on line 74 (repoUrl!) could cause runtime errors if the method is called with undefined parameters.


244-265: Validate required parameters in waitForBuildCompletion.

The non-null assertion on line 255 should be replaced with proper validation to prevent runtime errors.


277-296: Validate required parameters in getBuildByCommitSha.

The non-null assertion on line 287 should be replaced with validation to prevent runtime errors.

🧹 Nitpick comments (12)
src/api/ci/jenkins/enums/jenkins.enums.ts (1)

30-30: Address the TODO and fix formatting.

The TODO comment indicates uncertainty about the SSH credential type. Please verify this is correct for Jenkins credential management.

Also fix the formatting issue:

- SSH_USERNAME_PRIVATE_KEY = 'SSH Username with private key',//TODO: need to confirm if this is correct
+ SSH_USERNAME_PRIVATE_KEY = 'SSH Username with private key', // TODO: need to confirm if this is correct

Would you like me to help verify the correct Jenkins credential types?

src/api/ci/jenkins/index.ts (1)

28-28: Fix trailing whitespace.

Remove the trailing whitespace at the end of the line.

-export { JenkinsClient } from './jenkins.client'; 
+export { JenkinsClient } from './jenkins.client';
src/api/ci/jenkins/types/jenkins.types.ts (2)

6-6: Consider more specific types for Jenkins API responses.

While any types are sometimes necessary for dynamic API responses, consider creating more specific interfaces for well-known Jenkins API structures to improve type safety.

For example, you could define specific interfaces for:

// For actions array
export interface JenkinsAction {
  _class: string;
  [key: string]: any;
}

// For health reports
export interface JenkinsHealthReport {
  description: string;
  iconClassName?: string;
  iconUrl?: string;
  score: number;
}

// For parameter definitions
export interface JenkinsParameterDefinition {
  name: string;
  type: string;
  description?: string;
  defaultParameterValue?: {
    name: string;
    value: string | number | boolean;
  };
}

Also applies to: 91-91, 95-95, 140-142, 150-150, 155-157


158-158: Fix trailing whitespace.

Remove the trailing whitespace at the end of the file.

-} 
+}
src/api/ci/jenkins/README.md (1)

20-43: Specify language for fenced code block.

Add a language specification to improve syntax highlighting and markdown compliance.

-```
+```text
 jenkins/
 ├── enums/                    # Enums for Jenkins constants
src/api/ci/jenkins/errors/jenkins.errors.ts (1)

12-12: Fix formatting issues.

Remove extra whitespace and add proper line ending.

     this.name = 'JenkinsError';
-    
+
     // Capture stack trace if available
-    const message = retryAfter 
+    const message = retryAfter
       ? `Rate limit exceeded. Retry after ${retryAfter} seconds.`
       : 'Rate limit exceeded.';
-} 
+}

Also applies to: 87-87, 93-93

src/api/ci/jenkins/http/jenkins-http.client.ts (1)

1-7: Address formatting and import organization issues.

The static analysis tools have identified several formatting inconsistencies that should be addressed for code consistency.

Key formatting issues to fix:

  • Import statement ordering and spacing
  • Extra spaces and indentation
  • Missing newline at end of file

Run your formatter (Prettier) to automatically fix these issues:

npx prettier --write src/api/ci/jenkins/http/jenkins-http.client.ts

Also applies to: 83-85, 99-103, 111-111, 130-132, 136-136, 148-148, 153-153, 184-184

src/api/ci/jenkins/utils/jenkins.utils.ts (1)

231-264: Consider refactoring polling utility to functions for consistency.

For consistency with other utilities, consider refactoring this static-only class to module-level functions.

-export class JenkinsPollingUtils {
-  static async pollUntil<T>(
+export async function pollUntil<T>(
     pollFn: () => Promise<T>,
     conditionFn: (result: T) => boolean,
     timeoutMs: number = JenkinsConfig.DEFAULT_TIMEOUT_MS,
     intervalMs: number = JenkinsConfig.DEFAULT_POLL_INTERVAL_MS
   ): Promise<T> {
     // ... implementation ...
-    await this.sleep(intervalMs);
+    await sleep(intervalMs);
   }
-}

-  static sleep(ms: number): Promise<void> {
+export function sleep(ms: number): Promise<void> {
     return new Promise(resolve => setTimeout(resolve, ms));
-  }
+}
src/api/ci/jenkins/services/jenkins-build.service.ts (1)

352-352: Use optional chaining for cleaner null checks.

These conditions can be simplified using optional chaining.

-    if (cause.shortDescription && cause.shortDescription.includes(normalizedCommitSha)) {
+    if (cause.shortDescription?.includes(normalizedCommitSha)) {

-    if (build.displayName && build.displayName.includes(normalizedCommitSha)) {
+    if (build.displayName?.includes(normalizedCommitSha)) {

-    } else if (build.description && build.description.includes(normalizedCommitSha)) {
+    } else if (build.description?.includes(normalizedCommitSha)) {

Also applies to: 360-360, 363-363

src/api/ci/jenkins/jenkins.client.ts (3)

1-16: Fix import formatting and organization.

The ESLint prettier errors indicate formatting inconsistencies in the import statements. These should be resolved to maintain code consistency.

Apply this diff to fix the import formatting:

-import { JenkinsHttpClient } from './http/jenkins-http.client';
-import { JenkinsJobService } from './services/jenkins-job.service';
-import { JenkinsBuildService } from './services/jenkins-build.service';
-import { JenkinsCredentialService } from './services/jenkins-credential.service';
-import { 
-  JenkinsClientConfig,
-  JenkinsApiResponse,
-  FolderConfig,
-  CreateJobOptions,
-  BuildOptions,
-  BuildSearchOptions,
-  WaitForBuildOptions,
-  JenkinsBuild,
-  JenkinsJob
-} from './types/jenkins.types';
-import { CredentialType, JenkinsBuildTrigger } from './enums/jenkins.enums';
+import { CredentialType, JenkinsBuildTrigger } from './enums/jenkins.enums';
+import { JenkinsHttpClient } from './http/jenkins-http.client';
+import { JenkinsJobService } from './services/jenkins-job.service';
+import { JenkinsBuildService } from './services/jenkins-build.service';
+import { JenkinsCredentialService } from './services/jenkins-credential.service';
+import {
+  BuildOptions,
+  BuildSearchOptions,
+  CreateJobOptions,
+  FolderConfig,
+  JenkinsApiResponse,
+  JenkinsBuild,
+  JenkinsClientConfig,
+  JenkinsJob,
+  WaitForBuildOptions,
+} from './types/jenkins.types';

18-380: Excellent architectural design with proper separation of concerns.

The implementation follows a well-structured facade pattern that:

  • Provides a unified interface over multiple specialized services
  • Maintains backward compatibility through method overloading
  • Enables advanced usage through direct service access
  • Organizes operations logically (folder, job, credential, build, utility)
  • Demonstrates clear separation of concerns and modularity

The service delegation pattern ensures each service handles its specific domain while the client provides a convenient unified interface.


380-380: Fix trailing whitespace.

Remove the trailing space at the end of the file as indicated by ESLint.

-} 
+}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 93132aa and 139b04a.

📒 Files selected for processing (19)
  • src/api/ci/gitlabciClient.ts (1 hunks)
  • src/api/ci/jenkins/README.md (1 hunks)
  • src/api/ci/jenkins/config/jenkins.config.ts (1 hunks)
  • src/api/ci/jenkins/enums/jenkins.enums.ts (1 hunks)
  • src/api/ci/jenkins/errors/jenkins.errors.ts (1 hunks)
  • src/api/ci/jenkins/http/jenkins-http.client.ts (1 hunks)
  • src/api/ci/jenkins/index.ts (1 hunks)
  • src/api/ci/jenkins/jenkins.client.ts (1 hunks)
  • src/api/ci/jenkins/services/jenkins-build.service.ts (1 hunks)
  • src/api/ci/jenkins/services/jenkins-credential.service.ts (1 hunks)
  • src/api/ci/jenkins/services/jenkins-job.service.ts (1 hunks)
  • src/api/ci/jenkins/strategies/credential.strategy.ts (1 hunks)
  • src/api/ci/jenkins/types/jenkins.types.ts (1 hunks)
  • src/api/ci/jenkins/utils/jenkins.utils.ts (1 hunks)
  • src/rhtap/core/integration/ci/providers/gitlabCI.ts (1 hunks)
  • src/rhtap/core/integration/ci/providers/jenkinsCI.ts (2 hunks)
  • src/rhtap/postcreation/strategies/commands/addJenkinsSecretsCommand.ts (1 hunks)
  • tests/api/ci/jenkinsClient.test.ts (1 hunks)
  • tsconfig.json (1 hunks)
🧬 Code Graph Analysis (3)
src/api/ci/jenkins/strategies/credential.strategy.ts (1)
src/api/ci/jenkins/config/jenkins.config.ts (1)
  • JenkinsConfig (4-44)
src/api/ci/jenkins/http/jenkins-http.client.ts (3)
src/api/ci/jenkins/index.ts (1)
  • JenkinsHttpClient (20-20)
src/api/ci/jenkins/types/jenkins.types.ts (2)
  • JenkinsClientConfig (16-20)
  • JenkinsApiResponse (6-11)
src/api/ci/jenkins/errors/jenkins.errors.ts (3)
  • JenkinsError (4-18)
  • JenkinsAuthenticationError (75-80)
  • JenkinsRateLimitError (85-93)
src/api/ci/jenkins/utils/jenkins.utils.ts (3)
src/api/ci/jenkins/config/jenkins.config.ts (1)
  • JenkinsConfig (4-44)
src/api/ci/jenkins/index.ts (1)
  • JenkinsConfig (8-8)
src/api/ci/jenkins/types/jenkins.types.ts (1)
  • CreateJobOptions (33-40)
🪛 ESLint
src/rhtap/core/integration/ci/providers/gitlabCI.ts

[error] 281-281: 'pipeline' is defined but never used. Allowed unused args must match /^_/u.

(@typescript-eslint/no-unused-vars)

src/api/ci/jenkins/services/jenkins-credential.service.ts

[error] 1-2: Replace HttpClient·}·from·'../http/jenkins-http.client';⏎import·{·JenkinsApiResponse·}·from·'../types/jenkins.types with Config·}·from·'../config/jenkins.config

(prettier/prettier)


[error] 4-4: Replace onfig·}·from·'../config/jenkins.config with redentialError·}·from·'../errors/jenkins.errors

(prettier/prettier)


[error] 5-5: Replace PathBuilder·}·from·'../utils/jenkins.utils with HttpClient·}·from·'../http/jenkins-http.client

(prettier/prettier)


[error] 7-7: Replace CredentialError·}·from·'../errors/jenkins.error with ApiResponse·}·from·'../types/jenkins.types';⏎import·{·JenkinsPathBuilder·}·from·'../utils/jenkins.util

(prettier/prettier)


[error] 27-27: Delete ······

(prettier/prettier)


[error] 30-30: Delete ······

(prettier/prettier)


[error] 33-33: Delete ······

(prettier/prettier)


[error] 35-35: Delete ······

(prettier/prettier)


[error] 57-57: Delete ······

(prettier/prettier)


[error] 60-60: Delete ······

(prettier/prettier)


[error] 65-65: Delete ······

(prettier/prettier)


[error] 67-67: Delete ······

(prettier/prettier)


[error] 69-69: Delete ······

(prettier/prettier)


[error] 88-88: Delete ······

(prettier/prettier)


[error] 90-90: Delete ······

(prettier/prettier)


[error] 92-92: Delete ······

(prettier/prettier)


[error] 120-120: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 126-126: Delete ······

(prettier/prettier)


[error] 128-128: Delete ······

(prettier/prettier)


[error] 130-130: Delete ······

(prettier/prettier)


[error] 133-136: Replace ⏎········credentialId,⏎········'Credential·not·found·or·not·accessible'⏎······ with credentialId,·'Credential·not·found·or·not·accessible'

(prettier/prettier)


[error] 143-143: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 149-149: Delete ······

(prettier/prettier)


[error] 151-151: Delete ······

(prettier/prettier)


[error] 152-152: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 157-157: Delete ······

(prettier/prettier)


[error] 188-188: Replace folderName,·credentialId,·secretValue,·CredentialType.USERNAME_PASSWORD with ⏎······folderName,⏎······credentialId,⏎······secretValue,⏎······CredentialType.USERNAME_PASSWORD⏎····

(prettier/prettier)


[error] 201-201: Delete ·

(prettier/prettier)


[error] 204-204: Replace folderName,·credentialId,·secretValue,·CredentialType.SSH_USERNAME_PRIVATE_KEY with ⏎······folderName,⏎······credentialId,⏎······secretValue,⏎······CredentialType.SSH_USERNAME_PRIVATE_KEY⏎····

(prettier/prettier)


[error] 220-220: Replace · with

(prettier/prettier)

src/api/ci/jenkins/services/jenkins-job.service.ts

[error] 1-1: Replace HttpClient·}·from·'../http/jenkins-http.client with Config·}·from·'../config/jenkins.config

(prettier/prettier)


[error] 2-7: Replace ·⏎··JenkinsApiResponse,·⏎··FolderConfig,·⏎··CreateJobOptions,⏎··JenkinsJob⏎}·from·'../types/jenkins.type with ·JenkinsFolderError,·JenkinsJobNotFoundError·}·from·'../errors/jenkins.error

(prettier/prettier)


[error] 8-8: Replace Config·}·from·'../config/jenkins.config with HttpClient·}·from·'../http/jenkins-http.client

(prettier/prettier)


[error] 9-9: Replace ·JenkinsPathBuilder,·JenkinsXmlBuilder·}·from·'../utils/jenkins.util with ⏎··CreateJobOptions,⏎··FolderConfig,⏎··JenkinsApiResponse,⏎··JenkinsJob,⏎}·from·'../types/jenkins.type

(prettier/prettier)


[error] 10-10: Replace FolderError,·JenkinsJobNotFoundError·}·from·'../errors/jenkins.error with PathBuilder,·JenkinsXmlBuilder·}·from·'../utils/jenkins.util

(prettier/prettier)


[error] 25-25: Delete ······

(prettier/prettier)


[error] 27-27: Delete ······

(prettier/prettier)


[error] 45-45: Delete ······

(prettier/prettier)


[error] 51-51: Delete ······

(prettier/prettier)


[error] 54-54: Replace ·?·${options.folderName}/${options.jobName}`` with ⏎········?·${options.folderName}/${options.jobName}`⏎·······`

(prettier/prettier)


[error] 90-90: Replace ``${path}/doDelete,·'',·JenkinsConfig.HEADERS.JSON); with `⏎········`${path}/doDelete`,⏎········'',⏎········JenkinsConfig.HEADERS.JSON`

(prettier/prettier)


[error] 91-91: Insert );⏎

(prettier/prettier)


[error] 119-119: Delete ·

(prettier/prettier)


[error] 122-122: Delete ······

(prettier/prettier)


[error] 144-144: Replace ``${path}/disable,·'',·JenkinsConfig.HEADERS.JSON); with `⏎········`${path}/disable`,⏎········'',⏎········JenkinsConfig.HEADERS.JSON`

(prettier/prettier)


[error] 145-145: Insert );⏎

(prettier/prettier)


[error] 160-160: Delete ······

(prettier/prettier)


[error] 171-171: Replace jobName:·string,·configXml:·string,·folderName?:·string with ⏎····jobName:·string,⏎····configXml:·string,⏎····folderName?:·string⏎··

(prettier/prettier)


[error] 174-174: Replace ``${path}/config.xml,·configXml,·JenkinsConfig.HEADERS.XML); with `⏎········`${path}/config.xml`,⏎········configXml,⏎········JenkinsConfig.HEADERS.XML`

(prettier/prettier)


[error] 175-175: Insert );⏎

(prettier/prettier)


[error] 189-189: Replace ``${path}/config.xml,·JenkinsConfig.HEADERS.XML); with `⏎········`${path}/config.xml`,⏎········JenkinsConfig.HEADERS.XML`

(prettier/prettier)


[error] 190-190: Insert );⏎

(prettier/prettier)


[error] 197-197: Replace · with

(prettier/prettier)

src/api/ci/jenkins/strategies/credential.strategy.ts

[error] 1-1: Replace CredentialType·}·from·'../enums/jenkins.enums with JenkinsConfig·}·from·'../config/jenkins.config

(prettier/prettier)


[error] 2-2: Replace JenkinsConfig·}·from·'../config/jenkins.config with CredentialType·}·from·'../enums/jenkins.enums

(prettier/prettier)


[error] 45-45: Delete ····

(prettier/prettier)


[error] 64-64: Delete ····

(prettier/prettier)


[error] 67-67: Delete ····

(prettier/prettier)


[error] 87-87: Delete ····

(prettier/prettier)


[error] 107-107: Replace 'SSH·credentials·must·be·in·format·"username::privateKey"·or·"username::privateKey::passphrase"'); with ⏎········'SSH·credentials·must·be·in·format·"username::privateKey"·or·"username::privateKey::passphrase"'

(prettier/prettier)


[error] 108-108: Replace ····} with ······);

(prettier/prettier)


[error] 109-109: Insert }⏎

(prettier/prettier)


[error] 113-113: Delete ····

(prettier/prettier)


[error] 142-142: Delete ····

(prettier/prettier)


[error] 146-146: Delete ····

(prettier/prettier)


[error] 163-163: Replace · with

(prettier/prettier)

src/api/ci/jenkins/services/jenkins-build.service.ts

[error] 1-1: Replace HttpClient·}·from·'../http/jenkins-http.client with Config·}·from·'../config/jenkins.config

(prettier/prettier)


[error] 2-5: Replace ⏎··JenkinsApiResponse,·⏎··BuildOptions,·⏎··BuildSearchOptions, with JenkinsBuildTrigger·}·from·'../enums/jenkins.enums';⏎import·{

(prettier/prettier)


[error] 6-6: Replace WaitForBuildOptions with JenkinsBuildNotFoundError

(prettier/prettier)


[error] 7-7: Insert TimeoutError

(prettier/prettier)


[error] 8-8: Insert NotFoundError,

(prettier/prettier)


[error] 9-9: Replace types/jenkins.type with errors/jenkins.error

(prettier/prettier)


[error] 10-10: Replace BuildTrigger·}·from·'../enums/jenkins.enums with HttpClient·}·from·'../http/jenkins-http.client

(prettier/prettier)


[error] 11-12: Replace ·JenkinsConfig·}·from·'../config/jenkins.config';⏎import·{· with ⏎··BuildOptions,⏎··BuildSearchOptions,⏎··JenkinsApiResponse,

(prettier/prettier)


[error] 13-13: Replace PathBuilder,· with Build,

(prettier/prettier)


[error] 14-14: Replace TriggerAnalyzer,· with Job,

(prettier/prettier)


[error] 15-15: Replace JenkinsPollingUtils· with WaitForBuildOptions,

(prettier/prettier)


[error] 16-16: Replace utils/jenkins.util with types/jenkins.type

(prettier/prettier)


[error] 17-17: Delete ·

(prettier/prettier)


[error] 18-18: Replace BuildNotFoundError,· with PathBuilder,

(prettier/prettier)


[error] 19-19: Replace BuildTimeoutError with PollingUtils

(prettier/prettier)


[error] 20-20: Replace JobNotFoundError· with TriggerAnalyzer,

(prettier/prettier)


[error] 21-21: Replace errors/jenkins.error with utils/jenkins.util

(prettier/prettier)


[error] 35-35: Delete ·

(prettier/prettier)


[error] 36-36: Delete ·

(prettier/prettier)


[error] 38-38: Delete ······

(prettier/prettier)


[error] 40-40: Delete ·

(prettier/prettier)


[error] 41-41: Delete ·

(prettier/prettier)


[error] 42-42: Delete ·

(prettier/prettier)


[error] 45-45: Delete ······

(prettier/prettier)


[error] 48-48: Replace ·?·${options.folderName}/${options.jobName}`` with ⏎········?·${options.folderName}/${options.jobName}`⏎·······`

(prettier/prettier)


[error] 57-57: Delete ·

(prettier/prettier)


[error] 58-58: Delete ·

(prettier/prettier)


[error] 64-64: Delete ·

(prettier/prettier)


[error] 65-65: Delete ·

(prettier/prettier)


[error] 66-66: Delete ·

(prettier/prettier)


[error] 69-69: Delete ······

(prettier/prettier)


[error] 70-73: Replace ⏎········path,⏎········JenkinsConfig.HEADERS.JSON⏎······ with path,·JenkinsConfig.HEADERS.JSON

(prettier/prettier)


[error] 77-77: Replace buildInfo with ⏎··········buildInfo⏎········

(prettier/prettier)


[error] 92-92: Delete ······

(prettier/prettier)


[error] 151-151: Delete ·

(prettier/prettier)


[error] 152-152: Delete ·

(prettier/prettier)


[error] 153-153: Delete ·

(prettier/prettier)


[error] 157-159: Replace ⏎········path,⏎········JenkinsConfig.HEADERS.PLAIN, with path,·JenkinsConfig.HEADERS.PLAIN,·{

(prettier/prettier)


[error] 160-160: Replace {·start:·0·} with start:·0,

(prettier/prettier)


[error] 161-161: Insert }

(prettier/prettier)


[error] 178-178: Insert ,

(prettier/prettier)


[error] 204-204: Insert ,

(prettier/prettier)


[error] 234-234: Delete ········

(prettier/prettier)


[error] 264-264: Delete ·

(prettier/prettier)


[error] 265-265: Delete ·

(prettier/prettier)


[error] 276-276: Delete ·

(prettier/prettier)


[error] 277-277: Delete ·

(prettier/prettier)


[error] 288-288: Delete ·

(prettier/prettier)


[error] 289-289: Delete ·

(prettier/prettier)


[error] 318-318: Replace Found·matching·commit·in·buildsByBranchName·for·branch·${branch}:·${branchSha} with ⏎··················Found·matching·commit·in·buildsByBranchName·for·branch·${branch}:·${branchSha}⏎················

(prettier/prettier)


[error] 328-328: Replace (param.name·===·'GIT_COMMIT'·||·param.name·===·'ghprbActualCommit')·&&·param.value with ⏎··············(param.name·===·'GIT_COMMIT'·||·param.name·===·'ghprbActualCommit')·&&⏎··············param.value⏎············

(prettier/prettier)


[error] 377-377: Replace · with

(prettier/prettier)

src/api/ci/jenkins/config/jenkins.config.ts

[error] 11-11: Delete ··

(prettier/prettier)


[error] 17-17: Replace 'Accept' with Accept

(prettier/prettier)


[error] 18-18: Replace 'Accept' with Accept

(prettier/prettier)


[error] 44-44: Replace · with

(prettier/prettier)

src/api/ci/jenkins/enums/jenkins.enums.ts

[error] 30-30: Insert ·

(prettier/prettier)


[error] 31-31: Replace · with

(prettier/prettier)

src/api/ci/jenkins/errors/jenkins.errors.ts

[error] 12-12: Delete ····

(prettier/prettier)


[error] 87-87: Delete ·

(prettier/prettier)


[error] 93-93: Replace · with

(prettier/prettier)

src/api/ci/jenkins/http/jenkins-http.client.ts

[error] 1-1: Replace axios,·{·AxiosInstance,·AxiosRequestConfig,·AxiosResponse·}·from·'axio with {⏎··JenkinsAuthenticationError,⏎··JenkinsError,⏎··JenkinsRateLimitError,⏎}·from·'../errors/jenkins.error

(prettier/prettier)


[error] 2-2: Replace ClientConfig,·JenkinsApiResponse with ApiResponse,·JenkinsClientConfig

(prettier/prettier)


[error] 3-7: Replace {·⏎··JenkinsError,·⏎··JenkinsAuthenticationError,·⏎··JenkinsRateLimitError·⏎}·from·'../errors/jenkins.error with axios,·{·AxiosInstance,·AxiosRequestConfig,·AxiosResponse·}·from·'axio

(prettier/prettier)


[error] 64-68: Replace ⏎················Jenkins·API·request·failed:·${message},⏎················status,⏎················error⏎·············· with ``Jenkins·API·request·failed:·${message},·status,·error

(prettier/prettier)


[error] 82-82: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 83-83: Delete ·

(prettier/prettier)


[error] 85-85: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 99-99: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 101-101: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 103-103: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 111-111: Delete ····

(prettier/prettier)


[error] 130-130: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 132-132: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 136-136: Delete ····

(prettier/prettier)


[error] 148-148: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 153-153: Delete ····

(prettier/prettier)


[error] 184-184: Replace · with

(prettier/prettier)

src/api/ci/jenkins/index.ts

[error] 28-28: Replace · with

(prettier/prettier)

src/api/ci/jenkins/jenkins.client.ts

[error] 1-1: Replace JenkinsHttpClient·}·from·'./http/jenkins-http.client with CredentialType,·JenkinsBuildTrigger·}·from·'./enums/jenkins.enums

(prettier/prettier)


[error] 2-2: Replace JobService·}·from·'./services/jenkins-job.service with HttpClient·}·from·'./http/jenkins-http.client

(prettier/prettier)


[error] 5-9: Replace ⏎··JenkinsClientConfig,⏎··JenkinsApiResponse,⏎··FolderConfig,⏎··CreateJobOptions, with JenkinsJobService·}·from·'./services/jenkins-job.service';⏎import·{

(prettier/prettier)


[error] 12-12: Replace WaitForBuild with CreateJob

(prettier/prettier)


[error] 13-13: Replace JenkinsBuild with FolderConfig,⏎··JenkinsApiResponse

(prettier/prettier)


[error] 14-14: Replace Job with Build,

(prettier/prettier)


[error] 15-16: Replace }·from·'./types/jenkins.types';⏎import·{·CredentialType,·JenkinsBuildTrigger·}·from·'./enums/jenkins.enum with ··JenkinsClientConfig,⏎··JenkinsJob,⏎··WaitForBuildOptions,⏎}·from·'./types/jenkins.type

(prettier/prettier)


[error] 142-142: Replace folderName,·credentialId,·secretValue,·credentialType with ⏎······folderName,⏎······credentialId,⏎······secretValue,⏎······credentialType⏎····

(prettier/prettier)


[error] 165-165: Replace folderName,·credentialId,·username,·password with ⏎······folderName,⏎······credentialId,⏎······username,⏎······password⏎····

(prettier/prettier)


[error] 380-380: Replace · with

(prettier/prettier)

src/api/ci/jenkins/types/jenkins.types.ts

[error] 6-6: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 91-91: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 95-95: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 140-140: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 141-141: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 142-142: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 150-150: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 155-155: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 156-156: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 157-157: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 158-158: Replace · with

(prettier/prettier)

src/api/ci/jenkins/utils/jenkins.utils.ts

[error] 1-1: Replace CreateJobOptions·}·from·'../types/jenkins.types with JenkinsConfig·}·from·'../config/jenkins.config

(prettier/prettier)


[error] 2-2: Replace JenkinsConfig·}·from·'../config/jenkins.config with CreateJobOptions·}·from·'../types/jenkins.types

(prettier/prettier)


[error] 12-12: Delete ·

(prettier/prettier)


[error] 21-21: Delete ·

(prettier/prettier)


[error] 48-48: Replace jobName:·string,·buildNumber:·number,·folderName?:·string,·endpoint:·string·=·'' with ⏎····jobName:·string,⏎····buildNumber:·number,⏎····folderName?:·string,⏎····endpoint:·string·=·''⏎··

(prettier/prettier)


[error] 75-75: Delete ·

(prettier/prettier)


[error] 76-76: Delete ·

(prettier/prettier)


[error] 77-77: Delete ·

(prettier/prettier)


[error] 78-78: Delete ·

(prettier/prettier)


[error] 79-79: Replace · with ,

(prettier/prettier)


[error] 81-81: Delete ····

(prettier/prettier)


[error] 140-140: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 172-172: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 173-173: Insert (⏎······

(prettier/prettier)


[error] 174-174: Delete ·····

(prettier/prettier)


[error] 175-175: Delete ·····

(prettier/prettier)


[error] 176-176: Replace ·····(action.parameters·&&·action.parameters.some((p:·any)·=> with (action.parameters·&&⏎········action.parameters.some(

(prettier/prettier)


[error] 176-176: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 177-177: Replace ···p.name?.includes('ghpr')·||·p.name?.includes('pull')·||·p.name?.includes('PR')) with (p:·any)·=>·p.name?.includes('ghpr')·||·p.name?.includes('pull')·||·p.name?.includes('PR')⏎········))⏎····

(prettier/prettier)


[error] 183-183: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 190-190: Replace description.includes('pull·request')·|| with ⏎······description.includes('pull·request')·||⏎·····

(prettier/prettier)


[error] 191-191: Replace ········cause._class?.toLowerCase().includes('pullrequest') with ······cause._class?.toLowerCase().includes('pullrequest')⏎····

(prettier/prettier)


[error] 195-195: Insert ⏎······

(prettier/prettier)


[error] 196-196: Replace ········ with ······

(prettier/prettier)


[error] 197-197: Replace ··cause._class?.includes('GitLabWebHookCause') with cause._class?.includes('GitLabWebHookCause')⏎····

(prettier/prettier)


[error] 201-202: Delete ⏎·······

(prettier/prettier)


[error] 206-207: Delete ⏎·······

(prettier/prettier)


[error] 211-212: Delete ⏎·······

(prettier/prettier)


[error] 222-222: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 223-223: Replace build.actions·&&·build.actions.some( with (⏎······build.actions·&&⏎······build.actions.some(⏎········

(prettier/prettier)


[error] 223-223: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 224-224: Replace ······action._class?.includes('git')·||·action.lastBuiltRevision·||·action.buildsByBranchName with ··········action._class?.includes('git')·||·action.lastBuiltRevision·||·action.buildsByBranchName⏎······)⏎····

(prettier/prettier)


[error] 242-242: Delete ····

(prettier/prettier)


[error] 245-245: Delete ······

(prettier/prettier)


[error] 249-249: Delete ······

(prettier/prettier)


[error] 253-253: Delete ······

(prettier/prettier)


[error] 264-264: Replace · with

(prettier/prettier)

🪛 Biome (1.9.4)
src/api/ci/jenkins/strategies/credential.strategy.ts

[error] 130-163: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)


[error] 141-141: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 154-154: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 161-161: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)

src/api/ci/jenkins/services/jenkins-build.service.ts

[error] 352-352: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 360-360: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 363-363: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

src/api/ci/jenkins/config/jenkins.config.ts

[error] 4-44: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)

src/api/ci/jenkins/http/jenkins-http.client.ts

[error] 59-59: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)

src/api/ci/jenkins/utils/jenkins.utils.ts

[error] 7-52: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)


[error] 49-49: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 57-131: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)


[error] 64-64: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 100-100: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 101-101: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 106-106: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 113-113: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 136-226: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)


[error] 145-145: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 154-154: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 162-162: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 176-177: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 223-224: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 231-264: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)


[error] 254-254: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)

🪛 markdownlint-cli2 (0.17.2)
src/api/ci/jenkins/README.md

20-20: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

✅ Files skipped from review due to trivial changes (2)
  • tests/api/ci/jenkinsClient.test.ts
  • src/rhtap/core/integration/ci/providers/jenkinsCI.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/rhtap/postcreation/strategies/commands/addJenkinsSecretsCommand.ts
🧰 Additional context used
🧬 Code Graph Analysis (3)
src/api/ci/jenkins/strategies/credential.strategy.ts (1)
src/api/ci/jenkins/config/jenkins.config.ts (1)
  • JenkinsConfig (4-44)
src/api/ci/jenkins/http/jenkins-http.client.ts (3)
src/api/ci/jenkins/index.ts (1)
  • JenkinsHttpClient (20-20)
src/api/ci/jenkins/types/jenkins.types.ts (2)
  • JenkinsClientConfig (16-20)
  • JenkinsApiResponse (6-11)
src/api/ci/jenkins/errors/jenkins.errors.ts (3)
  • JenkinsError (4-18)
  • JenkinsAuthenticationError (75-80)
  • JenkinsRateLimitError (85-93)
src/api/ci/jenkins/utils/jenkins.utils.ts (3)
src/api/ci/jenkins/config/jenkins.config.ts (1)
  • JenkinsConfig (4-44)
src/api/ci/jenkins/index.ts (1)
  • JenkinsConfig (8-8)
src/api/ci/jenkins/types/jenkins.types.ts (1)
  • CreateJobOptions (33-40)
🪛 ESLint
src/rhtap/core/integration/ci/providers/gitlabCI.ts

[error] 281-281: 'pipeline' is defined but never used. Allowed unused args must match /^_/u.

(@typescript-eslint/no-unused-vars)

src/api/ci/jenkins/services/jenkins-credential.service.ts

[error] 1-2: Replace HttpClient·}·from·'../http/jenkins-http.client';⏎import·{·JenkinsApiResponse·}·from·'../types/jenkins.types with Config·}·from·'../config/jenkins.config

(prettier/prettier)


[error] 4-4: Replace onfig·}·from·'../config/jenkins.config with redentialError·}·from·'../errors/jenkins.errors

(prettier/prettier)


[error] 5-5: Replace PathBuilder·}·from·'../utils/jenkins.utils with HttpClient·}·from·'../http/jenkins-http.client

(prettier/prettier)


[error] 7-7: Replace CredentialError·}·from·'../errors/jenkins.error with ApiResponse·}·from·'../types/jenkins.types';⏎import·{·JenkinsPathBuilder·}·from·'../utils/jenkins.util

(prettier/prettier)


[error] 27-27: Delete ······

(prettier/prettier)


[error] 30-30: Delete ······

(prettier/prettier)


[error] 33-33: Delete ······

(prettier/prettier)


[error] 35-35: Delete ······

(prettier/prettier)


[error] 57-57: Delete ······

(prettier/prettier)


[error] 60-60: Delete ······

(prettier/prettier)


[error] 65-65: Delete ······

(prettier/prettier)


[error] 67-67: Delete ······

(prettier/prettier)


[error] 69-69: Delete ······

(prettier/prettier)


[error] 88-88: Delete ······

(prettier/prettier)


[error] 90-90: Delete ······

(prettier/prettier)


[error] 92-92: Delete ······

(prettier/prettier)


[error] 120-120: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 126-126: Delete ······

(prettier/prettier)


[error] 128-128: Delete ······

(prettier/prettier)


[error] 130-130: Delete ······

(prettier/prettier)


[error] 133-136: Replace ⏎········credentialId,⏎········'Credential·not·found·or·not·accessible'⏎······ with credentialId,·'Credential·not·found·or·not·accessible'

(prettier/prettier)


[error] 143-143: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 149-149: Delete ······

(prettier/prettier)


[error] 151-151: Delete ······

(prettier/prettier)


[error] 152-152: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 157-157: Delete ······

(prettier/prettier)


[error] 188-188: Replace folderName,·credentialId,·secretValue,·CredentialType.USERNAME_PASSWORD with ⏎······folderName,⏎······credentialId,⏎······secretValue,⏎······CredentialType.USERNAME_PASSWORD⏎····

(prettier/prettier)


[error] 201-201: Delete ·

(prettier/prettier)


[error] 204-204: Replace folderName,·credentialId,·secretValue,·CredentialType.SSH_USERNAME_PRIVATE_KEY with ⏎······folderName,⏎······credentialId,⏎······secretValue,⏎······CredentialType.SSH_USERNAME_PRIVATE_KEY⏎····

(prettier/prettier)


[error] 220-220: Replace · with

(prettier/prettier)

src/api/ci/jenkins/services/jenkins-job.service.ts

[error] 1-1: Replace HttpClient·}·from·'../http/jenkins-http.client with Config·}·from·'../config/jenkins.config

(prettier/prettier)


[error] 2-7: Replace ·⏎··JenkinsApiResponse,·⏎··FolderConfig,·⏎··CreateJobOptions,⏎··JenkinsJob⏎}·from·'../types/jenkins.type with ·JenkinsFolderError,·JenkinsJobNotFoundError·}·from·'../errors/jenkins.error

(prettier/prettier)


[error] 8-8: Replace Config·}·from·'../config/jenkins.config with HttpClient·}·from·'../http/jenkins-http.client

(prettier/prettier)


[error] 9-9: Replace ·JenkinsPathBuilder,·JenkinsXmlBuilder·}·from·'../utils/jenkins.util with ⏎··CreateJobOptions,⏎··FolderConfig,⏎··JenkinsApiResponse,⏎··JenkinsJob,⏎}·from·'../types/jenkins.type

(prettier/prettier)


[error] 10-10: Replace FolderError,·JenkinsJobNotFoundError·}·from·'../errors/jenkins.error with PathBuilder,·JenkinsXmlBuilder·}·from·'../utils/jenkins.util

(prettier/prettier)


[error] 25-25: Delete ······

(prettier/prettier)


[error] 27-27: Delete ······

(prettier/prettier)


[error] 45-45: Delete ······

(prettier/prettier)


[error] 51-51: Delete ······

(prettier/prettier)


[error] 54-54: Replace ·?·${options.folderName}/${options.jobName}`` with ⏎········?·${options.folderName}/${options.jobName}`⏎·······`

(prettier/prettier)


[error] 90-90: Replace ``${path}/doDelete,·'',·JenkinsConfig.HEADERS.JSON); with `⏎········`${path}/doDelete`,⏎········'',⏎········JenkinsConfig.HEADERS.JSON`

(prettier/prettier)


[error] 91-91: Insert );⏎

(prettier/prettier)


[error] 119-119: Delete ·

(prettier/prettier)


[error] 122-122: Delete ······

(prettier/prettier)


[error] 144-144: Replace ``${path}/disable,·'',·JenkinsConfig.HEADERS.JSON); with `⏎········`${path}/disable`,⏎········'',⏎········JenkinsConfig.HEADERS.JSON`

(prettier/prettier)


[error] 145-145: Insert );⏎

(prettier/prettier)


[error] 160-160: Delete ······

(prettier/prettier)


[error] 171-171: Replace jobName:·string,·configXml:·string,·folderName?:·string with ⏎····jobName:·string,⏎····configXml:·string,⏎····folderName?:·string⏎··

(prettier/prettier)


[error] 174-174: Replace ``${path}/config.xml,·configXml,·JenkinsConfig.HEADERS.XML); with `⏎········`${path}/config.xml`,⏎········configXml,⏎········JenkinsConfig.HEADERS.XML`

(prettier/prettier)


[error] 175-175: Insert );⏎

(prettier/prettier)


[error] 189-189: Replace ``${path}/config.xml,·JenkinsConfig.HEADERS.XML); with `⏎········`${path}/config.xml`,⏎········JenkinsConfig.HEADERS.XML`

(prettier/prettier)


[error] 190-190: Insert );⏎

(prettier/prettier)


[error] 197-197: Replace · with

(prettier/prettier)

src/api/ci/jenkins/strategies/credential.strategy.ts

[error] 1-1: Replace CredentialType·}·from·'../enums/jenkins.enums with JenkinsConfig·}·from·'../config/jenkins.config

(prettier/prettier)


[error] 2-2: Replace JenkinsConfig·}·from·'../config/jenkins.config with CredentialType·}·from·'../enums/jenkins.enums

(prettier/prettier)


[error] 45-45: Delete ····

(prettier/prettier)


[error] 64-64: Delete ····

(prettier/prettier)


[error] 67-67: Delete ····

(prettier/prettier)


[error] 87-87: Delete ····

(prettier/prettier)


[error] 107-107: Replace 'SSH·credentials·must·be·in·format·"username::privateKey"·or·"username::privateKey::passphrase"'); with ⏎········'SSH·credentials·must·be·in·format·"username::privateKey"·or·"username::privateKey::passphrase"'

(prettier/prettier)


[error] 108-108: Replace ····} with ······);

(prettier/prettier)


[error] 109-109: Insert }⏎

(prettier/prettier)


[error] 113-113: Delete ····

(prettier/prettier)


[error] 142-142: Delete ····

(prettier/prettier)


[error] 146-146: Delete ····

(prettier/prettier)


[error] 163-163: Replace · with

(prettier/prettier)

src/api/ci/jenkins/services/jenkins-build.service.ts

[error] 1-1: Replace HttpClient·}·from·'../http/jenkins-http.client with Config·}·from·'../config/jenkins.config

(prettier/prettier)


[error] 2-5: Replace ⏎··JenkinsApiResponse,·⏎··BuildOptions,·⏎··BuildSearchOptions, with JenkinsBuildTrigger·}·from·'../enums/jenkins.enums';⏎import·{

(prettier/prettier)


[error] 6-6: Replace WaitForBuildOptions with JenkinsBuildNotFoundError

(prettier/prettier)


[error] 7-7: Insert TimeoutError

(prettier/prettier)


[error] 8-8: Insert NotFoundError,

(prettier/prettier)


[error] 9-9: Replace types/jenkins.type with errors/jenkins.error

(prettier/prettier)


[error] 10-10: Replace BuildTrigger·}·from·'../enums/jenkins.enums with HttpClient·}·from·'../http/jenkins-http.client

(prettier/prettier)


[error] 11-12: Replace ·JenkinsConfig·}·from·'../config/jenkins.config';⏎import·{· with ⏎··BuildOptions,⏎··BuildSearchOptions,⏎··JenkinsApiResponse,

(prettier/prettier)


[error] 13-13: Replace PathBuilder,· with Build,

(prettier/prettier)


[error] 14-14: Replace TriggerAnalyzer,· with Job,

(prettier/prettier)


[error] 15-15: Replace JenkinsPollingUtils· with WaitForBuildOptions,

(prettier/prettier)


[error] 16-16: Replace utils/jenkins.util with types/jenkins.type

(prettier/prettier)


[error] 17-17: Delete ·

(prettier/prettier)


[error] 18-18: Replace BuildNotFoundError,· with PathBuilder,

(prettier/prettier)


[error] 19-19: Replace BuildTimeoutError with PollingUtils

(prettier/prettier)


[error] 20-20: Replace JobNotFoundError· with TriggerAnalyzer,

(prettier/prettier)


[error] 21-21: Replace errors/jenkins.error with utils/jenkins.util

(prettier/prettier)


[error] 35-35: Delete ·

(prettier/prettier)


[error] 36-36: Delete ·

(prettier/prettier)


[error] 38-38: Delete ······

(prettier/prettier)


[error] 40-40: Delete ·

(prettier/prettier)


[error] 41-41: Delete ·

(prettier/prettier)


[error] 42-42: Delete ·

(prettier/prettier)


[error] 45-45: Delete ······

(prettier/prettier)


[error] 48-48: Replace ·?·${options.folderName}/${options.jobName}`` with ⏎········?·${options.folderName}/${options.jobName}`⏎·······`

(prettier/prettier)


[error] 57-57: Delete ·

(prettier/prettier)


[error] 58-58: Delete ·

(prettier/prettier)


[error] 64-64: Delete ·

(prettier/prettier)


[error] 65-65: Delete ·

(prettier/prettier)


[error] 66-66: Delete ·

(prettier/prettier)


[error] 69-69: Delete ······

(prettier/prettier)


[error] 70-73: Replace ⏎········path,⏎········JenkinsConfig.HEADERS.JSON⏎······ with path,·JenkinsConfig.HEADERS.JSON

(prettier/prettier)


[error] 77-77: Replace buildInfo with ⏎··········buildInfo⏎········

(prettier/prettier)


[error] 92-92: Delete ······

(prettier/prettier)


[error] 151-151: Delete ·

(prettier/prettier)


[error] 152-152: Delete ·

(prettier/prettier)


[error] 153-153: Delete ·

(prettier/prettier)


[error] 157-159: Replace ⏎········path,⏎········JenkinsConfig.HEADERS.PLAIN, with path,·JenkinsConfig.HEADERS.PLAIN,·{

(prettier/prettier)


[error] 160-160: Replace {·start:·0·} with start:·0,

(prettier/prettier)


[error] 161-161: Insert }

(prettier/prettier)


[error] 178-178: Insert ,

(prettier/prettier)


[error] 204-204: Insert ,

(prettier/prettier)


[error] 234-234: Delete ········

(prettier/prettier)


[error] 264-264: Delete ·

(prettier/prettier)


[error] 265-265: Delete ·

(prettier/prettier)


[error] 276-276: Delete ·

(prettier/prettier)


[error] 277-277: Delete ·

(prettier/prettier)


[error] 288-288: Delete ·

(prettier/prettier)


[error] 289-289: Delete ·

(prettier/prettier)


[error] 318-318: Replace Found·matching·commit·in·buildsByBranchName·for·branch·${branch}:·${branchSha} with ⏎··················Found·matching·commit·in·buildsByBranchName·for·branch·${branch}:·${branchSha}⏎················

(prettier/prettier)


[error] 328-328: Replace (param.name·===·'GIT_COMMIT'·||·param.name·===·'ghprbActualCommit')·&&·param.value with ⏎··············(param.name·===·'GIT_COMMIT'·||·param.name·===·'ghprbActualCommit')·&&⏎··············param.value⏎············

(prettier/prettier)


[error] 377-377: Replace · with

(prettier/prettier)

src/api/ci/jenkins/config/jenkins.config.ts

[error] 11-11: Delete ··

(prettier/prettier)


[error] 17-17: Replace 'Accept' with Accept

(prettier/prettier)


[error] 18-18: Replace 'Accept' with Accept

(prettier/prettier)


[error] 44-44: Replace · with

(prettier/prettier)

src/api/ci/jenkins/enums/jenkins.enums.ts

[error] 30-30: Insert ·

(prettier/prettier)


[error] 31-31: Replace · with

(prettier/prettier)

src/api/ci/jenkins/errors/jenkins.errors.ts

[error] 12-12: Delete ····

(prettier/prettier)


[error] 87-87: Delete ·

(prettier/prettier)


[error] 93-93: Replace · with

(prettier/prettier)

src/api/ci/jenkins/http/jenkins-http.client.ts

[error] 1-1: Replace axios,·{·AxiosInstance,·AxiosRequestConfig,·AxiosResponse·}·from·'axio with {⏎··JenkinsAuthenticationError,⏎··JenkinsError,⏎··JenkinsRateLimitError,⏎}·from·'../errors/jenkins.error

(prettier/prettier)


[error] 2-2: Replace ClientConfig,·JenkinsApiResponse with ApiResponse,·JenkinsClientConfig

(prettier/prettier)


[error] 3-7: Replace {·⏎··JenkinsError,·⏎··JenkinsAuthenticationError,·⏎··JenkinsRateLimitError·⏎}·from·'../errors/jenkins.error with axios,·{·AxiosInstance,·AxiosRequestConfig,·AxiosResponse·}·from·'axio

(prettier/prettier)


[error] 64-68: Replace ⏎················Jenkins·API·request·failed:·${message},⏎················status,⏎················error⏎·············· with ``Jenkins·API·request·failed:·${message},·status,·error

(prettier/prettier)


[error] 82-82: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 83-83: Delete ·

(prettier/prettier)


[error] 85-85: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 99-99: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 101-101: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 103-103: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 111-111: Delete ····

(prettier/prettier)


[error] 130-130: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 132-132: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 136-136: Delete ····

(prettier/prettier)


[error] 148-148: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 153-153: Delete ····

(prettier/prettier)


[error] 184-184: Replace · with

(prettier/prettier)

src/api/ci/jenkins/index.ts

[error] 28-28: Replace · with

(prettier/prettier)

src/api/ci/jenkins/jenkins.client.ts

[error] 1-1: Replace JenkinsHttpClient·}·from·'./http/jenkins-http.client with CredentialType,·JenkinsBuildTrigger·}·from·'./enums/jenkins.enums

(prettier/prettier)


[error] 2-2: Replace JobService·}·from·'./services/jenkins-job.service with HttpClient·}·from·'./http/jenkins-http.client

(prettier/prettier)


[error] 5-9: Replace ⏎··JenkinsClientConfig,⏎··JenkinsApiResponse,⏎··FolderConfig,⏎··CreateJobOptions, with JenkinsJobService·}·from·'./services/jenkins-job.service';⏎import·{

(prettier/prettier)


[error] 12-12: Replace WaitForBuild with CreateJob

(prettier/prettier)


[error] 13-13: Replace JenkinsBuild with FolderConfig,⏎··JenkinsApiResponse

(prettier/prettier)


[error] 14-14: Replace Job with Build,

(prettier/prettier)


[error] 15-16: Replace }·from·'./types/jenkins.types';⏎import·{·CredentialType,·JenkinsBuildTrigger·}·from·'./enums/jenkins.enum with ··JenkinsClientConfig,⏎··JenkinsJob,⏎··WaitForBuildOptions,⏎}·from·'./types/jenkins.type

(prettier/prettier)


[error] 142-142: Replace folderName,·credentialId,·secretValue,·credentialType with ⏎······folderName,⏎······credentialId,⏎······secretValue,⏎······credentialType⏎····

(prettier/prettier)


[error] 165-165: Replace folderName,·credentialId,·username,·password with ⏎······folderName,⏎······credentialId,⏎······username,⏎······password⏎····

(prettier/prettier)


[error] 380-380: Replace · with

(prettier/prettier)

src/api/ci/jenkins/types/jenkins.types.ts

[error] 6-6: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 91-91: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 95-95: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 140-140: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 141-141: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 142-142: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 150-150: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 155-155: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 156-156: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 157-157: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 158-158: Replace · with

(prettier/prettier)

src/api/ci/jenkins/utils/jenkins.utils.ts

[error] 1-1: Replace CreateJobOptions·}·from·'../types/jenkins.types with JenkinsConfig·}·from·'../config/jenkins.config

(prettier/prettier)


[error] 2-2: Replace JenkinsConfig·}·from·'../config/jenkins.config with CreateJobOptions·}·from·'../types/jenkins.types

(prettier/prettier)


[error] 12-12: Delete ·

(prettier/prettier)


[error] 21-21: Delete ·

(prettier/prettier)


[error] 48-48: Replace jobName:·string,·buildNumber:·number,·folderName?:·string,·endpoint:·string·=·'' with ⏎····jobName:·string,⏎····buildNumber:·number,⏎····folderName?:·string,⏎····endpoint:·string·=·''⏎··

(prettier/prettier)


[error] 75-75: Delete ·

(prettier/prettier)


[error] 76-76: Delete ·

(prettier/prettier)


[error] 77-77: Delete ·

(prettier/prettier)


[error] 78-78: Delete ·

(prettier/prettier)


[error] 79-79: Replace · with ,

(prettier/prettier)


[error] 81-81: Delete ····

(prettier/prettier)


[error] 140-140: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 172-172: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 173-173: Insert (⏎······

(prettier/prettier)


[error] 174-174: Delete ·····

(prettier/prettier)


[error] 175-175: Delete ·····

(prettier/prettier)


[error] 176-176: Replace ·····(action.parameters·&&·action.parameters.some((p:·any)·=> with (action.parameters·&&⏎········action.parameters.some(

(prettier/prettier)


[error] 176-176: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 177-177: Replace ···p.name?.includes('ghpr')·||·p.name?.includes('pull')·||·p.name?.includes('PR')) with (p:·any)·=>·p.name?.includes('ghpr')·||·p.name?.includes('pull')·||·p.name?.includes('PR')⏎········))⏎····

(prettier/prettier)


[error] 183-183: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 190-190: Replace description.includes('pull·request')·|| with ⏎······description.includes('pull·request')·||⏎·····

(prettier/prettier)


[error] 191-191: Replace ········cause._class?.toLowerCase().includes('pullrequest') with ······cause._class?.toLowerCase().includes('pullrequest')⏎····

(prettier/prettier)


[error] 195-195: Insert ⏎······

(prettier/prettier)


[error] 196-196: Replace ········ with ······

(prettier/prettier)


[error] 197-197: Replace ··cause._class?.includes('GitLabWebHookCause') with cause._class?.includes('GitLabWebHookCause')⏎····

(prettier/prettier)


[error] 201-202: Delete ⏎·······

(prettier/prettier)


[error] 206-207: Delete ⏎·······

(prettier/prettier)


[error] 211-212: Delete ⏎·······

(prettier/prettier)


[error] 222-222: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 223-223: Replace build.actions·&&·build.actions.some( with (⏎······build.actions·&&⏎······build.actions.some(⏎········

(prettier/prettier)


[error] 223-223: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 224-224: Replace ······action._class?.includes('git')·||·action.lastBuiltRevision·||·action.buildsByBranchName with ··········action._class?.includes('git')·||·action.lastBuiltRevision·||·action.buildsByBranchName⏎······)⏎····

(prettier/prettier)


[error] 242-242: Delete ····

(prettier/prettier)


[error] 245-245: Delete ······

(prettier/prettier)


[error] 249-249: Delete ······

(prettier/prettier)


[error] 253-253: Delete ······

(prettier/prettier)


[error] 264-264: Replace · with

(prettier/prettier)

🪛 Biome (1.9.4)
src/api/ci/jenkins/strategies/credential.strategy.ts

[error] 130-163: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)


[error] 141-141: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 154-154: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 161-161: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)

src/api/ci/jenkins/services/jenkins-build.service.ts

[error] 352-352: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 360-360: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 363-363: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

src/api/ci/jenkins/config/jenkins.config.ts

[error] 4-44: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)

src/api/ci/jenkins/http/jenkins-http.client.ts

[error] 59-59: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)

src/api/ci/jenkins/utils/jenkins.utils.ts

[error] 7-52: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)


[error] 49-49: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 57-131: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)


[error] 64-64: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 100-100: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 101-101: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 106-106: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 113-113: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 136-226: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)


[error] 145-145: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 154-154: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 162-162: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 176-177: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 223-224: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 231-264: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)


[error] 254-254: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)

🪛 markdownlint-cli2 (0.17.2)
src/api/ci/jenkins/README.md

20-20: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Red Hat Konflux / tssc-test-on-pull-request
🔇 Additional comments (10)
tsconfig.json (1)

7-7: Confirm TypeScript compilation scope and adjust output paths

The expanded rootDir ("./") does not pull in any extra .ts/.tsx files because your include/exclude settings restrict compilation to:

  • include: src/**/*, tests/**/*
  • exclude: node_modules, **/*.test.ts

All discovered root‐level .ts files (global-setup.ts, playwright.config.ts) remain outside the compile set.

However, changing rootDir from "./src" to "./" will alter your output tree under dist/ (e.g. src/foo.tsdist/src/foo.js instead of dist/foo.js). Please verify that any build, packaging, or deployment scripts (and import paths, if used) are updated to reference the new dist/src/… layout.

src/rhtap/core/integration/ci/providers/gitlabCI.ts (1)

278-278: Good consistency improvement.

Wrapping the return value in Promise.resolve() ensures consistent Promise-based behavior across the interface.

src/api/ci/jenkins/enums/jenkins.enums.ts (1)

4-31: Well-structured enum definitions.

The Jenkins enums provide good type safety and cover the essential build results, triggers, and credential types needed for Jenkins integration.

src/api/ci/jenkins/index.ts (1)

1-28: Excellent module organization!

This barrel export file provides a clean, well-organized entry point for the Jenkins client with logical grouping by functionality. The structure follows TypeScript best practices and makes the API easy to consume.

src/api/ci/jenkins/types/jenkins.types.ts (1)

3-158: Comprehensive and well-structured type definitions.

The interfaces provide excellent type safety for Jenkins API interactions with thorough documentation and logical organization. The types cover all major Jenkins concepts including builds, jobs, configuration options, and API responses.

src/api/ci/jenkins/README.md (1)

1-231: Outstanding documentation!

This README provides comprehensive documentation of the refactored Jenkins client architecture. It covers all essential aspects including usage examples, design patterns, configuration, extensibility, and best practices. This will greatly help developers understand and use the new client effectively.

src/api/ci/jenkins/errors/jenkins.errors.ts (1)

1-93: Excellent error hierarchy design!

The error classes provide a well-structured hierarchy for Jenkins-specific errors with appropriate status codes, contextual information, and clear error messages. This will greatly improve error handling and debugging throughout the Jenkins client.

src/api/ci/jenkins/http/jenkins-http.client.ts (1)

12-184: Well-designed HTTP client with comprehensive error handling.

The JenkinsHttpClient provides a solid foundation for Jenkins API interactions with proper authentication, timeout configuration, request/response interceptors, and specific error handling. The utility methods (ping, getVersion) are valuable additions for server connectivity checks.

src/api/ci/jenkins/jenkins.client.ts (1)

22-33: Well-designed constructor with proper dependency injection.

The constructor correctly implements dependency injection by initializing the HTTP client first and then passing it to all services, ensuring they share the same connection configuration.

src/api/ci/jenkins/strategies/credential.strategy.ts (1)

4-10: Clean interface design for the strategy pattern.

The interface appropriately defines the contract for credential strategies with clear method signatures for XML generation and type identification.

Comment on lines +149 to +166
//TODO: need to confirm if this is correct
public async getPipelineLogs(projectPath: string, jobId: number): Promise<string> {
try {
// Access the raw REST API client to make a direct request for job logs
const gitlab = this.gitlabClient.getClient();

// // GitLab API endpoint for job traces is GET /projects/:id/jobs/:job_id/trace
// const encodedProjectPath = encodeURIComponent(projectPath);
// const url = `projects/${encodedProjectPath}/jobs/${jobId}/trace`;
// GitLab API endpoint for job traces is GET /projects/:id/jobs/:job_id/trace
const encodedProjectPath = encodeURIComponent(projectPath);
const url = `projects/${encodedProjectPath}/jobs/${jobId}/trace`;

// // Make the request using the underlying requester
// const jobTrace = await gitlab.request.get(url);
// return jobTrace as string;
// } catch (error) {
// console.error(`Failed to get logs for job ${jobId} in project ${projectPath}:`, error);
// return 'Failed to retrieve job logs';
// }
// }
// Make the request using the underlying requester
const jobTrace = await gitlab.requester.get(url);
return jobTrace as unknown as string;
} catch (error) {
console.error(`Failed to get logs for job ${jobId} in project ${projectPath}:`, error);
return 'Failed to retrieve job logs';
}
}
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Address the TODO and improve error handling.

The method implementation needs verification and better error handling:

  1. The TODO comment indicates uncertainty about the implementation
  2. Returning a generic failure message instead of proper error propagation may hide important debugging information

Consider this refactor for better error handling:

  public async getPipelineLogs(projectPath: string, jobId: number): Promise<string> {
    try {
      const gitlab = this.gitlabClient.getClient();
      const encodedProjectPath = encodeURIComponent(projectPath);
      const url = `projects/${encodedProjectPath}/jobs/${jobId}/trace`;
      
      const jobTrace = await gitlab.requester.get(url);
      return jobTrace as unknown as string;
    } catch (error) {
      console.error(`Failed to get logs for job ${jobId} in project ${projectPath}:`, error);
-     return 'Failed to retrieve job logs';
+     throw new Error(`Failed to retrieve job logs for job ${jobId}: ${error instanceof Error ? error.message : String(error)}`);
    }
  }

🏁 Script executed:

#!/bin/bash
# Description: Verify GitLab API endpoint for job traces
# Expected: Confirm the correct API path and method

echo "=== Checking GitLab API documentation reference ==="
echo "Searching for GitLab API trace endpoint usage in codebase..."
rg -A 3 -B 3 "jobs.*trace|trace.*jobs" --type ts

Length of output: 1022


Refine getPipelineLogs implementation and error handling

Verified that GitLab’s API for raw job logs is indeed
GET /projects/:id/jobs/:job_id/trace
and returns the full log as text. Please remove the lingering TODO and improve error propagation so consumers can handle failures more granularly.

• File: src/api/ci/gitlabciClient.ts (lines 149–166)

  1. Remove the //TODO comment now that the endpoint has been confirmed.
  2. Replace the generic failure return with a thrown Error, preserving the original message.
  3. (Optional) Explicitly set Accept: text/plain in the request if your client doesn’t default to it.

Suggested diff:

   public async getPipelineLogs(projectPath: string, jobId: number): Promise<string> {
     try {
       const gitlab = this.gitlabClient.getClient();
       const encodedProjectPath = encodeURIComponent(projectPath);
       const url = `projects/${encodedProjectPath}/jobs/${jobId}/trace`;
-      // Make the request using the underlying requester
+      // Fetch raw job logs as plain text
       const jobTrace = await gitlab.requester.get(url);
       return jobTrace as unknown as string;
     } catch (error) {
-      console.error(`Failed to get logs for job ${jobId} in project ${projectPath}:`, error);
-      return 'Failed to retrieve job logs';
+      console.error(`Failed to retrieve logs for job ${jobId} in project ${projectPath}:`, error);
+      throw new Error(
+        `getPipelineLogs error for project "${projectPath}", job ${jobId}: ` +
+        (error instanceof Error ? error.message : String(error))
+      );
     }
   }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
//TODO: need to confirm if this is correct
public async getPipelineLogs(projectPath: string, jobId: number): Promise<string> {
try {
// Access the raw REST API client to make a direct request for job logs
const gitlab = this.gitlabClient.getClient();
// // GitLab API endpoint for job traces is GET /projects/:id/jobs/:job_id/trace
// const encodedProjectPath = encodeURIComponent(projectPath);
// const url = `projects/${encodedProjectPath}/jobs/${jobId}/trace`;
// GitLab API endpoint for job traces is GET /projects/:id/jobs/:job_id/trace
const encodedProjectPath = encodeURIComponent(projectPath);
const url = `projects/${encodedProjectPath}/jobs/${jobId}/trace`;
// // Make the request using the underlying requester
// const jobTrace = await gitlab.request.get(url);
// return jobTrace as string;
// } catch (error) {
// console.error(`Failed to get logs for job ${jobId} in project ${projectPath}:`, error);
// return 'Failed to retrieve job logs';
// }
// }
// Make the request using the underlying requester
const jobTrace = await gitlab.requester.get(url);
return jobTrace as unknown as string;
} catch (error) {
console.error(`Failed to get logs for job ${jobId} in project ${projectPath}:`, error);
return 'Failed to retrieve job logs';
}
}
//TODO: need to confirm if this is correct
public async getPipelineLogs(projectPath: string, jobId: number): Promise<string> {
try {
const gitlab = this.gitlabClient.getClient();
const encodedProjectPath = encodeURIComponent(projectPath);
const url = `projects/${encodedProjectPath}/jobs/${jobId}/trace`;
// Fetch raw job logs as plain text
const jobTrace = await gitlab.requester.get(url);
return jobTrace as unknown as string;
} catch (error) {
console.error(`Failed to retrieve logs for job ${jobId} in project ${projectPath}:`, error);
throw new Error(
`getPipelineLogs error for project "${projectPath}", job ${jobId}: ` +
(error instanceof Error ? error.message : String(error))
);
}
}
🤖 Prompt for AI Agents
In src/api/ci/gitlabciClient.ts lines 149 to 166, remove the TODO comment since
the endpoint is confirmed correct. Modify the error handling by throwing a new
Error with the failure message instead of returning a generic string, so callers
can handle errors properly. Optionally, add an 'Accept: text/plain' header to
the request to explicitly request plain text logs if not already set by the
client.

/**
* Get credential information (without sensitive data)
*/
async getCredential(folderName: string, credentialId: string): Promise<any> {
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Define proper types instead of using 'any'.

Using any type reduces type safety and makes the API contract unclear. Consider defining interfaces for credential responses.

Define proper interfaces:

+interface CredentialInfo {
+  id: string;
+  description?: string;
+  typeName: string;
+  // Add other relevant fields
+}

-  async getCredential(folderName: string, credentialId: string): Promise<any> {
+  async getCredential(folderName: string, credentialId: string): Promise<CredentialInfo> {

-  async listCredentials(folderName?: string): Promise<any[]> {
+  async listCredentials(folderName?: string): Promise<CredentialInfo[]> {

-      const response = await this.httpClient.get<{ credentials: any[] }>(
+      const response = await this.httpClient.get<{ credentials: CredentialInfo[] }>(

Also applies to: 143-143, 152-152

🧰 Tools
🪛 ESLint

[error] 120-120: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)

🤖 Prompt for AI Agents
In src/api/ci/jenkins/services/jenkins-credential.service.ts at lines 120, 143,
and 152, the methods currently return Promise<any>, which reduces type safety
and clarity. Define appropriate TypeScript interfaces representing the structure
of the credential responses and update the method return types to Promise of
those interfaces instead of any. This will improve type safety and make the API
contract explicit.

Comment on lines +281 to 283
public override async getPipelineLogs(pipeline: Pipeline): Promise<string> {
throw new Error('GitLab does not support getting pipeline logs.');
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Fix unused parameter and clarify the contradiction.

  1. The unused pipeline parameter should be prefixed with underscore to satisfy the linter
  2. This method throws an error indicating GitLab doesn't support pipeline logs, but gitlabciClient.ts was just enhanced to support job log retrieval. Consider clarifying this discrepancy.
- public override async getPipelineLogs(pipeline: Pipeline): Promise<string> {
+ public override async getPipelineLogs(_pipeline: Pipeline): Promise<string> {
    throw new Error('GitLab does not support getting pipeline logs.');
  }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public override async getPipelineLogs(pipeline: Pipeline): Promise<string> {
throw new Error('GitLab does not support getting pipeline logs.');
}
public override async getPipelineLogs(_pipeline: Pipeline): Promise<string> {
throw new Error('GitLab does not support getting pipeline logs.');
}
🧰 Tools
🪛 ESLint

[error] 281-281: 'pipeline' is defined but never used. Allowed unused args must match /^_/u.

(@typescript-eslint/no-unused-vars)

🤖 Prompt for AI Agents
In src/rhtap/core/integration/ci/providers/gitlabCI.ts around lines 281 to 283,
rename the unused parameter 'pipeline' to '_pipeline' to satisfy the linter.
Update the error message to clarify that while GitLab does not support
retrieving full pipeline logs, job log retrieval is supported, reflecting the
recent enhancement in gitlabciClient.ts.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

♻️ Duplicate comments (15)
src/api/ci/jenkins/config/jenkins.config.ts (1)

4-44: Address the static-only class anti-pattern identified in previous reviews.

The static analysis and previous reviews correctly identified that using a class with only static members is an anti-pattern in TypeScript. This should be refactored to use a const object or namespace instead.

src/api/ci/jenkins/http/jenkins-http.client.ts (2)

58-60: Fix variable scoping in switch statement.

The retryAfter variable can be accessed by other switch cases due to lack of block scoping.


112-117: Remove redundant status check.

This status check is unnecessary since the response interceptor already handles non-2xx status codes.

src/api/ci/jenkins/strategies/credential.strategy.ts (2)

29-36: Extract duplicated XML escaping logic to shared utility.

The XML escaping method is duplicated across all credential strategy classes, violating DRY principles.


130-163: Refactor static-only factory class.

The factory class contains only static members, which is an anti-pattern in TypeScript and should be refactored to use functions or namespace.

src/api/ci/jenkins/services/jenkins-credential.service.ts (4)

62-67: Extract duplicated credential path building logic.

The path building logic is duplicated across multiple methods and should be extracted to a utility method.


120-120: Define proper types instead of using 'any'.

Using any types reduces type safety and should be replaced with proper interfaces for credential responses.


143-143: Define proper types instead of using 'any'.

Using any types reduces type safety and should be replaced with proper interfaces for credential responses.


152-152: Define proper types instead of using 'any'.

Using any types reduces type safety and should be replaced with proper interfaces for credential responses.

src/api/ci/jenkins/services/jenkins-job.service.ts (1)

53-56: Use appropriate error type for job creation failure

Throwing JenkinsJobNotFoundError when job creation fails is semantically incorrect. Consider creating a JenkinsJobCreationError or using a more generic JenkinsError with appropriate context.

} catch (error) {
  const jobPath = options.folderName ? `${options.folderName}/${options.jobName}` : options.jobName;
-  throw new JenkinsJobNotFoundError(jobPath);
+  throw new JenkinsError(
+    `Failed to create job: ${jobPath}`,
+    undefined,
+    error instanceof Error ? error : undefined
+  );
}
src/api/ci/jenkins/utils/jenkins.utils.ts (3)

7-52: Consider refactoring static utility class to functions.

The JenkinsPathBuilder class contains only static methods. Consider refactoring to standalone functions for better tree-shaking and cleaner code. Also, replace this with the class name in static contexts.

-export class JenkinsPathBuilder {
-  /**
-   * Build a job path for API calls
-   */
-  static buildJobPath(jobName: string, folderName?: string): string {
+/**
+ * Build a job path for API calls
+ */
+export function buildJobPath(jobName: string, folderName?: string): string {
     return folderName 
       ? `job/${encodeURIComponent(folderName)}/job/${encodeURIComponent(jobName)}`
       : `job/${encodeURIComponent(jobName)}`;
-  }
+}

-  static buildBuildPath(jobName: string, buildNumber: number, folderName?: string, endpoint: string = ''): string {
-    const jobPath = this.buildJobPath(jobName, folderName);
+export function buildBuildPath(jobName: string, buildNumber: number, folderName?: string, endpoint: string = ''): string {
+    const jobPath = buildJobPath(jobName, folderName);
     return endpoint ? `${jobPath}/${buildNumber}/${endpoint}` : `${jobPath}/${buildNumber}`;
-  }
-}
+}

Continue this pattern for all methods in the class.


57-131: Refactor XML builder to functions and fix static method references.

Like JenkinsPathBuilder, this static-only class should be refactored to functions. The XML escaping implementation is excellent and properly handles all special characters.

-export class JenkinsXmlBuilder {
-  static buildFolderXml(description: string = ''): string {
+export function buildFolderXml(description: string = ''): string {
     return `<?xml version='1.1' encoding='UTF-8'?>
 <com.cloudbees.hudson.plugins.folder.Folder>
-  <description>${this.escapeXml(description)}</description>
+  <description>${escapeXml(description)}</description>
   <properties/>
   <folderViews/>
   <healthMetrics/>
 </com.cloudbees.hudson.plugins.folder.Folder>`;
-  }
+}

-  private static escapeXml(text: string): string {
+function escapeXml(text: string): string {
     return text
       .replace(/&/g, '&amp;')
       .replace(/</g, '&lt;')
       .replace(/>/g, '&gt;')
       .replace(/"/g, '&quot;')
       .replace(/'/g, '&#39;');
-  }
-}
+}

136-226: Improve type safety and code consistency in trigger analyzer.

The JenkinsTriggerAnalyzer has comprehensive logic but uses any types and inconsistent optional chaining. Consider:

  1. Define proper types for build objects instead of using any
  2. Use optional chaining consistently
  3. Consider refactoring to functions
+interface BuildAction {
+  _class?: string;
+  pullRequest?: { source?: { commit?: string } };
+  parameters?: Array<{ name?: string; value?: string }>;
+  lastBuiltRevision?: { SHA1?: string };
+  buildsByBranchName?: Record<string, { revision?: { SHA1?: string } }>;
+}
+
+interface Build {
+  actions?: BuildAction[];
+  causes?: Array<{ shortDescription?: string; _class?: string }>;
+  displayName?: string;
+  description?: string;
+}

-export class JenkinsTriggerAnalyzer {
-  static determineBuildTrigger(build: any): string {
+export function determineBuildTrigger(build: Build): string {
     // Check if build has actions array
-    if (build.actions && Array.isArray(build.actions)) {
+    if (build.actions?.length) {
       // Look for pull request related information in actions
       for (const action of build.actions) {
-        if (this.isPullRequestTrigger(action)) {
+        if (isPullRequestTrigger(action)) {
           return 'PULL_REQUEST';
         }
       }
     }

-    if (action.parameters && action.parameters.some((p: any) =>
-      p.name?.includes('ghpr') || p.name?.includes('pull') || p.name?.includes('PR'))) {
+    if (action.parameters?.some((p) =>
+      p.name?.includes('ghpr') || p.name?.includes('pull') || p.name?.includes('PR'))) {
src/api/ci/jenkins/services/jenkins-build.service.ts (2)

210-253: Remove debug console.log statements

Multiple console.log statements appear to be debug code that should not be in production. Consider using a proper logging framework with configurable log levels or removing these statements entirely.

Remove all console.log statements in this method:

  • Line 210
  • Line 221
  • Line 224
  • Line 232
  • Lines 242-244
  • Lines 251-253

307-365: Remove additional debug console.log statements

This method also contains multiple console.log statements that should be removed or replaced with proper logging.

Remove console.log statements at:

  • Line 307
  • Line 318
  • Line 331
  • Line 342
  • Line 353
  • Line 361
  • Line 364

Additionally, consider using optional chaining for cleaner code:

-if (cause.shortDescription && cause.shortDescription.includes(normalizedCommitSha)) {
+if (cause.shortDescription?.includes(normalizedCommitSha)) {
-if (build.displayName && build.displayName.includes(normalizedCommitSha)) {
+if (build.displayName?.includes(normalizedCommitSha)) {
-} else if (build.description && build.description.includes(normalizedCommitSha)) {
+} else if (build.description?.includes(normalizedCommitSha)) {
🧹 Nitpick comments (2)
src/api/ci/jenkins/README.md (1)

20-43: Add language specification to fenced code block.

The directory structure code block should specify a language for better rendering and accessibility.

-```
+```text
 jenkins/
 ├── enums/                    # Enums for Jenkins constants
 │   └── jenkins.enums.ts
 ├── types/                    # TypeScript type definitions
 │   └── jenkins.types.ts
 ├── config/                   # Configuration constants
 │   └── jenkins.config.ts
 ├── errors/                   # Custom error classes
 │   └── jenkins.errors.ts
 ├── utils/                    # Utility classes
 │   └── jenkins.utils.ts
 ├── strategies/               # Strategy pattern implementations
 │   └── credential.strategy.ts
 ├── http/                     # HTTP client abstraction
 │   └── jenkins-http.client.ts
 ├── services/                 # Business logic services
 │   ├── jenkins-job.service.ts
 │   ├── jenkins-build.service.ts
 │   └── jenkins-credential.service.ts
 ├── jenkins.client.ts         # Main client facade
 ├── index.ts                  # Module exports
 └── README.md                 # This file
-```
+```
src/api/ci/jenkins/services/jenkins-job.service.ts (1)

24-24: Consider extracting folder mode constant.

The folder mode com.cloudbees.hudson.plugins.folder.Folder is hardcoded. Consider moving it to JenkinsConfig for better maintainability.

Add to JenkinsConfig:

public static readonly FOLDER_MODE = 'com.cloudbees.hudson.plugins.folder.Folder';

Then update this line:

-const path = `${JenkinsConfig.ENDPOINTS.CREATE_ITEM}?name=${encodeURIComponent(folderConfig.name)}&mode=com.cloudbees.hudson.plugins.folder.Folder`;
+const path = `${JenkinsConfig.ENDPOINTS.CREATE_ITEM}?name=${encodeURIComponent(folderConfig.name)}&mode=${JenkinsConfig.FOLDER_MODE}`;
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 139b04a and 91642e7.

📒 Files selected for processing (18)
  • src/api/ci/gitlabciClient.ts (1 hunks)
  • src/api/ci/jenkins/README.md (1 hunks)
  • src/api/ci/jenkins/config/jenkins.config.ts (1 hunks)
  • src/api/ci/jenkins/enums/jenkins.enums.ts (1 hunks)
  • src/api/ci/jenkins/errors/jenkins.errors.ts (1 hunks)
  • src/api/ci/jenkins/http/jenkins-http.client.ts (1 hunks)
  • src/api/ci/jenkins/index.ts (1 hunks)
  • src/api/ci/jenkins/jenkins.client.ts (1 hunks)
  • src/api/ci/jenkins/services/jenkins-build.service.ts (1 hunks)
  • src/api/ci/jenkins/services/jenkins-credential.service.ts (1 hunks)
  • src/api/ci/jenkins/services/jenkins-job.service.ts (1 hunks)
  • src/api/ci/jenkins/strategies/credential.strategy.ts (1 hunks)
  • src/api/ci/jenkins/types/jenkins.types.ts (1 hunks)
  • src/api/ci/jenkins/utils/jenkins.utils.ts (1 hunks)
  • src/rhtap/core/integration/ci/providers/gitlabCI.ts (1 hunks)
  • src/rhtap/core/integration/ci/providers/jenkinsCI.ts (2 hunks)
  • src/rhtap/postcreation/strategies/commands/addJenkinsSecretsCommand.ts (1 hunks)
  • tests/api/ci/jenkinsClient.test.ts (1 hunks)
🧬 Code Graph Analysis (3)
src/api/ci/jenkins/utils/jenkins.utils.ts (4)
src/api/ci/jenkins/config/jenkins.config.ts (1)
  • JenkinsConfig (4-44)
src/api/ci/jenkins/index.ts (1)
  • JenkinsConfig (8-8)
src/api/ci/jenkins/types/jenkins.types.ts (1)
  • CreateJobOptions (33-40)
src/api/ci/jenkins/jenkins.client.ts (1)
  • build (181-198)
src/api/ci/jenkins/http/jenkins-http.client.ts (3)
src/api/ci/jenkins/index.ts (1)
  • JenkinsHttpClient (20-20)
src/api/ci/jenkins/types/jenkins.types.ts (2)
  • JenkinsClientConfig (16-20)
  • JenkinsApiResponse (6-11)
src/api/ci/jenkins/errors/jenkins.errors.ts (3)
  • JenkinsError (4-18)
  • JenkinsAuthenticationError (75-80)
  • JenkinsRateLimitError (85-93)
src/api/ci/jenkins/strategies/credential.strategy.ts (1)
src/api/ci/jenkins/config/jenkins.config.ts (1)
  • JenkinsConfig (4-44)
🪛 Biome (1.9.4)
src/api/ci/jenkins/utils/jenkins.utils.ts

[error] 7-52: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)


[error] 49-49: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 57-131: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)


[error] 64-64: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 100-100: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 101-101: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 106-106: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 113-113: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 136-226: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)


[error] 145-145: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 154-154: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 162-162: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 176-177: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 223-224: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 231-264: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)


[error] 254-254: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)

src/api/ci/jenkins/services/jenkins-build.service.ts

[error] 352-352: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 360-360: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 363-363: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

src/api/ci/jenkins/config/jenkins.config.ts

[error] 4-44: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)

src/api/ci/jenkins/http/jenkins-http.client.ts

[error] 59-59: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)

src/api/ci/jenkins/strategies/credential.strategy.ts

[error] 130-163: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)


[error] 141-141: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 154-154: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 161-161: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)

🪛 markdownlint-cli2 (0.17.2)
src/api/ci/jenkins/README.md

20-20: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

✅ Files skipped from review due to trivial changes (2)
  • src/api/ci/jenkins/enums/jenkins.enums.ts
  • src/api/ci/jenkins/index.ts
🚧 Files skipped from review as they are similar to previous changes (8)
  • src/rhtap/postcreation/strategies/commands/addJenkinsSecretsCommand.ts
  • tests/api/ci/jenkinsClient.test.ts
  • src/rhtap/core/integration/ci/providers/jenkinsCI.ts
  • src/rhtap/core/integration/ci/providers/gitlabCI.ts
  • src/api/ci/gitlabciClient.ts
  • src/api/ci/jenkins/types/jenkins.types.ts
  • src/api/ci/jenkins/errors/jenkins.errors.ts
  • src/api/ci/jenkins/jenkins.client.ts
🧰 Additional context used
🧬 Code Graph Analysis (3)
src/api/ci/jenkins/utils/jenkins.utils.ts (4)
src/api/ci/jenkins/config/jenkins.config.ts (1)
  • JenkinsConfig (4-44)
src/api/ci/jenkins/index.ts (1)
  • JenkinsConfig (8-8)
src/api/ci/jenkins/types/jenkins.types.ts (1)
  • CreateJobOptions (33-40)
src/api/ci/jenkins/jenkins.client.ts (1)
  • build (181-198)
src/api/ci/jenkins/http/jenkins-http.client.ts (3)
src/api/ci/jenkins/index.ts (1)
  • JenkinsHttpClient (20-20)
src/api/ci/jenkins/types/jenkins.types.ts (2)
  • JenkinsClientConfig (16-20)
  • JenkinsApiResponse (6-11)
src/api/ci/jenkins/errors/jenkins.errors.ts (3)
  • JenkinsError (4-18)
  • JenkinsAuthenticationError (75-80)
  • JenkinsRateLimitError (85-93)
src/api/ci/jenkins/strategies/credential.strategy.ts (1)
src/api/ci/jenkins/config/jenkins.config.ts (1)
  • JenkinsConfig (4-44)
🪛 Biome (1.9.4)
src/api/ci/jenkins/utils/jenkins.utils.ts

[error] 7-52: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)


[error] 49-49: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 57-131: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)


[error] 64-64: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 100-100: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 101-101: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 106-106: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 113-113: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 136-226: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)


[error] 145-145: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 154-154: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 162-162: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 176-177: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 223-224: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 231-264: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)


[error] 254-254: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)

src/api/ci/jenkins/services/jenkins-build.service.ts

[error] 352-352: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 360-360: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 363-363: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

src/api/ci/jenkins/config/jenkins.config.ts

[error] 4-44: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)

src/api/ci/jenkins/http/jenkins-http.client.ts

[error] 59-59: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)

src/api/ci/jenkins/strategies/credential.strategy.ts

[error] 130-163: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)


[error] 141-141: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 154-154: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 161-161: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)

🪛 markdownlint-cli2 (0.17.2)
src/api/ci/jenkins/README.md

20-20: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🔇 Additional comments (1)
src/api/ci/jenkins/services/jenkins-job.service.ts (1)

62-74: LGTM!

The method correctly handles job path formatting for nested folders and has appropriate error handling.


// Determine trigger type if requested
if (includeTriggerInfo) {
buildInfo.triggerType = JenkinsTriggerAnalyzer.determineBuildTrigger(buildInfo) as JenkinsBuildTrigger;
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Avoid unsafe type assertion for trigger type.

The type assertion as JenkinsBuildTrigger could hide type mismatches. Consider validating the trigger type.

-buildInfo.triggerType = JenkinsTriggerAnalyzer.determineBuildTrigger(buildInfo) as JenkinsBuildTrigger;
+const triggerType = JenkinsTriggerAnalyzer.determineBuildTrigger(buildInfo);
+buildInfo.triggerType = Object.values(JenkinsBuildTrigger).includes(triggerType as JenkinsBuildTrigger) 
+  ? triggerType as JenkinsBuildTrigger 
+  : JenkinsBuildTrigger.UNKNOWN;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
buildInfo.triggerType = JenkinsTriggerAnalyzer.determineBuildTrigger(buildInfo) as JenkinsBuildTrigger;
// Validate that the determined trigger is a known JenkinsBuildTrigger,
// fallback to UNKNOWN if it’s not a valid enum member.
const triggerType = JenkinsTriggerAnalyzer.determineBuildTrigger(buildInfo);
buildInfo.triggerType = Object
.values(JenkinsBuildTrigger)
.includes(triggerType as JenkinsBuildTrigger)
? (triggerType as JenkinsBuildTrigger)
: JenkinsBuildTrigger.UNKNOWN;
🤖 Prompt for AI Agents
In src/api/ci/jenkins/services/jenkins-build.service.ts at line 77, avoid using
the unsafe type assertion 'as JenkinsBuildTrigger' for the triggerType
assignment. Instead, validate the result of
JenkinsTriggerAnalyzer.determineBuildTrigger(buildInfo) to ensure it matches the
expected JenkinsBuildTrigger type before assignment. Implement a type guard or
conditional check to confirm the type and handle unexpected values appropriately
to prevent type mismatches.

Comment on lines +231 to +264
export class JenkinsPollingUtils {
/**
* Generic polling utility with timeout
*/
static async pollUntil<T>(
pollFn: () => Promise<T>,
conditionFn: (result: T) => boolean,
timeoutMs: number = JenkinsConfig.DEFAULT_TIMEOUT_MS,
intervalMs: number = JenkinsConfig.DEFAULT_POLL_INTERVAL_MS
): Promise<T> {
const startTime = Date.now();

while (true) {
const result = await pollFn();

if (conditionFn(result)) {
return result;
}

if (Date.now() - startTime > timeoutMs) {
throw new Error(`Polling timed out after ${timeoutMs}ms`);
}

await this.sleep(intervalMs);
}
}

/**
* Sleep utility
*/
static sleep(ms: number): Promise<void> {
return new Promise(resolve => setTimeout(resolve, ms));
}
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Refactor polling utilities to functions.

Convert this static-only class to standalone functions for consistency with other utilities.

-export class JenkinsPollingUtils {
-  static async pollUntil<T>(
+export async function pollUntil<T>(
     pollFn: () => Promise<T>,
     conditionFn: (result: T) => boolean,
     timeoutMs: number = JenkinsConfig.DEFAULT_TIMEOUT_MS,
     intervalMs: number = JenkinsConfig.DEFAULT_POLL_INTERVAL_MS
   ): Promise<T> {
     // ... implementation ...
-      await this.sleep(intervalMs);
+      await sleep(intervalMs);
     }
-  }
+}

-  static sleep(ms: number): Promise<void> {
+export function sleep(ms: number): Promise<void> {
     return new Promise(resolve => setTimeout(resolve, ms));
-  }
-}
+}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export class JenkinsPollingUtils {
/**
* Generic polling utility with timeout
*/
static async pollUntil<T>(
pollFn: () => Promise<T>,
conditionFn: (result: T) => boolean,
timeoutMs: number = JenkinsConfig.DEFAULT_TIMEOUT_MS,
intervalMs: number = JenkinsConfig.DEFAULT_POLL_INTERVAL_MS
): Promise<T> {
const startTime = Date.now();
while (true) {
const result = await pollFn();
if (conditionFn(result)) {
return result;
}
if (Date.now() - startTime > timeoutMs) {
throw new Error(`Polling timed out after ${timeoutMs}ms`);
}
await this.sleep(intervalMs);
}
}
/**
* Sleep utility
*/
static sleep(ms: number): Promise<void> {
return new Promise(resolve => setTimeout(resolve, ms));
}
}
/**
* Generic polling utility with timeout
*/
export async function pollUntil<T>(
pollFn: () => Promise<T>,
conditionFn: (result: T) => boolean,
timeoutMs: number = JenkinsConfig.DEFAULT_TIMEOUT_MS,
intervalMs: number = JenkinsConfig.DEFAULT_POLL_INTERVAL_MS
): Promise<T> {
const startTime = Date.now();
while (true) {
const result = await pollFn();
if (conditionFn(result)) {
return result;
}
if (Date.now() - startTime > timeoutMs) {
throw new Error(`Polling timed out after ${timeoutMs}ms`);
}
await sleep(intervalMs);
}
}
/**
* Sleep utility
*/
export function sleep(ms: number): Promise<void> {
return new Promise(resolve => setTimeout(resolve, ms));
}
🧰 Tools
🪛 Biome (1.9.4)

[error] 231-264: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)


[error] 254-254: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)

🤖 Prompt for AI Agents
In src/api/ci/jenkins/utils/jenkins.utils.ts from lines 231 to 264, refactor the
JenkinsPollingUtils static class into standalone functions. Extract the
pollUntil method into an async function named pollUntil, and the sleep method
into a separate function named sleep. Remove the class wrapper and export these
functions individually to align with the style of other utility functions in the
codebase.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (18)
src/api/ci/jenkins/config/jenkins.config.ts (1)

4-44: Static-only class anti-pattern still needs addressing.

This issue was previously identified and the suggested refactor to use a const object instead of a static-only class is still valid.

src/api/ci/jenkins/http/jenkins-http.client.ts (2)

58-60: Fix variable scoping in switch statement.

The scoping issue in the switch case was previously identified and still needs to be addressed.


112-117: Remove redundant status check.

This redundant status check was previously identified and should be removed as suggested.

src/api/ci/jenkins/strategies/credential.strategy.ts (2)

29-36: DRY violation: Extract duplicated XML escaping logic.

The XML escaping logic duplication was previously identified and is now present in three places (including the new SSH strategy). This should be extracted to a shared utility as suggested.


130-163: Refactor static-only factory class.

The static-only class anti-pattern was previously identified and should be refactored to use module-level functions as suggested.

src/api/ci/jenkins/services/jenkins-credential.service.ts (2)

62-67: Extract credential path building to utility method

The path building logic is duplicated across updateCredential, deleteCredential, and other methods. Consider adding a helper method to JenkinsPathBuilder for credential-specific paths.

This would improve maintainability and ensure consistent path construction.


120-120: Define proper types instead of using 'any'.

Using any type reduces type safety and makes the API contract unclear. Consider defining interfaces for credential responses.

Also applies to: 143-143, 152-152

src/api/ci/jenkins/services/jenkins-job.service.ts (1)

53-56: Use appropriate error type for job creation failure

Throwing JenkinsJobNotFoundError when job creation fails is semantically incorrect. Consider creating a JenkinsJobCreationError or using a more generic JenkinsError with appropriate context.

src/api/ci/jenkins/utils/jenkins.utils.ts (4)

7-52: Consider refactoring static utility class to functions.

The JenkinsPathBuilder class contains only static methods. Consider refactoring to standalone functions for better tree-shaking and cleaner code. Also, replace this with the class name in static contexts.


54-131: Refactor XML builder to functions and fix static method references.

Like JenkinsPathBuilder, this static-only class should be refactored to functions. The XML escaping implementation is excellent and properly handles all special characters.


136-226: Improve type safety and code consistency in trigger analyzer.

The JenkinsTriggerAnalyzer has comprehensive logic but uses any types and inconsistent optional chaining. Consider:

  1. Define proper types for build objects instead of using any
  2. Use optional chaining consistently
  3. Consider refactoring to functions

231-264: Refactor polling utilities to functions.

Convert this static-only class to standalone functions for consistency with other utilities.

src/api/ci/jenkins/services/jenkins-build.service.ts (3)

79-79: Avoid unsafe type assertion for trigger type.

The type assertion as JenkinsBuildTrigger could hide type mismatches. Consider validating the trigger type.


212-255: Remove debug console.log statements

Multiple console.log statements appear to be debug code that should not be in production. Consider using a proper logging framework with configurable log levels or removing these statements entirely.


309-367: Remove additional debug console.log statements

This method also contains multiple console.log statements that should be removed or replaced with proper logging.

src/api/ci/jenkins/jenkins.client.ts (3)

72-87: Add runtime validation for legacy method parameters.

The non-null assertion on line 76 (repoUrl!) could cause runtime errors if the method is called with undefined parameters. Consider adding validation.


299-320: Validate required parameters in waitForBuildCompletion.

The non-null assertion on line 310 should be replaced with proper validation.


332-351: Validate required parameters in getBuildByCommitSha.

The non-null assertion on line 342 should be replaced with validation.

🧹 Nitpick comments (2)
src/api/ci/jenkins/README.md (1)

20-43: Specify language for fenced code block.

The directory structure code block should specify a language for better markdown compliance.

-```
+```text
 jenkins/
 ├── enums/                    # Enums for Jenkins constants
 │   └── jenkins.enums.ts
src/api/ci/jenkins/strategies/credential.strategy.ts (1)

104-114: Consider validation for SSH private key format.

While the parsing logic is sound, consider adding basic validation to ensure the private key appears to be in valid format (e.g., starts with -----BEGIN and ends with -----END).

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 91642e7 and 676dbf8.

📒 Files selected for processing (18)
  • src/api/ci/gitlabciClient.ts (1 hunks)
  • src/api/ci/jenkins/README.md (1 hunks)
  • src/api/ci/jenkins/config/jenkins.config.ts (1 hunks)
  • src/api/ci/jenkins/enums/jenkins.enums.ts (1 hunks)
  • src/api/ci/jenkins/errors/jenkins.errors.ts (1 hunks)
  • src/api/ci/jenkins/http/jenkins-http.client.ts (1 hunks)
  • src/api/ci/jenkins/index.ts (1 hunks)
  • src/api/ci/jenkins/jenkins.client.ts (1 hunks)
  • src/api/ci/jenkins/services/jenkins-build.service.ts (1 hunks)
  • src/api/ci/jenkins/services/jenkins-credential.service.ts (1 hunks)
  • src/api/ci/jenkins/services/jenkins-job.service.ts (1 hunks)
  • src/api/ci/jenkins/strategies/credential.strategy.ts (1 hunks)
  • src/api/ci/jenkins/types/jenkins.types.ts (1 hunks)
  • src/api/ci/jenkins/utils/jenkins.utils.ts (1 hunks)
  • src/rhtap/core/integration/ci/providers/gitlabCI.ts (1 hunks)
  • src/rhtap/core/integration/ci/providers/jenkinsCI.ts (4 hunks)
  • src/rhtap/postcreation/strategies/commands/addJenkinsSecretsCommand.ts (1 hunks)
  • tests/api/ci/jenkinsClient.test.ts (1 hunks)
🧬 Code Graph Analysis (2)
src/api/ci/jenkins/http/jenkins-http.client.ts (3)
src/api/ci/jenkins/index.ts (1)
  • JenkinsHttpClient (20-20)
src/api/ci/jenkins/types/jenkins.types.ts (2)
  • JenkinsClientConfig (16-20)
  • JenkinsApiResponse (6-11)
src/api/ci/jenkins/errors/jenkins.errors.ts (3)
  • JenkinsError (4-18)
  • JenkinsAuthenticationError (75-80)
  • JenkinsRateLimitError (85-93)
src/api/ci/jenkins/strategies/credential.strategy.ts (1)
src/api/ci/jenkins/config/jenkins.config.ts (1)
  • JenkinsConfig (4-44)
🪛 Biome (1.9.4)
src/api/ci/jenkins/services/jenkins-build.service.ts

[error] 354-354: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 362-362: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 365-365: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

src/api/ci/jenkins/config/jenkins.config.ts

[error] 4-44: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)

src/api/ci/jenkins/http/jenkins-http.client.ts

[error] 59-59: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)

src/api/ci/jenkins/strategies/credential.strategy.ts

[error] 130-163: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)


[error] 141-141: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 154-154: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 161-161: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)

src/api/ci/jenkins/utils/jenkins.utils.ts

[error] 7-52: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)


[error] 49-49: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 57-131: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)


[error] 64-64: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 100-100: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 101-101: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 106-106: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 113-113: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 136-226: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)


[error] 145-145: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 154-154: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 162-162: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 176-177: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 223-224: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 231-264: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)


[error] 254-254: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)

🪛 markdownlint-cli2 (0.17.2)
src/api/ci/jenkins/README.md

20-20: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

✅ Files skipped from review due to trivial changes (3)
  • src/rhtap/core/integration/ci/providers/gitlabCI.ts
  • src/api/ci/jenkins/enums/jenkins.enums.ts
  • src/api/ci/jenkins/index.ts
🚧 Files skipped from review as they are similar to previous changes (5)
  • src/rhtap/postcreation/strategies/commands/addJenkinsSecretsCommand.ts
  • tests/api/ci/jenkinsClient.test.ts
  • src/api/ci/gitlabciClient.ts
  • src/api/ci/jenkins/errors/jenkins.errors.ts
  • src/rhtap/core/integration/ci/providers/jenkinsCI.ts
🧰 Additional context used
🧬 Code Graph Analysis (2)
src/api/ci/jenkins/http/jenkins-http.client.ts (3)
src/api/ci/jenkins/index.ts (1)
  • JenkinsHttpClient (20-20)
src/api/ci/jenkins/types/jenkins.types.ts (2)
  • JenkinsClientConfig (16-20)
  • JenkinsApiResponse (6-11)
src/api/ci/jenkins/errors/jenkins.errors.ts (3)
  • JenkinsError (4-18)
  • JenkinsAuthenticationError (75-80)
  • JenkinsRateLimitError (85-93)
src/api/ci/jenkins/strategies/credential.strategy.ts (1)
src/api/ci/jenkins/config/jenkins.config.ts (1)
  • JenkinsConfig (4-44)
🪛 Biome (1.9.4)
src/api/ci/jenkins/services/jenkins-build.service.ts

[error] 354-354: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 362-362: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 365-365: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

src/api/ci/jenkins/config/jenkins.config.ts

[error] 4-44: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)

src/api/ci/jenkins/http/jenkins-http.client.ts

[error] 59-59: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)

src/api/ci/jenkins/strategies/credential.strategy.ts

[error] 130-163: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)


[error] 141-141: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 154-154: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 161-161: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)

src/api/ci/jenkins/utils/jenkins.utils.ts

[error] 7-52: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)


[error] 49-49: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 57-131: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)


[error] 64-64: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 100-100: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 101-101: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 106-106: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 113-113: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 136-226: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)


[error] 145-145: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 154-154: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 162-162: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 176-177: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 223-224: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 231-264: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)


[error] 254-254: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)

🪛 markdownlint-cli2 (0.17.2)
src/api/ci/jenkins/README.md

20-20: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Red Hat Konflux / tssc-test-on-pull-request
🔇 Additional comments (4)
src/api/ci/jenkins/README.md (1)

1-231: Excellent comprehensive documentation.

The README provides thorough documentation of the refactored architecture, usage examples, design patterns, and extensibility guidelines. This will greatly help developers understand and maintain the Jenkins client.

src/api/ci/jenkins/types/jenkins.types.ts (1)

1-179: Comprehensive and well-structured type definitions.

The type definitions provide excellent TypeScript support for the Jenkins client with:

  • Strong typing for all API responses and configuration objects
  • Proper use of enums for build results and triggers
  • Clear interface structure matching Jenkins API patterns
  • Good separation of concerns between different operation types
src/api/ci/jenkins/http/jenkins-http.client.ts (1)

12-184: Well-designed HTTP client abstraction.

The HTTP client provides excellent abstraction with:

  • Proper error handling and custom Jenkins-specific errors
  • Consistent API response structure
  • Utility methods for ping and version checking
  • Centralized request/response interceptors
src/api/ci/jenkins/strategies/credential.strategy.ts (1)

84-125: Well-implemented SSH credential strategy.

The SSH private key credential strategy is well-implemented with:

  • Proper credential parsing with delimiter separation (::)
  • Validation for required fields
  • Support for optional passphrase
  • Correct Jenkins XML structure for SSH credentials

// Method 5: Check in build causes
if (build.causes) {
for (const cause of build.causes) {
if (cause.shortDescription && cause.shortDescription.includes(normalizedCommitSha)) {
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Use optional chaining for safer property access

Consider using optional chaining for safer property access to prevent potential runtime errors.

-    if (build.causes) {
+    if (build.causes?.length) {
       for (const cause of build.causes) {
-        if (cause.shortDescription && cause.shortDescription.includes(normalizedCommitSha)) {
+        if (cause.shortDescription?.includes(normalizedCommitSha)) {
           console.log(`Found matching commit in build causes: ${cause.shortDescription}`);
           return true;
         }
       }
     }

     // Method 6: Check in build display name or description
-    if (build.displayName && build.displayName.includes(normalizedCommitSha)) {
+    if (build.displayName?.includes(normalizedCommitSha)) {
       console.log(`Found matching commit in build display name: ${build.displayName}`);
       return true;
-    } else if (build.description && build.description.includes(normalizedCommitSha)) {
+    } else if (build.description?.includes(normalizedCommitSha)) {
       console.log(`Found matching commit in build description: ${build.description}`);
       return true;
     }

Also applies to: 362-365

🧰 Tools
🪛 Biome (1.9.4)

[error] 354-354: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

🤖 Prompt for AI Agents
In src/api/ci/jenkins/services/jenkins-build.service.ts at lines 354 and
362-365, replace direct property accesses like cause.shortDescription with
optional chaining (cause?.shortDescription) to safely handle cases where cause
or its properties might be undefined, preventing runtime errors.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

♻️ Duplicate comments (14)
src/api/ci/jenkins/config/jenkins.config.ts (1)

4-44: Refactor to avoid static-only class anti-pattern.

src/api/ci/jenkins/strategies/credential.strategy.ts (2)

29-36: DRY violation: Duplicated XML escaping logic.

Also applies to: 71-78, 117-124


130-163: Refactor static-only factory class to use functions or namespace.

src/api/ci/jenkins/http/jenkins-http.client.ts (2)

58-61: Fix variable scoping in switch statement.


112-117: Remove redundant status check.

src/api/ci/jenkins/services/jenkins-job.service.ts (1)

53-56: Use appropriate error type for job creation failure.

src/api/ci/jenkins/utils/jenkins.utils.ts (4)

7-52: Consider refactoring static utility class to functions.

The previous review comment about converting this static-only class to standalone functions is still applicable. The class contains only static methods and should be refactored for better tree-shaking and cleaner code structure.


57-131: Refactor XML builder to functions and fix static method references.

The previous review comment about refactoring this static-only class to standalone functions is still applicable. The XML escaping implementation is excellent, but the class should be converted to functions for consistency.


136-226: Improve type safety and code consistency in trigger analyzer.

The previous review comment about defining proper types instead of using any and refactoring to functions is still applicable. The class needs better type definitions and consistent optional chaining usage.


231-264: Refactor polling utilities to functions.

The previous review comment about converting this static-only class to standalone functions for consistency is still applicable.

src/api/ci/jenkins/services/jenkins-build.service.ts (4)

212-256: Remove debug console.log statements

The previous review comment about removing console.log statements used for debugging is still applicable. Multiple console.log statements appear throughout this method (lines 212, 222, 226, 234, 244-246, 253-255) and should be removed from production code.


309-366: Remove additional debug console.log statements

The previous review comment about removing console.log statements is still applicable. This method contains multiple debug logging statements (lines 309, 320, 333, 344, 355, 363, 366) that should be removed from production code.


354-365: Use optional chaining for safer property access

The previous review comment about using optional chaining for safer property access is still applicable. Consider updating the property access patterns to use optional chaining consistently.


79-79: Avoid unsafe type assertion for trigger type.

The previous review comment about avoiding the unsafe type assertion as JenkinsBuildTrigger is still applicable. Consider validating the trigger type before assignment to prevent type mismatches.

🧹 Nitpick comments (2)
src/api/ci/jenkins/README.md (1)

20-43: Add language specification to fenced code block.

The directory structure code block should specify a language for proper syntax highlighting.

-```
+```
jenkins/
├── enums/                    # Enums for Jenkins constants
│   └── jenkins.enums.ts
-```
+```
src/api/ci/jenkins/services/jenkins-build.service.ts (1)

439-468: Consider removing or replacing console.log statements with proper logging.

Additional console.log statements are present in the waitForMultipleJobsToComplete method that weren't addressed in previous reviews. For consistency with the debug logging cleanup, consider using a proper logging framework or removing these statements.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 676dbf8 and 36ca4ca.

📒 Files selected for processing (18)
  • src/api/ci/gitlabciClient.ts (1 hunks)
  • src/api/ci/jenkins/README.md (1 hunks)
  • src/api/ci/jenkins/config/jenkins.config.ts (1 hunks)
  • src/api/ci/jenkins/enums/jenkins.enums.ts (1 hunks)
  • src/api/ci/jenkins/errors/jenkins.errors.ts (1 hunks)
  • src/api/ci/jenkins/http/jenkins-http.client.ts (1 hunks)
  • src/api/ci/jenkins/index.ts (1 hunks)
  • src/api/ci/jenkins/jenkins.client.ts (1 hunks)
  • src/api/ci/jenkins/services/jenkins-build.service.ts (1 hunks)
  • src/api/ci/jenkins/services/jenkins-credential.service.ts (1 hunks)
  • src/api/ci/jenkins/services/jenkins-job.service.ts (1 hunks)
  • src/api/ci/jenkins/strategies/credential.strategy.ts (1 hunks)
  • src/api/ci/jenkins/types/jenkins.types.ts (1 hunks)
  • src/api/ci/jenkins/utils/jenkins.utils.ts (1 hunks)
  • src/rhtap/core/integration/ci/providers/gitlabCI.ts (1 hunks)
  • src/rhtap/core/integration/ci/providers/jenkinsCI.ts (4 hunks)
  • src/rhtap/postcreation/strategies/commands/addJenkinsSecretsCommand.ts (1 hunks)
  • tests/api/ci/jenkinsClient.test.ts (1 hunks)
🧬 Code Graph Analysis (3)
src/api/ci/jenkins/services/jenkins-job.service.ts (5)
src/api/ci/jenkins/http/jenkins-http.client.ts (1)
  • JenkinsHttpClient (12-184)
src/api/ci/jenkins/types/jenkins.types.ts (4)
  • FolderConfig (25-28)
  • JenkinsApiResponse (6-11)
  • CreateJobOptions (33-40)
  • JenkinsJob (114-158)
src/api/ci/jenkins/utils/jenkins.utils.ts (2)
  • JenkinsXmlBuilder (57-131)
  • JenkinsPathBuilder (7-52)
src/api/ci/jenkins/config/jenkins.config.ts (1)
  • JenkinsConfig (4-44)
src/api/ci/jenkins/errors/jenkins.errors.ts (2)
  • JenkinsFolderError (65-70)
  • JenkinsJobNotFoundError (23-29)
src/api/ci/jenkins/http/jenkins-http.client.ts (3)
src/api/ci/jenkins/index.ts (1)
  • JenkinsHttpClient (20-20)
src/api/ci/jenkins/types/jenkins.types.ts (2)
  • JenkinsClientConfig (16-20)
  • JenkinsApiResponse (6-11)
src/api/ci/jenkins/errors/jenkins.errors.ts (3)
  • JenkinsError (4-18)
  • JenkinsAuthenticationError (75-80)
  • JenkinsRateLimitError (85-93)
src/api/ci/jenkins/strategies/credential.strategy.ts (1)
src/api/ci/jenkins/config/jenkins.config.ts (1)
  • JenkinsConfig (4-44)
🪛 Biome (1.9.4)
src/api/ci/jenkins/services/jenkins-build.service.ts

[error] 354-354: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 362-362: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 365-365: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

src/api/ci/jenkins/config/jenkins.config.ts

[error] 4-44: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)

src/api/ci/jenkins/http/jenkins-http.client.ts

[error] 59-59: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)

src/api/ci/jenkins/strategies/credential.strategy.ts

[error] 130-163: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)


[error] 141-141: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 154-154: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 161-161: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)

src/api/ci/jenkins/utils/jenkins.utils.ts

[error] 7-52: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)


[error] 49-49: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 57-131: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)


[error] 64-64: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 100-100: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 101-101: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 106-106: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 113-113: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 136-226: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)


[error] 145-145: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 154-154: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 162-162: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 176-177: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 223-224: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 231-264: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)


[error] 254-254: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)

🪛 markdownlint-cli2 (0.17.2)
src/api/ci/jenkins/README.md

20-20: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

✅ Files skipped from review due to trivial changes (3)
  • tests/api/ci/jenkinsClient.test.ts
  • src/api/ci/jenkins/enums/jenkins.enums.ts
  • src/api/ci/jenkins/index.ts
🚧 Files skipped from review as they are similar to previous changes (8)
  • src/rhtap/postcreation/strategies/commands/addJenkinsSecretsCommand.ts
  • src/rhtap/core/integration/ci/providers/gitlabCI.ts
  • src/api/ci/gitlabciClient.ts
  • src/api/ci/jenkins/types/jenkins.types.ts
  • src/api/ci/jenkins/errors/jenkins.errors.ts
  • src/rhtap/core/integration/ci/providers/jenkinsCI.ts
  • src/api/ci/jenkins/services/jenkins-credential.service.ts
  • src/api/ci/jenkins/jenkins.client.ts
🧰 Additional context used
🧬 Code Graph Analysis (3)
src/api/ci/jenkins/services/jenkins-job.service.ts (5)
src/api/ci/jenkins/http/jenkins-http.client.ts (1)
  • JenkinsHttpClient (12-184)
src/api/ci/jenkins/types/jenkins.types.ts (4)
  • FolderConfig (25-28)
  • JenkinsApiResponse (6-11)
  • CreateJobOptions (33-40)
  • JenkinsJob (114-158)
src/api/ci/jenkins/utils/jenkins.utils.ts (2)
  • JenkinsXmlBuilder (57-131)
  • JenkinsPathBuilder (7-52)
src/api/ci/jenkins/config/jenkins.config.ts (1)
  • JenkinsConfig (4-44)
src/api/ci/jenkins/errors/jenkins.errors.ts (2)
  • JenkinsFolderError (65-70)
  • JenkinsJobNotFoundError (23-29)
src/api/ci/jenkins/http/jenkins-http.client.ts (3)
src/api/ci/jenkins/index.ts (1)
  • JenkinsHttpClient (20-20)
src/api/ci/jenkins/types/jenkins.types.ts (2)
  • JenkinsClientConfig (16-20)
  • JenkinsApiResponse (6-11)
src/api/ci/jenkins/errors/jenkins.errors.ts (3)
  • JenkinsError (4-18)
  • JenkinsAuthenticationError (75-80)
  • JenkinsRateLimitError (85-93)
src/api/ci/jenkins/strategies/credential.strategy.ts (1)
src/api/ci/jenkins/config/jenkins.config.ts (1)
  • JenkinsConfig (4-44)
🪛 Biome (1.9.4)
src/api/ci/jenkins/services/jenkins-build.service.ts

[error] 354-354: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 362-362: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 365-365: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

src/api/ci/jenkins/config/jenkins.config.ts

[error] 4-44: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)

src/api/ci/jenkins/http/jenkins-http.client.ts

[error] 59-59: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)

src/api/ci/jenkins/strategies/credential.strategy.ts

[error] 130-163: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)


[error] 141-141: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 154-154: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 161-161: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)

src/api/ci/jenkins/utils/jenkins.utils.ts

[error] 7-52: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)


[error] 49-49: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 57-131: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)


[error] 64-64: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 100-100: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 101-101: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 106-106: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 113-113: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 136-226: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)


[error] 145-145: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 154-154: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 162-162: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 176-177: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 223-224: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 231-264: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)


[error] 254-254: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)

🪛 markdownlint-cli2 (0.17.2)
src/api/ci/jenkins/README.md

20-20: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Red Hat Konflux / tssc-test-on-pull-request

Comment on lines +93 to +96
} catch (error) {
const jobPath = folderName ? `${folderName}/${jobName}` : jobName;
throw new JenkinsJobNotFoundError(jobPath);
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Use appropriate error type for job deletion failure.

Throwing JenkinsJobNotFoundError when job deletion fails is semantically incorrect. The job may exist but the deletion operation failed for other reasons.

     } catch (error) {
       const jobPath = folderName ? `${folderName}/${jobName}` : jobName;
-      throw new JenkinsJobNotFoundError(jobPath);
+      throw new JenkinsError(
+        `Failed to delete job: ${jobPath}`,
+        undefined,
+        error instanceof Error ? error : undefined
+      );
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
} catch (error) {
const jobPath = folderName ? `${folderName}/${jobName}` : jobName;
throw new JenkinsJobNotFoundError(jobPath);
}
} catch (error) {
const jobPath = folderName ? `${folderName}/${jobName}` : jobName;
throw new JenkinsError(
`Failed to delete job: ${jobPath}`,
undefined,
error instanceof Error ? error : undefined
);
}
🤖 Prompt for AI Agents
In src/api/ci/jenkins/services/jenkins-job.service.ts around lines 93 to 96, the
catch block throws JenkinsJobNotFoundError on any job deletion failure, which is
incorrect because the job might exist but deletion failed for other reasons.
Replace JenkinsJobNotFoundError with a more appropriate error type that reflects
a deletion failure, such as a generic JenkinsJobDeletionError or a custom error
indicating deletion failure, and ensure the error message clearly states the
deletion operation failed.

Comment on lines +147 to +150
} catch (error) {
const jobPath = folderName ? `${folderName}/${jobName}` : jobName;
throw new JenkinsJobNotFoundError(jobPath);
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Use appropriate error types for operation failures.

Multiple methods incorrectly throw JenkinsJobNotFoundError for operation failures (disable, enable, update config, get config). These operations may fail for reasons other than the job not existing.

Consider creating more specific error types or using generic JenkinsError with descriptive messages:

     } catch (error) {
       const jobPath = folderName ? `${folderName}/${jobName}` : jobName;
-      throw new JenkinsJobNotFoundError(jobPath);
+      throw new JenkinsError(
+        `Failed to [operation] job: ${jobPath}`,
+        undefined,
+        error instanceof Error ? error : undefined
+      );
     }

Also applies to: 162-165, 177-180, 192-195

🤖 Prompt for AI Agents
In src/api/ci/jenkins/services/jenkins-job.service.ts around lines 147 to 150,
the catch blocks throw JenkinsJobNotFoundError for various operation failures
that may not be related to the job's existence. To fix this, create more
specific error classes for each failure type or use a generic JenkinsError with
detailed messages describing the actual failure cause. Apply this change
consistently to the catch blocks at lines 162-165, 177-180, and 192-195 as well.

@xinredhat xinredhat changed the title [WIP]refactor jenkins client refactor jenkins client Jul 23, 2025
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (15)
src/api/ci/jenkins/config/jenkins.config.ts (1)

4-44: Static-only class anti-pattern persists.

This issue was previously identified and the recommended refactor to use a const object or namespace instead of a static-only class has not been implemented.

src/api/ci/jenkins/http/jenkins-http.client.ts (2)

58-61: Variable scoping issue in switch statement persists.

The retryAfter variable declaration can still be accessed by other switch cases. The previously suggested fix to wrap the case in braces has not been implemented.


112-117: Redundant status check still present.

The unnecessary status check in the post method that duplicates the response interceptor's error handling has not been removed as previously suggested.

src/api/ci/jenkins/strategies/credential.strategy.ts (2)

29-36: DRY violation in XML escaping logic persists and has worsened.

The XML escaping duplication issue previously identified has not been addressed and now exists in three locations (lines 29-36, 71-78, and 117-124). The suggested utility function extraction has not been implemented.


130-163: Static-only factory class pattern still not refactored.

The previously identified issues with the static-only class and confusing 'this' usage in static context have not been addressed. The suggested refactor to module-level functions has not been implemented.

src/api/ci/jenkins/services/jenkins-credential.service.ts (2)

62-67: Credential path building duplication persists.

The duplicated path construction logic identified in the previous review has not been addressed. The same pattern exists in multiple methods (updateCredential, deleteCredential, getCredential, listCredentials).


120-120: Usage of 'any' type instead of proper interfaces persists.

The methods still return Promise instead of properly typed interfaces as previously suggested. This affects type safety and API clarity.

src/api/ci/jenkins/utils/jenkins.utils.ts (4)

7-52: The static-only class refactoring suggestion remains unaddressed.

The previous review comment about converting JenkinsPathBuilder to standalone functions is still applicable. This class contains only static methods and should be refactored for better tree-shaking and cleaner code structure.


57-131: The XML builder refactoring suggestion remains unaddressed.

The previous review comment about converting JenkinsXmlBuilder to standalone functions is still applicable. This static-only class should be refactored to improve code structure and eliminate static context confusion.


136-226: The type safety and refactoring suggestions remain unaddressed.

The previous review comment about improving type safety by replacing any types with proper interfaces and considering refactoring to functions is still applicable. The extensive use of any reduces code safety and clarity.


231-264: The polling utilities refactoring suggestion remains unaddressed.

The previous review comment about converting JenkinsPollingUtils to standalone functions is still applicable. This static-only class should be refactored for consistency with other utilities.

src/api/ci/jenkins/services/jenkins-build.service.ts (4)

79-79: The unsafe type assertion issue remains unaddressed.

The previous review comment about avoiding the unsafe type assertion as JenkinsBuildTrigger is still applicable. This could hide type mismatches and should be replaced with proper type validation.


212-255: Debug console.log statements remain unaddressed.

The previous review comment about removing console.log statements used for debugging purposes is still applicable. Multiple console.log statements are present throughout this method and should be removed or replaced with proper logging.


309-366: Debug console.log statements remain unaddressed.

The previous review comment about removing console.log statements in this method is still applicable. Multiple debugging statements should be cleaned up from production code.


354-365: Optional chaining improvements remain unaddressed.

The previous review comment about using optional chaining for safer property access is still applicable. Lines 354, 362, and 365 should use optional chaining to prevent potential runtime errors.

🧹 Nitpick comments (2)
src/api/ci/jenkins/README.md (1)

20-43: Add language specification to fenced code block.

The directory structure code block is missing a language specification which affects syntax highlighting and documentation tools.

-```
+```
jenkins/
src/api/ci/jenkins/services/jenkins-build.service.ts (1)

439-468: Consider replacing console.log with proper logging framework.

The console.log statements in this method appear to be intentional monitoring logs rather than debug statements. Consider using a proper logging framework with configurable log levels instead of direct console.log calls.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 36ca4ca and a950535.

📒 Files selected for processing (18)
  • src/api/ci/gitlabciClient.ts (1 hunks)
  • src/api/ci/jenkins/README.md (1 hunks)
  • src/api/ci/jenkins/config/jenkins.config.ts (1 hunks)
  • src/api/ci/jenkins/enums/jenkins.enums.ts (1 hunks)
  • src/api/ci/jenkins/errors/jenkins.errors.ts (1 hunks)
  • src/api/ci/jenkins/http/jenkins-http.client.ts (1 hunks)
  • src/api/ci/jenkins/index.ts (1 hunks)
  • src/api/ci/jenkins/jenkins.client.ts (1 hunks)
  • src/api/ci/jenkins/services/jenkins-build.service.ts (1 hunks)
  • src/api/ci/jenkins/services/jenkins-credential.service.ts (1 hunks)
  • src/api/ci/jenkins/services/jenkins-job.service.ts (1 hunks)
  • src/api/ci/jenkins/strategies/credential.strategy.ts (1 hunks)
  • src/api/ci/jenkins/types/jenkins.types.ts (1 hunks)
  • src/api/ci/jenkins/utils/jenkins.utils.ts (1 hunks)
  • src/rhtap/core/integration/ci/providers/gitlabCI.ts (1 hunks)
  • src/rhtap/core/integration/ci/providers/jenkinsCI.ts (4 hunks)
  • src/rhtap/postcreation/strategies/commands/addJenkinsSecretsCommand.ts (1 hunks)
  • tests/api/ci/jenkinsClient.test.ts (0 hunks)
🧬 Code Graph Analysis (3)
src/api/ci/jenkins/services/jenkins-credential.service.ts (6)
src/api/ci/jenkins/http/jenkins-http.client.ts (1)
  • JenkinsHttpClient (12-184)
src/api/ci/jenkins/types/jenkins.types.ts (1)
  • JenkinsApiResponse (6-11)
src/api/ci/jenkins/strategies/credential.strategy.ts (1)
  • CredentialStrategyFactory (130-163)
src/api/ci/jenkins/utils/jenkins.utils.ts (1)
  • JenkinsPathBuilder (7-52)
src/api/ci/jenkins/config/jenkins.config.ts (1)
  • JenkinsConfig (4-44)
src/api/ci/jenkins/errors/jenkins.errors.ts (1)
  • JenkinsCredentialError (55-60)
src/api/ci/jenkins/http/jenkins-http.client.ts (3)
src/api/ci/jenkins/index.ts (1)
  • JenkinsHttpClient (20-20)
src/api/ci/jenkins/types/jenkins.types.ts (2)
  • JenkinsClientConfig (16-20)
  • JenkinsApiResponse (6-11)
src/api/ci/jenkins/errors/jenkins.errors.ts (3)
  • JenkinsError (4-18)
  • JenkinsAuthenticationError (75-80)
  • JenkinsRateLimitError (85-93)
src/api/ci/jenkins/strategies/credential.strategy.ts (1)
src/api/ci/jenkins/config/jenkins.config.ts (1)
  • JenkinsConfig (4-44)
🪛 Biome (1.9.4)
src/api/ci/jenkins/services/jenkins-build.service.ts

[error] 354-354: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 362-362: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 365-365: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

src/api/ci/jenkins/config/jenkins.config.ts

[error] 4-44: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)

src/api/ci/jenkins/http/jenkins-http.client.ts

[error] 59-59: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)

src/api/ci/jenkins/strategies/credential.strategy.ts

[error] 130-163: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)


[error] 141-141: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 154-154: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 161-161: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)

src/api/ci/jenkins/utils/jenkins.utils.ts

[error] 7-52: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)


[error] 49-49: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 57-131: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)


[error] 64-64: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 100-100: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 101-101: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 106-106: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 113-113: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 136-226: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)


[error] 145-145: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 154-154: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 162-162: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 176-177: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 223-224: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 231-264: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)


[error] 254-254: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)

🪛 markdownlint-cli2 (0.17.2)
src/api/ci/jenkins/README.md

20-20: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

💤 Files with no reviewable changes (1)
  • tests/api/ci/jenkinsClient.test.ts
✅ Files skipped from review due to trivial changes (1)
  • src/api/ci/jenkins/enums/jenkins.enums.ts
🚧 Files skipped from review as they are similar to previous changes (9)
  • src/rhtap/postcreation/strategies/commands/addJenkinsSecretsCommand.ts
  • src/api/ci/gitlabciClient.ts
  • src/rhtap/core/integration/ci/providers/gitlabCI.ts
  • src/api/ci/jenkins/index.ts
  • src/api/ci/jenkins/types/jenkins.types.ts
  • src/api/ci/jenkins/errors/jenkins.errors.ts
  • src/api/ci/jenkins/services/jenkins-job.service.ts
  • src/rhtap/core/integration/ci/providers/jenkinsCI.ts
  • src/api/ci/jenkins/jenkins.client.ts
🧰 Additional context used
🧬 Code Graph Analysis (3)
src/api/ci/jenkins/services/jenkins-credential.service.ts (6)
src/api/ci/jenkins/http/jenkins-http.client.ts (1)
  • JenkinsHttpClient (12-184)
src/api/ci/jenkins/types/jenkins.types.ts (1)
  • JenkinsApiResponse (6-11)
src/api/ci/jenkins/strategies/credential.strategy.ts (1)
  • CredentialStrategyFactory (130-163)
src/api/ci/jenkins/utils/jenkins.utils.ts (1)
  • JenkinsPathBuilder (7-52)
src/api/ci/jenkins/config/jenkins.config.ts (1)
  • JenkinsConfig (4-44)
src/api/ci/jenkins/errors/jenkins.errors.ts (1)
  • JenkinsCredentialError (55-60)
src/api/ci/jenkins/http/jenkins-http.client.ts (3)
src/api/ci/jenkins/index.ts (1)
  • JenkinsHttpClient (20-20)
src/api/ci/jenkins/types/jenkins.types.ts (2)
  • JenkinsClientConfig (16-20)
  • JenkinsApiResponse (6-11)
src/api/ci/jenkins/errors/jenkins.errors.ts (3)
  • JenkinsError (4-18)
  • JenkinsAuthenticationError (75-80)
  • JenkinsRateLimitError (85-93)
src/api/ci/jenkins/strategies/credential.strategy.ts (1)
src/api/ci/jenkins/config/jenkins.config.ts (1)
  • JenkinsConfig (4-44)
🪛 Biome (1.9.4)
src/api/ci/jenkins/services/jenkins-build.service.ts

[error] 354-354: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 362-362: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 365-365: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

src/api/ci/jenkins/config/jenkins.config.ts

[error] 4-44: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)

src/api/ci/jenkins/http/jenkins-http.client.ts

[error] 59-59: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)

src/api/ci/jenkins/strategies/credential.strategy.ts

[error] 130-163: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)


[error] 141-141: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 154-154: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 161-161: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)

src/api/ci/jenkins/utils/jenkins.utils.ts

[error] 7-52: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)


[error] 49-49: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 57-131: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)


[error] 64-64: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 100-100: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 101-101: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 106-106: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 113-113: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 136-226: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)


[error] 145-145: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 154-154: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 162-162: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 176-177: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 223-224: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 231-264: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)


[error] 254-254: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)

🪛 markdownlint-cli2 (0.17.2)
src/api/ci/jenkins/README.md

20-20: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Red Hat Konflux / tssc-test-on-pull-request
🔇 Additional comments (4)
src/api/ci/jenkins/README.md (1)

1-231: Excellent comprehensive documentation.

This README provides thorough coverage of the refactored architecture, including:

  • Clear architectural overview with benefits
  • Well-structured directory layout
  • Multiple usage examples (backwards compatible and new patterns)
  • Design patterns explanation
  • Extension guidelines
  • Testing, performance, and security considerations

The documentation will greatly help developers understand and use the new Jenkins client architecture.

src/api/ci/jenkins/http/jenkins-http.client.ts (1)

1-184: Well-structured HTTP client with proper abstraction.

The implementation provides:

  • Clean Axios wrapper with appropriate configuration
  • Proper error handling with custom Jenkins error types
  • Comprehensive HTTP methods (GET, POST, PUT, DELETE)
  • Utility methods for ping and version checking
  • Consistent response formatting

The architecture separation between HTTP concerns and business logic is excellent.

src/api/ci/jenkins/strategies/credential.strategy.ts (1)

4-126: Solid strategy pattern implementation.

The credential strategy interface and concrete implementations provide:

  • Clean separation of concerns for different credential types
  • Proper XML generation for Jenkins credential API
  • Good input validation and parsing logic
  • Extensible design for adding new credential types

The overall architecture effectively uses the Strategy pattern to handle credential type variations.

src/api/ci/jenkins/services/jenkins-credential.service.ts (1)

1-220: Comprehensive credential service with good error handling.

The service provides:

  • Complete CRUD operations for Jenkins credentials
  • Proper integration with the strategy pattern for XML generation
  • Consistent error handling with custom JenkinsCredentialError
  • Convenient methods for different credential types
  • Support for both folder-scoped and system-scoped credentials

The service layer effectively abstracts Jenkins credential API complexity and provides a clean interface for credential management.

@chetna14manku
Copy link
Contributor

/lgtm

@xinredhat xinredhat merged commit df11574 into redhat-appstudio:main Jul 23, 2025
4 checks passed
@xinredhat xinredhat deleted the refactor_jenkins branch July 23, 2025 11:50
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.

2 participants