Skip to content

Conversation

@VlaadyslavRuban
Copy link
Collaborator

@VlaadyslavRuban VlaadyslavRuban commented May 9, 2025

dev

JIRA

Code reviewers

  • @github_username

Second Level Review

  • @github_username

Summary of issue

ToDo

Summary of change

ToDo

Testing approach

ToDo

CHECK LIST

  • СI passed
  • Сode coverage >=95%
  • PR is reviewed manually again (to make sure you have 100% ready code)
  • All reviewers agreed to merge the PR
  • I've checked new feature as logged in and logged out user if needed
  • PR meets all conventions

Summary by CodeRabbit

  • New Features
    • Introduced a new Docker image and entrypoint script for running database updates.
    • Added support for managing and deploying a separate database update container alongside the main backend.
    • Integrated Discord notifications for deployment events.
  • Improvements
    • Enhanced deployment pipeline to include security scanning for both backend and database update images.
    • Updated deployment process to handle multiple images and improve deployment control flow.
  • Removals
    • Removed automatic database migration and data seeding from application startup.

sashapanasiuk5 and others added 30 commits October 22, 2024 15:46
@coderabbitai
Copy link

coderabbitai bot commented May 9, 2025

Walkthrough

This update introduces a new Dockerfile and entrypoint script to containerize and run a .NET database update utility. The Jenkins pipeline is extended to build, scan, and deploy both backend and dbupdate images, with added security scanning and Discord notifications. The application startup code no longer triggers automatic database migrations or seeding.

Changes

File(s) Change Summary
Dockerfile.dbupdate, entrypoint.sh Added a new Dockerfile for the DbUpdate .NET project using multi-stage builds, and a shell script as an entrypoint for diagnostics and execution of DbUpdate.dll.
Jenkinsfile Extended pipeline to build, scan, and push both backend and dbupdate Docker images; added Trivy security scanning, Discord notifications, new helper function, and updated deployment logic to handle both images and containers.
Streetcode/Streetcode.WebApi/Program.cs Removed automatic database migration and seeding logic from application startup.

Sequence Diagram(s)

sequenceDiagram
    participant Dev as Developer
    participant Jenkins as Jenkins Pipeline
    participant Docker as Docker Registry
    participant Discord as Discord Webhook
    participant Server as Deployment Server

    Dev->>Jenkins: Pushes code (with Dockerfile.dbupdate, entrypoint.sh)
    Jenkins->>Jenkins: Build backend image
    Jenkins->>Jenkins: Build dbupdate image
    Jenkins->>Jenkins: Run Trivy scan on both images
    Jenkins->>Docker: Push backend image
    Jenkins->>Docker: Push dbupdate image
    Jenkins->>Server: Deploy backend and dbupdate containers
    Jenkins->>Discord: Send deployment status notification
Loading

Possibly related PRs

  • ita-social-projects/StreetCode#2729: Also modifies the Jenkinsfile to add Trivy security scans for Docker images, including the new "dbupdate" image, showing a direct connection in pipeline enhancements.

Poem

In Docker’s embrace, a new script takes flight,
With Jenkins now watching both day and night.
DbUpdate marches, its entrypoint clear,
Discord rings out when deployments appear.
No more migrations at startup’s first light—
Just logs, scans, and pipelines running tight!
🚀

Tip

⚡️ Faster reviews with caching
  • CodeRabbit now supports caching for code and dependencies, helping speed up reviews. This means quicker feedback, reduced wait times, and a smoother review experience overall. Cached data is encrypted and stored securely. This feature will be automatically enabled for all accounts on May 16th. To opt out, configure Review - Disable Cache at either the organization or repository level. If you prefer to disable all data retention across your organization, simply turn off the Data Retention setting under your Organization Settings.

Enjoy the performance boost—your workflow just got faster.


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.

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: 4

🔭 Outside diff range comments (1)
Jenkinsfile (1)

374-379: ⚠️ Potential issue

Authenticate GitHub CLI before release creation
The gh release create command will fail without a prior login. Use the injected GH_TOKEN:

+    withCredentials([string(credentialsId: 'GH_TOKEN', variable: 'GH_TOKEN')]) {
+      sh 'echo "$GH_TOKEN" | gh auth login --with-token'
+    }
     sh "gh release create v${vers}  --generate-notes --draft"

This ensures the CLI has permissions to publish the draft release.

🧹 Nitpick comments (9)
Dockerfile.dbupdate (2)

11-11: Remove debug ls from build stage
The RUN ls -la /tmp/ScriptsMigration line is useful for debugging but should be removed (or gated by a build argument) in production to keep the image lean and avoid unnecessary layers.


19-19: Fix typo in comment
The comment reads # Publishishing application; please correct it to # Publishing application to maintain professionalism.

entrypoint.sh (1)

4-16: Review diagnostic verbosity for production
You print directory listings, network info, and routing tables at startup. These are great for debugging but may clutter logs in routine runs. Consider conditioning them on a debug flag or removing them in the production build.

Jenkinsfile (6)

3-5: Rename boolean flags for clarity and grammar
IS_DBUPDATE_IMAGE_BUILDED and IS_DBUPDATE_IMAGE_PUSH contain a typo (builded). For readability, rename to IS_DBUPDATE_IMAGE_BUILT and IS_DBUPDATE_IMAGE_PUSHED.


16-18: Remove or use the unused GH_TOKEN credential
You inject GH_TOKEN into environment but never reference it in the pipeline. Either remove this line or leverage it for GitHub CLI authentication in the release stage.


144-162: Optimize Docker build context and caching
Building both images with the full repo context without a .dockerignore may include unnecessary files and bust cache often. Recommend adding a .dockerignore (to exclude .git, docs, test data, etc.) and, if possible, running each docker build in its project subfolder:

- sh "docker build -f Dockerfile.dbupdate -t ${username}/dbupdate:${env.CODE_VERSION} ."
+ dir('Streetcode/DbUpdate') {
+   sh "docker build -f ../../Dockerfile.dbupdate -t ${username}/dbupdate:${env.CODE_VERSION} ."
+}

This improves caching and reduces context size.


168-189: Enforce failures on critical Trivy vulnerabilities
Right now you append || true, which masks exit codes. If you want to gate the build on security findings, remove || true or collect scan summaries and fail explicitly when critical issues are found.


260-269: Rename non-descriptive stage name
The stage titled 'WHAT IS THE NEXT STEP' isn’t self-documenting. Consider renaming to 'Confirm Production Deployment' or similar to clarify its purpose.


445-467: Consolidate Discord webhook credential usage
You define DISCORD_WEBHOOK_URL in environment and again via withCredentials in your function. Choose one approach: either reference the env var directly in the curl call or centralize credential retrieval in sendDiscordNotification. This will simplify maintenance.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 96b1dea and 3559e33.

⛔ Files ignored due to path filters (20)
  • Streetcode/DbUpdate/DbUpdate.csproj is excluded by !**/Streetcode/DbUpdate/**
  • Streetcode/DbUpdate/Program.cs is excluded by !**/Streetcode/DbUpdate/**
  • Streetcode/DbUpdate/appsettings.IntegrationTests.json is excluded by !**/Streetcode/DbUpdate/**
  • Streetcode/Streetcode.DAL/Persistence/ScriptsMigration/HealthCheck.sql is excluded by !**/ScriptsMigration/**, !**/Streetcode/Streetcode.DAL/Persistence/ScriptsMigration/**
  • Streetcode/Streetcode.DAL/Persistence/ScriptsMigration/Script_20230703154732_UpdatePartnerModel.sql is excluded by !**/ScriptsMigration/**, !**/Streetcode/Streetcode.DAL/Persistence/ScriptsMigration/**
  • Streetcode/Streetcode.DAL/Persistence/ScriptsMigration/Script_20230804120930_Change_StreetcodeCategoryContent_Text_to_10000_simb.sql is excluded by !**/ScriptsMigration/**, !**/Streetcode/Streetcode.DAL/Persistence/ScriptsMigration/**
  • Streetcode/Streetcode.DAL/Persistence/ScriptsMigration/Script_20230905201616_Jobs.sql is excluded by !**/ScriptsMigration/**, !**/Streetcode/Streetcode.DAL/Persistence/ScriptsMigration/**
  • Streetcode/Streetcode.DAL/Persistence/ScriptsMigration/Script_20231130202258_DatestringLength.sql is excluded by !**/ScriptsMigration/**, !**/Streetcode/Streetcode.DAL/Persistence/ScriptsMigration/**
  • Streetcode/Streetcode.DAL/Persistence/ScriptsMigration/Script_20240104113247_JobsDescriptionLength.sql is excluded by !**/ScriptsMigration/**, !**/Streetcode/Streetcode.DAL/Persistence/ScriptsMigration/**
  • Streetcode/Streetcode.DAL/Persistence/ScriptsMigration/Script_20240104204923_AddIdentityTables.sql is excluded by !**/ScriptsMigration/**, !**/Streetcode/Streetcode.DAL/Persistence/ScriptsMigration/**
  • Streetcode/Streetcode.DAL/Persistence/ScriptsMigration/Script_20240122161255_ForFansLength.sql is excluded by !**/ScriptsMigration/**, !**/Streetcode/Streetcode.DAL/Persistence/ScriptsMigration/**
  • Streetcode/Streetcode.DAL/Persistence/ScriptsMigration/Script_20240407205620_AddRefreshTokenToUser.sql is excluded by !**/ScriptsMigration/**, !**/Streetcode/Streetcode.DAL/Persistence/ScriptsMigration/**
  • Streetcode/Streetcode.DAL/Persistence/ScriptsMigration/Script_20240417150303_AudioConstraintChange.sql is excluded by !**/ScriptsMigration/**, !**/Streetcode/Streetcode.DAL/Persistence/ScriptsMigration/**
  • Streetcode/Streetcode.DAL/Persistence/ScriptsMigration/Script_20240428073027_FactIndexAdd.sql is excluded by !**/ScriptsMigration/**, !**/Streetcode/Streetcode.DAL/Persistence/ScriptsMigration/**
  • Streetcode/Streetcode.DAL/Persistence/ScriptsMigration/Script_20250118172930_ChangeConstraints.sql is excluded by !**/ScriptsMigration/**, !**/Streetcode/Streetcode.DAL/Persistence/ScriptsMigration/**
  • Streetcode/Streetcode.DAL/Persistence/ScriptsMigration/Script_20250124043754_UserUpdate.sql is excluded by !**/ScriptsMigration/**, !**/Streetcode/Streetcode.DAL/Persistence/ScriptsMigration/**
  • Streetcode/Streetcode.DAL/Persistence/ScriptsMigration/Script_20250204150151_AddFavourites.sql is excluded by !**/ScriptsMigration/**, !**/Streetcode/Streetcode.DAL/Persistence/ScriptsMigration/**
  • Streetcode/Streetcode.DAL/Persistence/ScriptsMigration/StreetcodeAuthor.sql is excluded by !**/ScriptsMigration/**, !**/Streetcode/Streetcode.DAL/Persistence/ScriptsMigration/**
  • Streetcode/Streetcode.DAL/Persistence/ScriptsMigration/UpdateUserNameFieldsLenght.sql is excluded by !**/ScriptsMigration/**, !**/Streetcode/Streetcode.DAL/Persistence/ScriptsMigration/**
  • Streetcode/Streetcode.DAL/Persistence/ScriptsMigration/ZTest.sql is excluded by !**/ScriptsMigration/**, !**/Streetcode/Streetcode.DAL/Persistence/ScriptsMigration/**
📒 Files selected for processing (4)
  • Dockerfile.dbupdate (1 hunks)
  • Jenkinsfile (9 hunks)
  • Streetcode/Streetcode.WebApi/Program.cs (0 hunks)
  • entrypoint.sh (1 hunks)
💤 Files with no reviewable changes (1)
  • Streetcode/Streetcode.WebApi/Program.cs
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Jenkins
🔇 Additional comments (1)
Jenkinsfile (1)

216-224: Verify dbupdate service is included in docker-compose.yml
You stop and prune dbupdate along with other services, but ensure your docker-compose file defines a dbupdate service so it will be restarted on up -d. Otherwise it may be inadvertently omitted.

Comment on lines +30 to +31

CMD ["dotnet", "DbUpdate.dll"] No newline at end of file
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Integrate the entrypoint.sh script into the image
You’ve added a runtime helper script (entrypoint.sh) but the Dockerfile never copies or uses it. Consider adding:

 COPY --from=build /tmp/ScriptsMigration /app/ScriptsMigration/
+COPY entrypoint.sh /app/entrypoint.sh
+RUN chmod +x /app/entrypoint.sh
- CMD ["dotnet", "DbUpdate.dll"]
+ENTRYPOINT ["/app/entrypoint.sh"]

This ensures the diagnostics, env-validation, and logging logic in entrypoint.sh actually runs.

📝 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
CMD ["dotnet", "DbUpdate.dll"]
COPY --from=build /tmp/ScriptsMigration /app/ScriptsMigration/
COPY entrypoint.sh /app/entrypoint.sh
RUN chmod +x /app/entrypoint.sh
ENTRYPOINT ["/app/entrypoint.sh"]

Comment on lines +1 to +2
#!/bin/bash
set -e
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Ensure pipeline fails if dotnet fails
With only set -e, a failing dotnet ... | tee ... won’t trigger exit because the pipeline return code is from tee. Add pipefail:

-#!/bin/bash
-set -e
+#!/bin/bash
+set -euo pipefail

This guarantees any subprocess error aborts the script.

Comment on lines +23 to +24
printenv | grep -i connection || echo " No connection string in environment"
printenv | grep -i sql || 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

Prevent leaking sensitive connection strings
The line printenv | grep -i connection can expose full credentials to logs. Either remove it or mask values:

-printenv | grep -i connection || echo " No connection string in environment"
+printenv | grep -i 'ConnectionStrings__DefaultConnection' | sed -E 's/(=.*)/=***MASKED***/' || echo " No connection string in environment"

This protects PII and secrets.

📝 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
printenv | grep -i connection || echo " No connection string in environment"
printenv | grep -i sql || true
# Protect default connection string by masking its value
printenv | grep -i 'ConnectionStrings__DefaultConnection' | sed -E 's/(=.*)/=***MASKED***/' || echo " No connection string in environment"
printenv | grep -i sql || true

@sonarqubecloud
Copy link

sonarqubecloud bot commented May 9, 2025

Quality Gate Failed Quality Gate failed

Failed conditions
1 Security Hotspot
0.0% Coverage on New Code (required ≥ 80%)
5.4% Duplication on New Code (required ≤ 3%)
E Reliability Rating on New Code (required ≥ A)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE


success {
script {
sendDiscordNotification('SUCCESS', 'Deployment pipeline completed successfully.')
Copy link
Collaborator

Choose a reason for hiding this comment

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

Will this be executed even if the last successfully executed stage is rollback?


}

post {
Copy link
Collaborator

Choose a reason for hiding this comment

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

If I'm not wrong we expected to have Notifications only when we deploy/rollback or do anything else with Stage deployment, that's why I'm not sure about keeping all these notifications here in 'post'
Please verify if this meets original ticket requirements

Copy link
Collaborator

Choose a reason for hiding this comment

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

Is this file still needed?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

this question needs research

VlaadyslavRuban and others added 6 commits May 12, 2025 21:14
deleted "RUN ls -la /tmp/ScriptsMigration"

Co-authored-by: Maxym <[email protected]>
Switched from the 'feature/add-init-container' branch to 'main'
Fix REGEXP pattern for matching release branch names
removed "connection string"
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: 4

♻️ Duplicate comments (1)
Jenkinsfile (1)

144-147: Great job updating the regex for multi-digit versions

The branch pattern now uses \\d+\\.\\d+\\.\\d+, which correctly supports branches like release/10.12.1.

🧹 Nitpick comments (4)
Jenkinsfile (4)

16-17: Remove redundant credential loading or unify usage

DISCORD_WEBHOOK_URL is loaded in the environment block but then re-fetched inside sendDiscordNotification with withCredentials. Likewise, GH_TOKEN isn’t directly referenced elsewhere. To avoid confusion:

  • Remove the environment { DISCORD_WEBHOOK_URL } entry and keep credential loading in your helper.
  • Or use env.DISCORD_WEBHOOK_URL in sendDiscordNotification and drop the extra withCredentials.

153-162: Consider adding --pull to Docker build commands

To ensure you always build from the latest base images (picking up security patches), include --pull:

- sh "docker build -f Dockerfile -t ${env.DOCKER_USERNAME}/streetcode:${env.CODE_VERSION} ."
+ sh "docker build --pull -f Dockerfile -t ${env.DOCKER_USERNAME}/streetcode:${env.CODE_VERSION} ."

- sh "docker build -f Dockerfile.dbupdate -t ${env.DOCKER_USERNAME}/dbupdate:${env.CODE_VERSION} ."
+ sh "docker build --pull -f Dockerfile.dbupdate -t ${env.DOCKER_USERNAME}/dbupdate:${env.CODE_VERSION} ."

281-289: Extract rollback steps into a shared function

The rollback logic in the aborted hook closely mirrors the deploy steps. To reduce duplication and simplify maintenance, extract these into a reusable Groovy function, for example:

def rollbackStage(backendTag, frontendTag) {
  sh "export DOCKER_TAG_BACKEND=${backendTag}"
  sh "export DOCKER_TAG_FRONTEND=${frontendTag}"
  sh 'docker compose --env-file /etc/environment down'
  sh 'docker compose --env-file /etc/environment up -d'
  sendDiscordNotification('ABORTED', 'Deployment was rolled back.')
}

218-242:

Details

❓ Verification inconclusive

Verify state flag persistence & streamline teardown

The when condition relies on Groovy vars IS_IMAGE_PUSH and IS_DBUPDATE_IMAGE_PUSH which may not persist across separate script blocks. Please confirm that these flags reliably guard the Deploy Stage. Additionally, consider replacing the explicit docker stop + prune sequence with Docker Compose’s built-in commands:


🏁 Script executed:

docker compose --env-file /etc/environment down --remove-orphans
docker compose --env-file /etc/environment up -d

Length of output: 311


Validate flag persistence & verify Docker Compose teardown

Please ensure that your IS_IMAGE_PUSH and IS_DBUPDATE_IMAGE_PUSH flags are declared at the pipeline level (e.g., in parameters or the top-level environment block) so they reliably persist into the when expression and across all script blocks. Then, confirm in your Jenkins environment that:

  • The Deploy Stage only executes when both flags are true.
  • Docker Compose is installed on your agent and the following commands cleanly stop and restart your services without errors:
docker compose --env-file /etc/environment down --remove-orphans
docker compose --env-file /etc/environment up -d

Suggested replacement for the explicit prune/stop sequence:

- sh 'docker image prune --force --filter "until=72h"'
- sh 'docker system prune --force --filter "until=72h"'
- sh """
-   docker stop backend frontend nginx loki certbot dbupdate
- """
+ sh '''
+   docker compose --env-file /etc/environment down --remove-orphans
+   docker compose --env-file /etc/environment up -d
+ '''

Please manually verify these compose commands on your build agents to ensure they behave as expected.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 32fdf64 and a3e7696.

⛔ Files ignored due to path filters (1)
  • Streetcode/DbUpdate/Program.cs is excluded by !**/Streetcode/DbUpdate/**
📒 Files selected for processing (1)
  • Jenkinsfile (9 hunks)
🔇 Additional comments (1)
Jenkinsfile (1)

193-206: Pushing both backend and dbupdate images

The extension to push the dbupdate image alongside the backend is clear and well-scoped. Credentials are correctly scoped and used.

Comment on lines +3 to +5
def IS_DBUPDATE_IMAGE_BUILDED = false
def IS_IMAGE_PUSH = false
def IS_DBUPDATE_IMAGE_PUSH = false
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 correct and consistent naming and scoping for build flags

The variables IS_IMAGE_BUILDED and IS_DBUPDATE_IMAGE_BUILDED use non-standard past-tense “BUILD​ED” and are declared as plain Groovy vars, which can lead to scoping issues across script blocks. Consider:

  • Renaming to IS_IMAGE_BUILT and IS_DBUPDATE_IMAGE_BUILT for correct grammar.
  • Promoting these flags into the environment block (e.g., environment { IS_IMAGE_BUILT = 'false' }) or storing state in currentBuild to ensure persistence between stages.

Comment on lines +445 to +467
def sendDiscordNotification(status, message) {
withCredentials([string(credentialsId: 'WEBHOOK_URL', variable: 'DISCORD_WEBHOOK_URL')]) {
def jsonMessage = """
{
"content": "$status: $message",
"embeds": [
{
"title": "Deployment Status",
"fields": [
{"name": "Environment", "value": "Stage", "inline": true},
{"name": "Pipeline Name", "value": "$env.JOB_NAME", "inline": true},
{"name": "Status", "value": "$status", "inline": true},
{"name": "Deployment Tag", "value": "$env.CODE_VERSION", "inline": true},
{"name": "Date and Time", "value": "${new Date().format('yyyy-MM-dd HH:mm:ss')}", "inline": true},
{"name": "Pipeline Link", "value": "[Click here]($env.BUILD_URL)", "inline": true}
]
}
]
}
"""
sh """curl -X POST -H 'Content-Type: application/json' -d '$jsonMessage' "\$DISCORD_WEBHOOK_URL" """
}
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Leverage a Pipeline HTTP step & JSON builder

Building JSON via multiline strings and shelling out with curl can introduce escaping errors and lacks error handling. Using the Jenkins httpRequest step with groovy.json.JsonOutput makes this more robust:

import groovy.json.JsonOutput

def payload = JsonOutput.toJson([
  content: "$status: $message",
  embeds: [ /* ... */ ]
])
httpRequest(
  httpMode: 'POST',
  contentType: 'APPLICATION_JSON',
  requestBody: payload,
  url: DISCORD_WEBHOOK_URL
)

Comment on lines +423 to +436
script {
sendDiscordNotification('SUCCESS', 'Deployment pipeline completed successfully.')
}
}
failure {
script {
sendDiscordNotification('FAILED', 'Deployment pipeline failed.')
}
}
aborted {
script {
sendDiscordNotification('ABORTED', 'Deployment pipeline was aborted.')
}
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Parameterize environment in notifications

The pipeline-level post always sets "Environment": "Stage" in the Discord embed, even for production flows. This hard-coding can lead to misleading alerts. Extend sendDiscordNotification to accept an environment argument or derive it dynamically:

sendDiscordNotification('SUCCESS', 'Pipeline completed', 'Production')

Comment on lines +168 to +186
stage('Trivy Security Scan') {
when {
expression { IS_IMAGE_BUILDED == true && IS_DBUPDATE_IMAGE_BUILDED == true }
}
steps {
script {
def imagesToScan = [
"${env.DOCKER_USERNAME}/streetcode:${env.CODE_VERSION}",
"${env.DOCKER_USERNAME}/dbupdate:${env.CODE_VERSION}"
]
imagesToScan.each { image ->
echo "Running Trivy scan on ${image}"
// Run Trivy scan and display the output in the console log ( || true - don't fail on exit code)
sh """
docker run --rm \
-v /var/run/docker.sock:/var/run/docker.sock \
aquasec/trivy image --no-progress --severity HIGH,CRITICAL --exit-code 1 ${image} || 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

Fail the build on critical vulnerabilities

The Trivy scan appends || true, which masks exit codes so the pipeline never fails even if HIGH/CRITICAL issues are found. To align with your security policy, remove || true or explicitly check the exit code and fail when non-zero:

- aquasec/trivy image --no-progress --severity HIGH,CRITICAL --exit-code 1 ${image} || true
+ aquasec/trivy image --no-progress --severity HIGH,CRITICAL --exit-code 1 ${image}
📝 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
stage('Trivy Security Scan') {
when {
expression { IS_IMAGE_BUILDED == true && IS_DBUPDATE_IMAGE_BUILDED == true }
}
steps {
script {
def imagesToScan = [
"${env.DOCKER_USERNAME}/streetcode:${env.CODE_VERSION}",
"${env.DOCKER_USERNAME}/dbupdate:${env.CODE_VERSION}"
]
imagesToScan.each { image ->
echo "Running Trivy scan on ${image}"
// Run Trivy scan and display the output in the console log ( || true - don't fail on exit code)
sh """
docker run --rm \
-v /var/run/docker.sock:/var/run/docker.sock \
aquasec/trivy image --no-progress --severity HIGH,CRITICAL --exit-code 1 ${image} || true
"""
}
stage('Trivy Security Scan') {
when {
expression { IS_IMAGE_BUILDED == true && IS_DBUPDATE_IMAGE_BUILDED == true }
}
steps {
script {
def imagesToScan = [
"${env.DOCKER_USERNAME}/streetcode:${env.CODE_VERSION}",
"${env.DOCKER_USERNAME}/dbupdate:${env.CODE_VERSION}"
]
imagesToScan.each { image ->
echo "Running Trivy scan on ${image}"
// Run Trivy scan and display the output in the console log (fail pipeline on exit code)
sh """
docker run --rm \
-v /var/run/docker.sock:/var/run/docker.sock \
aquasec/trivy image --no-progress --severity HIGH,CRITICAL --exit-code 1 ${image}
"""
}

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 (1)
Jenkinsfile (1)

144-147: Enhance release branch regex
The regex release/\\d+\\.\\d+\\.\\d+ now supports multi-digit version segments, aligning with prior feedback. This change is correct and improves version matching.

🧹 Nitpick comments (7)
Jenkinsfile (7)

3-5: Initialize dbupdate image tracking flags
You've added IS_DBUPDATE_IMAGE_BUILDED and IS_DBUPDATE_IMAGE_PUSH to track the dbupdate image lifecycle. Consider using consistent naming (e.g., IS_DBUPDATE_IMAGE_BUILT) and leveraging Jenkins env. scope for clarity.


16-17: Simplify credential injection
You load DISCORD_WEBHOOK_URL in environment and again inside sendDiscordNotification. You can remove the inner withCredentials and reference the env var directly. Also, GH_TOKEN is injected but unused—remove it or wire it into a GitHub step.


154-161: Build backend and dbupdate images together
Grouping the two Docker builds under shared credentials is effective. To improve:

  • Log each build’s exit code or output for easier debugging.
  • Confirm Dockerfile.dbupdate context includes all required files.

193-195: Gate image push on build success
The push stage checks both build flags correctly. Minor nit: rename IS_IMAGE_BUILDED to IS_IMAGE_BUILT for grammatical consistency.


200-201: Use Jenkins Docker credential binding
Instead of piping echo $password | docker login, consider docker.withRegistry or the Jenkins Docker plugin’s credential binding for cleaner credential handling.


249-250: Parameterize Stage notification
Integrating Discord notifications is excellent for visibility. To avoid hard-coding, parameterize the environment name (e.g., ${env.DEPLOY_ENV}) instead of "Stage" in the embed.


262-262: Clarify stage title
WHAT IS THE NEXT STEP is ambiguous. Rename to something like Approve Production Deployment to improve readability and align with pipeline conventions.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 32fdf64 and a3e7696.

⛔ Files ignored due to path filters (1)
  • Streetcode/DbUpdate/Program.cs is excluded by !**/Streetcode/DbUpdate/**
📒 Files selected for processing (1)
  • Jenkinsfile (9 hunks)
🔇 Additional comments (3)
Jenkinsfile (3)

174-178: Optimize image list for scanning
Defining imagesToScan as a list makes it straightforward to extend if more images are added. This is a clean, scalable approach.


205-207: Track dbupdate image push
Setting IS_DBUPDATE_IMAGE_PUSH after pushing ensures downstream stages only run when both images are available. This is implemented correctly.


218-219: Enforce both images before deployment
Using both push flags to guard the Deploy Stage ensures consistency across services. This conditional check is well-placed.

Comment on lines +168 to +170
stage('Trivy Security Scan') {
when {
expression { IS_IMAGE_BUILDED == true && IS_DBUPDATE_IMAGE_BUILDED == true }
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Condition Trivy scan on both images
You guard the security scan with both build flags. To enforce security best practices, consider failing the pipeline on HIGH/CRITICAL findings (i.e., remove || true) or aggregate scan reports for review.

Comment on lines +181 to +185
sh """
docker run --rm \
-v /var/run/docker.sock:/var/run/docker.sock \
aquasec/trivy image --no-progress --severity HIGH,CRITICAL --exit-code 1 ${image} || true
"""
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Strengthen vulnerability scan error handling
Masking failures with || true hides critical issues. Consider:

  • Removing || true so the stage fails on severity breaches.
  • Archiving Trivy JSON output as an artifact.

Comment on lines +445 to +467
def sendDiscordNotification(status, message) {
withCredentials([string(credentialsId: 'WEBHOOK_URL', variable: 'DISCORD_WEBHOOK_URL')]) {
def jsonMessage = """
{
"content": "$status: $message",
"embeds": [
{
"title": "Deployment Status",
"fields": [
{"name": "Environment", "value": "Stage", "inline": true},
{"name": "Pipeline Name", "value": "$env.JOB_NAME", "inline": true},
{"name": "Status", "value": "$status", "inline": true},
{"name": "Deployment Tag", "value": "$env.CODE_VERSION", "inline": true},
{"name": "Date and Time", "value": "${new Date().format('yyyy-MM-dd HH:mm:ss')}", "inline": true},
{"name": "Pipeline Link", "value": "[Click here]($env.BUILD_URL)", "inline": true}
]
}
]
}
"""
sh """curl -X POST -H 'Content-Type: application/json' -d '$jsonMessage' "\$DISCORD_WEBHOOK_URL" """
}
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Consolidate Discord notification logic
The sendDiscordNotification function is comprehensive, but you reload DISCORD_WEBHOOK_URL inside it despite already injecting it in environment. Consolidate credential handling to one location and ensure the triple‐quoted JSON payload handles quoting correctly (or switch to single‐quote style).

updated the Discord notifications logic to execute only when the status update about the deployment on the STG environment is available
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 (2)
Jenkinsfile (2)

3-5: 🛠️ Refactor suggestion

Inconsistent variable naming and scoping for build/push flags
The new flags IS_DBUPDATE_IMAGE_BUILDED and IS_DBUPDATE_IMAGE_PUSH follow the same grammar issue (“BUILDED”) as IS_IMAGE_BUILDED. Also, declaring these as top-level Groovy vars may lead to scoping issues across script blocks. Consider renaming to IS_DBUPDATE_IMAGE_BUILT / IS_IMAGE_BUILT / IS_IMAGE_PUSHED, etc., and moving flag state into the environment block or leveraging currentBuild properties for persistence.


168-185: ⚠️ Potential issue

Fail build on critical vulnerabilities
The || true at the end of the Trivy command masks exit codes so HIGH/CRITICAL findings won’t fail the pipeline. To align with your security policy, remove || true or explicitly handle the exit code to fail on vulnerability detection.

     sh """
         docker run --rm \
         -v /var/run/docker.sock:/var/run/docker.sock \
-        aquasec/trivy image --no-progress --severity HIGH,CRITICAL --exit-code 1 ${image} || true
+        aquasec/trivy image --no-progress --severity HIGH,CRITICAL --exit-code 1 ${image}
     """
🧹 Nitpick comments (3)
Jenkinsfile (3)

16-17: Consolidate credential usage for Discord webhook
You bind DISCORD_WEBHOOK_URL at the pipeline level and again inside sendDiscordNotification. To avoid duplication, either remove the outer credential injection and rely on the inner withCredentials, or drop the inner binding and reference env.DISCORD_WEBHOOK_URL directly.


256-259: Remove outdated commented code
The commented-out sendDiscordNotification invocation is no longer needed and clutters the stage. Deleting these lines will improve readability.


460-482: Parameterize environment and improve error handling in notifications

  • The "Environment": "Stage" field is hard-coded; accept an environment parameter to support multiple targets.
  • You can simplify credential management by using the pipeline’s DISCORD_WEBHOOK_URL directly, removing the nested withCredentials.
  • Rather than shelling out with curl, leverage the Jenkins httpRequest step and groovy.json.JsonOutput for safer JSON construction and built-in error handling.
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a3e7696 and 7f0b365.

📒 Files selected for processing (1)
  • Jenkinsfile (8 hunks)
🔇 Additional comments (7)
Jenkinsfile (7)

144-149: Correct branch regex for multi-digit versions
Great use of \\d+\\.\\d+\\.\\d+ to allow multi-digit release branches (e.g., release/10.12.1). This fully addresses earlier feedback.


153-162: Build both images securely and tag with version
The withCredentials scope for Docker registry credentials and env.DOCKER_USERNAME usage are spot-on. Building the backend and dbupdate images side-by-side with consistent tagging is implemented correctly.


195-206: Push both images only when built successfully
The when guard correctly ensures both images are built before pushing, and pushing the dbupdate image along with setting IS_DBUPDATE_IMAGE_PUSH is consistent with the build stage.


218-219: Deploy only after both images are pushed
Using IS_IMAGE_PUSH and IS_DBUPDATE_IMAGE_PUSH in the when block properly gates the Deploy Stage. This alignment between push flags and deployment is correct.


242-242: Include dbupdate in container stop command
Adding dbupdate ensures the old database-update container is stopped before bringing up the new stack. This is necessary and correctly applied.


271-273: Consistent gating for the next-step stage
Reusing the same when expression for WHAT IS THE NEXT STEP ensures the production choice prompt only appears after both images are pushed. This consistency is well-implemented.


293-301: Avoid input in post on aborted
Calling input inside a post { aborted { … } } block may not execute as expected since the pipeline is already in an aborted state. Consider capturing the rollback decision earlier or using a separate rollback stage.

Comment on lines +305 to +309
failure {
script {
sendDiscordNotification('FAILED', 'Unexpected failure in "WHAT IS THE NEXT STEP" stage.')
}
}
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 post for failure notifications
Similarly, it’s more robust to declare a stage-level post { failure { … } } section for unexpected failures rather than embedding it in a script block.

Comment on lines +249 to +255
if (currentBuild.result == 'SUCCESS') {
sendDiscordNotification('SUCCESS', 'Deployment to Stage completed successfully.')
} else if (currentBuild.result == 'ABORTED') {
sendDiscordNotification('ABORTED', 'Deployment to Stage was aborted.')
} else if (currentBuild.result == 'FAILURE') {
sendDiscordNotification('FAILED', 'Deployment to Stage failed.')
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Move status notifications to post
Embedding notifications inside the script block based on currentBuild.result can be unreliable on failure or abort. It’s clearer to define a stage-level post { success { … } failure { … } aborted { … } } block for notifications.

Resolved an issue where the pipeline failed at dotnet tool update due to dotnet-coverage version 17.13.1 already being installed
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 (2)
Jenkinsfile (2)

153-160: Branch pattern correctly supports multi-digit versions
The regex release/\\d+\\.\\d+\\.\\d+ now properly handles version segments like 10.12.1. 🎉


190-195: ⚠️ Potential issue

Prevent masking of critical vulnerabilities in Trivy scan
By appending || true, the pipeline will never fail on HIGH/CRITICAL findings, potentially overlooking release-blocking issues. To enforce policy, remove the || true or explicitly check the exit code:

- aquasec/trivy image --no-progress --severity HIGH,CRITICAL --exit-code 1 ${image} || true
+ aquasec/trivy image --no-progress --severity HIGH,CRITICAL --exit-code 1 ${image}
🧹 Nitpick comments (9)
Jenkinsfile (9)

16-18: Remove redundant credential lookup for Discord webhook
You load DISCORD_WEBHOOK_URL via credentials('WEBHOOK_URL') in the environment block, yet sendDiscordNotification also calls withCredentials. You can remove the inner lookup and reference env.DISCORD_WEBHOOK_URL to simplify and avoid duplicate credential fetches.


52-60: Consolidate dotnet-coverage installation logic
Instead of manually checking if dotnet-coverage is installed, use the update command which installs if missing or updates when present:

- def coverageInstalled = sh(... | grep dotnet-coverage) == 0
- if (!coverageInstalled) {
-   sh 'dotnet tool install --global dotnet-coverage --version 17.13.1'
- } else {
-   echo 'dotnet-coverage is already installed.'
- }
+ sh 'dotnet tool update --global dotnet-coverage --version 17.13.1'

This reduces branching and ensures idempotency.


162-171: Extract image build steps into a reusable function
The build logic for streetcode and dbupdate images is nearly identical. Consider creating a helper method to DRY this up:

def buildImage(name, dockerfile) {
  sh "docker build -f ${dockerfile} -t ${username}/${name}:${env.CODE_VERSION} ."
}

script {
  withCredentials([...]) {
    IS_IMAGE_BUILT = buildImage('streetcode', 'Dockerfile')
    IS_DBUPDATE_IMAGE_BUILT = buildImage('dbupdate', 'Dockerfile.dbupdate')
  }
}

258-264: Move notifications to stage-level post blocks
Embedding Discord notifications inside the script block depends on currentBuild.result and may not fire reliably. Consider using:

stage('Deploy Stage') {
  ...
  post {
    success { sendDiscordNotification('SUCCESS', 'Deployment to Stage completed successfully.') }
    failure { sendDiscordNotification('FAILED',  'Deployment to Stage failed.') }
    aborted { sendDiscordNotification('ABORTED','Deployment to Stage was aborted.') }
  }
}

This guarantees execution.


279-284: Rename stage for clarity
The title WHAT IS THE NEXT STEP is non-standard. Rename it to something like Next Actions or Promotion Choice to improve readability and make its purpose evident.


291-309: Streamline rollback logic in aborted post
The rollback steps duplicate cleanup commands from the deploy stage. Extract common logic into a function or post block to reduce duplication and improve maintainability.


314-318: Ensure failure notifications are always sent
Place sendDiscordNotification('FAILED', …) inside a post { failure { … } } block rather than a manual script conditional to ensure it triggers on any stage error.


445-460: Remove or re-enable commented global notifications
The post { success/failure/aborted } section is commented out, disabling pipeline-wide alerts. Either restore these notifications using sendDiscordNotification or delete the dead code to keep the Jenkinsfile clean.


469-491: Refactor sendDiscordNotification to use Jenkins httpRequest
Using curl in a shell step lacks error handling. Replace with the Jenkins HTTP request step and groovy.json.JsonOutput for robust payload creation and automatic failure on non-2xx responses:

import groovy.json.JsonOutput

def sendDiscordNotification(String status, String message) {
  def payload = JsonOutput.toJson([
    content: "$status: $message",
    embeds: [...]
  ])
  httpRequest(
    httpMode: 'POST',
    contentType: 'APPLICATION_JSON',
    requestBody: payload,
    url: env.DISCORD_WEBHOOK_URL
  )
}
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7f0b365 and b53106a.

📒 Files selected for processing (1)
  • Jenkinsfile (9 hunks)
🔇 Additional comments (4)
Jenkinsfile (4)

177-181: Validate both images are built before Scanning
The when condition correctly gates the Trivy scan, preventing null or missing images. Nice catch!


203-205: Push stage gating logic is correct
The push step only runs after both images are built. No changes needed here.


227-231: Expression gating is consistent for multi-image deployment
The when condition correctly checks both push flags before prompting for staging approval.


249-252: Include dbupdate container in cleanup commands
Adding dbupdate to docker stop ensures the new service is redeployed correctly.

Comment on lines 1 to +5
def CODE_VERSION = ''
def IS_IMAGE_BUILDED = false
def IS_DBUPDATE_IMAGE_BUILDED = false
def IS_IMAGE_PUSH = false
def IS_DBUPDATE_IMAGE_PUSH = false
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 boolean flags and version declarations into environment scope
It's recommended to promote pipeline-wide flags (IS_IMAGE_BUILDED, IS_DBUPDATE_IMAGE_BUILDED, IS_IMAGE_PUSH, IS_DBUPDATE_IMAGE_PUSH, CODE_VERSION) into the environment {} block and rename them for correct grammar (e.g., IS_IMAGE_BUILT). This ensures they persist across stages and reduces scoping issues in script blocks.

Comment on lines 209 to +216
sh 'echo "${password}" | docker login -u "${username}" --password-stdin'
sh "docker push ${username}/streetcode:latest"
sh "docker tag ${username}/streetcode:latest ${username}/streetcode:${env.CODE_VERSION}"

sh "docker push ${username}/streetcode:${env.CODE_VERSION}"
IS_IMAGE_PUSH = true


sh "docker push ${username}/dbupdate:${env.CODE_VERSION}"
IS_DBUPDATE_IMAGE_PUSH = 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

Fix shell quoting for Docker login and push
Using single quotes prevents Groovy from expanding ${password} and ${username}. Switch to double-quoted Groovy strings so variables interpolate properly:

- sh 'echo "${password}" | docker login -u "${username}" --password-stdin'
+ sh "echo \"${password}\" | docker login -u \"${username}\" --password-stdin"

Ensure docker push commands also interpolate correctly.

📝 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
sh 'echo "${password}" | docker login -u "${username}" --password-stdin'
sh "docker push ${username}/streetcode:latest"
sh "docker tag ${username}/streetcode:latest ${username}/streetcode:${env.CODE_VERSION}"
sh "docker push ${username}/streetcode:${env.CODE_VERSION}"
IS_IMAGE_PUSH = true
sh "docker push ${username}/dbupdate:${env.CODE_VERSION}"
IS_DBUPDATE_IMAGE_PUSH = true
sh "echo \"${password}\" | docker login -u \"${username}\" --password-stdin"
sh "docker push ${username}/streetcode:${env.CODE_VERSION}"
IS_IMAGE_PUSH = true
sh "docker push ${username}/dbupdate:${env.CODE_VERSION}"
IS_DBUPDATE_IMAGE_PUSH = true

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.

8 participants