Skip to content

Commit 9549cc2

Browse files
Ash-expnishantashishdevtronbadal773Badal Kumar Prusty
authored
chore: code refactoring v2 (#4572)
* stage 1 * fix: Image-Scanner status for failed request (#4513) * retry envs added * json naming * migration for image scan plugin and retry env fix * fix * image scan migration script updated - added new input variables * migration updated * migration updated * name changed * refactor * added default value and change script no * chore: added sql-validator in git-hub action (#4255) * added sql-validator in git-hub action * removed exit commands * edited the grep with whole word * modified * modified comments --------- Co-authored-by: Badal Kumar Prusty <[email protected]> * feat: Adds Copacetic plugin to patch vulnerable images (#4566) * Adds copacetic plugin * copacetic plugin: adds plugin icon and updates url in migration file * Update 211_copacetic_plugin_v1_0_0.up.sql adds copa patch command exit condition * Update 211_copacetic_plugin_v1_0_0.up.sql adds exit 1 if patching multi architecture image * dummy commit 211_copacetic_plugin_v1_0_0.up.sql dummy commit * chore: added sql-validator in git-hub action (#4255) * added sql-validator in git-hub action * removed exit commands * edited the grep with whole word * modified * modified comments --------- Co-authored-by: Badal Kumar Prusty <[email protected]> * updates migration no. --------- Co-authored-by: Badal Kumar <[email protected]> Co-authored-by: Badal Kumar Prusty <[email protected]> * feat: Create Dockerslim plugin and Create EKS Cluster plugin (#4525) * Plugins icon * eks and dockerslim plugin sql up * eks and dockerslim plugin down script * dockerslim plugin after review PR * Changes after review dockerslim * image changes * new image dockerslim * eks creation plugin * Final PR commit, eks and dockerslim plugins * feat: making pre,post,deploy triggers flows idempotent (#4486) * update common-lib * added idempotency code and common-lib version bump * added the optionsal validations pubsub msg pre-processing-hooks logic and added duplicate trigger check as a validation for pre,post,deploy trigger flows * bump common-lib * added callback logger func * sql scripts added * query fix * query fix * fix * refactoring * remove dag exececutor dependency from ciEeventHalndler Sevice * bump common-lib * move context to trigger context * add logs * migration version fix * remove test data * update script number --------- Co-authored-by: Kripansh <[email protected]> * chore: panic middleware and proxy handler (#4546) * initial commit * removed from hyperion * changes * added trace * pr comments * pg timeouts * panic message constant * cleaning up * common lib version * argo assets revert * adding image scanner proxy route * common-lib-update * refactoring: App Store deployment services * fix: sql script added for putting Identifier type=0 for all null values present in generic_note (#4568) * script for initializing null identifier type col to 0(cluster type) * script fix * empty script for 216 * 216 up script revert * fix: 500 fixes second iteration (#4464) * FetchChartNotes return 4xx when installed app or installed app versions not found * GetDeploymentHistory and GetInstalledAppVersion to return 4xx when installed app or installed app versions not found * fixes * adding pg:",discard_unknown_columns" in tables where doesn't exist * fix for Git Sensor response * fix for inception * fix for k8s resource delete * fix for pipeline already exists * fix for pipeline already exists * fix * fix * fix * fix * go mod version changes * merged * common lib main version sync * main merge --------- Co-authored-by: ShashwatDadhich <[email protected]> * feat: added posthog events for cloud provider and version (#4443) * added cloud provider event * added logger for testing * logger removed * common-lib version upgraded * introduced CASBIN_DATABASE env (#4547) * added --reuse-values in troubleshoot (#4577) Co-authored-by: Badal Kumar Prusty <[email protected]> --------- Co-authored-by: nishant <[email protected]> Co-authored-by: ashishdevtron <[email protected]> Co-authored-by: Badal Kumar <[email protected]> Co-authored-by: Badal Kumar Prusty <[email protected]> Co-authored-by: tayalrishabh96 <[email protected]> Co-authored-by: Rupin Solanki <[email protected]> Co-authored-by: Gireesh Naidu <[email protected]> Co-authored-by: Kripansh <[email protected]> Co-authored-by: subhashish-devtron <[email protected]> Co-authored-by: Prakash <[email protected]> Co-authored-by: ShashwatDadhich <[email protected]>
1 parent bb29cbc commit 9549cc2

File tree

151 files changed

+3824
-2211
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

151 files changed

+3824
-2211
lines changed

.github/workflows/pr-issue-validator.yaml

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ jobs:
2929
steps:
3030
- name: Checkout repository
3131
uses: actions/checkout@v2
32+
with:
33+
ref: ${{ github.event.pull_request.head.sha }}
34+
fetch-depth: 0
35+
3236

3337
- name: Validate Issue Reference
3438
env:
@@ -150,3 +154,84 @@ jobs:
150154
gh pr edit $PRNUM --remove-label "PR:Ready-to-Review"
151155
exit 1
152156
fi
157+
- name: Check SQL file format and duplicates
158+
shell: bash
159+
env:
160+
pr_no: ${{ github.event.pull_request.number }}
161+
GH_TOKEN: ${{ github.token }}
162+
run: |
163+
164+
# Fetch the latest changes from the main branch
165+
git fetch origin main
166+
167+
# Get the list of changed files
168+
git diff origin/main...HEAD --name-only > diff
169+
170+
echo "Changed files:"
171+
cat diff
172+
173+
echo "Changed SQL files-:"
174+
# Filter SQL files from the list of changed files
175+
awk '/scripts\/sql\//' diff
176+
177+
# Count the number of changed SQL files in the 'scripts/sql' directory
178+
count=$(awk '/scripts\/sql\//' diff | wc -l)
179+
180+
# Check if no SQL files were changed
181+
if [[ $count == "0" ]]; then
182+
echo "No SQL files were added, Exiting from this action."
183+
exit 0
184+
fi
185+
186+
# Iterate through each changed SQL file
187+
for filename in $(awk '/scripts\/sql\//' diff); do
188+
echo "Checking File: $filename"
189+
190+
# Check if the SQL file name is in the correct format (i.e., it ends with either '.up.sql' or '.down.sql')
191+
if [[ "$filename" =~ \.(up|down)\.sql$ ]]; then
192+
193+
# Print a message that the file name is in the correct format
194+
echo "File name: $filename is in the correct format"
195+
else
196+
# Print an error message
197+
echo "Error: The SQL file name is not in the correct format: $filename."
198+
199+
# Post a comment on a GitHub pull request with the error message
200+
gh pr comment $pr_no --body "The SQL file name: $filename is not in the correct format."
201+
202+
# Exit the script with a non-zero status code
203+
exit 1
204+
fi
205+
206+
# Navigate to the SQL files directory
207+
sql_dir="scripts/sql"
208+
echo "Current directory: $(pwd)"
209+
cd "$sql_dir"
210+
echo "SQL files directory: $(pwd)"
211+
212+
# Extract the migration number from the SQL file name
213+
migration_no=$(echo "$filename" | cut -d "/" -f 3 | cut -d "_" -f 1)
214+
echo "Migration Number: $migration_no"
215+
216+
# Count the number of files with the same migration number
217+
migration_files_present_of_this_no=$(ls | cut -d "_" -f 1 | grep -w -c "$migration_no")
218+
219+
# Navigate back to the original directory
220+
cd ../..
221+
222+
# Check the conditions based on the number of files with the same migration number
223+
if [[ $migration_files_present_of_this_no == "2" ]]; then
224+
echo "All looks good for this migration number."
225+
elif [[ $migration_files_present_of_this_no == "1" ]]; then
226+
# Only one file is present for this migration number
227+
echo "Only single migration file was present for migration no.: $migration_no. either up or down migration is missing! EXITING"
228+
gh pr comment $pr_no --body "Error: Only a single migration file was present for this number: $migration_no."
229+
exit 1
230+
else
231+
# Migration number is repeated
232+
echo "Error: Migration number is repeated."
233+
gh pr comment $pr_no --body "Error: The SQL file number: $migration_no is duplicated"
234+
exit 1
235+
fi
236+
done
237+

App.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"context"
2222
"crypto/tls"
2323
"fmt"
24+
"github.com/devtron-labs/common-lib/middlewares"
2425
"log"
2526
"net/http"
2627
"os"
@@ -101,6 +102,8 @@ func (app *App) Start() {
101102
server := &http.Server{Addr: fmt.Sprintf(":%d", port), Handler: authMiddleware.Authorizer(app.sessionManager2, user.WhitelistChecker)(app.MuxRouter.Router)}
102103
app.MuxRouter.Router.Use(app.loggingMiddleware.LoggingMiddleware)
103104
app.MuxRouter.Router.Use(middleware.PrometheusMiddleware)
105+
app.MuxRouter.Router.Use(middlewares.Recovery)
106+
104107
if tracerProvider != nil {
105108
app.MuxRouter.Router.Use(otelmux.Middleware(otel.OTEL_ORCHESTRASTOR_SERVICE_NAME))
106109
}

Wire.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ package main
2222

2323
import (
2424
"github.com/devtron-labs/authenticator/middleware"
25+
cloudProviderIdentifier "github.com/devtron-labs/common-lib/cloud-provider-identifier"
2526
pubsub1 "github.com/devtron-labs/common-lib/pubsub-lib"
2627
util4 "github.com/devtron-labs/common-lib/utils/k8s"
2728
"github.com/devtron-labs/devtron/api/apiToken"
@@ -65,6 +66,7 @@ import (
6566
"github.com/devtron-labs/devtron/client/gitSensor"
6667
"github.com/devtron-labs/devtron/client/grafana"
6768
"github.com/devtron-labs/devtron/client/lens"
69+
"github.com/devtron-labs/devtron/client/proxy"
6870
"github.com/devtron-labs/devtron/client/telemetry"
6971
"github.com/devtron-labs/devtron/internal/sql/repository"
7072
app2 "github.com/devtron-labs/devtron/internal/sql/repository/app"
@@ -87,7 +89,6 @@ import (
8789
"github.com/devtron-labs/devtron/pkg/appStatus"
8890
"github.com/devtron-labs/devtron/pkg/appStore/chartGroup"
8991
repository4 "github.com/devtron-labs/devtron/pkg/appStore/chartGroup/repository"
90-
appStoreDeploymentFullMode "github.com/devtron-labs/devtron/pkg/appStore/deployment/fullMode"
9192
"github.com/devtron-labs/devtron/pkg/appStore/deployment/service"
9293
appStoreDeploymentGitopsTool "github.com/devtron-labs/devtron/pkg/appStore/deployment/tool"
9394
"github.com/devtron-labs/devtron/pkg/appWorkflow"
@@ -144,6 +145,7 @@ func InitializeApp() (*App, error) {
144145
sso.SsoConfigWireSet,
145146
cluster.ClusterWireSet,
146147
dashboard.DashboardWireSet,
148+
proxy.ProxyWireSet,
147149
client.HelmAppWireSet,
148150
k8s.K8sApplicationWireSet,
149151
chartRepo.ChartRepositoryWireSet,
@@ -663,6 +665,9 @@ func InitializeApp() (*App, error) {
663665
wire.Bind(new(restHandler.TelemetryRestHandler), new(*restHandler.TelemetryRestHandlerImpl)),
664666
telemetry.NewPosthogClient,
665667

668+
cloudProviderIdentifier.NewProviderIdentifierServiceImpl,
669+
wire.Bind(new(cloudProviderIdentifier.ProviderIdentifierService), new(*cloudProviderIdentifier.ProviderIdentifierServiceImpl)),
670+
666671
telemetry.NewTelemetryEventClientImplExtended,
667672
wire.Bind(new(telemetry.TelemetryEventClient), new(*telemetry.TelemetryEventClientImplExtended)),
668673

@@ -713,8 +718,6 @@ func InitializeApp() (*App, error) {
713718
delete2.NewDeleteServiceFullModeImpl,
714719
wire.Bind(new(delete2.DeleteServiceFullMode), new(*delete2.DeleteServiceFullModeImpl)),
715720

716-
appStoreDeploymentFullMode.NewAppStoreDeploymentFullModeServiceImpl,
717-
wire.Bind(new(appStoreDeploymentFullMode.AppStoreDeploymentFullModeService), new(*appStoreDeploymentFullMode.AppStoreDeploymentFullModeServiceImpl)),
718721
appStoreDeploymentGitopsTool.NewAppStoreDeploymentArgoCdServiceImpl,
719722
wire.Bind(new(appStoreDeploymentGitopsTool.AppStoreDeploymentArgoCdService), new(*appStoreDeploymentGitopsTool.AppStoreDeploymentArgoCdServiceImpl)),
720723
// util2.NewGoJsonSchemaCustomFormatChecker,

api/appStore/InstalledAppRestHandler.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,13 @@ import (
2222
"encoding/json"
2323
"errors"
2424
"fmt"
25+
client "github.com/devtron-labs/devtron/api/helm-app/gRPC"
2526
"net/http"
2627
"strconv"
2728
"strings"
2829
"time"
2930

3031
bean2 "github.com/devtron-labs/devtron/api/bean"
31-
client "github.com/devtron-labs/devtron/api/helm-app"
3232
openapi "github.com/devtron-labs/devtron/api/helm-app/openapiClient"
3333
"github.com/devtron-labs/devtron/api/restHandler/common"
3434
"github.com/devtron-labs/devtron/client/argocdServer/application"

api/appStore/deployment/AppStoreDeploymentRestHandler.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"encoding/json"
2323
"errors"
2424
"fmt"
25+
service2 "github.com/devtron-labs/devtron/api/helm-app/service"
2526
"net/http"
2627
"strconv"
2728
"strings"
@@ -67,15 +68,15 @@ type AppStoreDeploymentRestHandlerImpl struct {
6768
appStoreDeploymentService service.AppStoreDeploymentService
6869
appStoreDeploymentServiceC appStoreDeploymentCommon.AppStoreDeploymentCommonService
6970
validator *validator.Validate
70-
helmAppService client.HelmAppService
71+
helmAppService service2.HelmAppService
7172
helmAppRestHandler client.HelmAppRestHandler
7273
argoUserService argo.ArgoUserService
7374
attributesService attributes.AttributesService
7475
}
7576

7677
func NewAppStoreDeploymentRestHandlerImpl(Logger *zap.SugaredLogger, userAuthService user.UserService,
7778
enforcer casbin.Enforcer, enforcerUtil rbac.EnforcerUtil, enforcerUtilHelm rbac.EnforcerUtilHelm, appStoreDeploymentService service.AppStoreDeploymentService,
78-
validator *validator.Validate, helmAppService client.HelmAppService, appStoreDeploymentServiceC appStoreDeploymentCommon.AppStoreDeploymentCommonService,
79+
validator *validator.Validate, helmAppService service2.HelmAppService, appStoreDeploymentServiceC appStoreDeploymentCommon.AppStoreDeploymentCommonService,
7980
argoUserService argo.ArgoUserService, attributesService attributes.AttributesService) *AppStoreDeploymentRestHandlerImpl {
8081
return &AppStoreDeploymentRestHandlerImpl{
8182
Logger: Logger,

api/appStore/deployment/CommonDeploymentRestHandler.go

Lines changed: 26 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"context"
2222
"encoding/json"
2323
"fmt"
24+
service2 "github.com/devtron-labs/devtron/api/helm-app/service"
2425
"net/http"
2526
"strconv"
2627
"time"
@@ -31,7 +32,6 @@ import (
3132
"github.com/devtron-labs/devtron/api/restHandler/common"
3233
"github.com/devtron-labs/devtron/internal/util"
3334
appStoreBean "github.com/devtron-labs/devtron/pkg/appStore/bean"
34-
appStoreDeploymentCommon "github.com/devtron-labs/devtron/pkg/appStore/deployment/common"
3535
"github.com/devtron-labs/devtron/pkg/appStore/deployment/service"
3636
"github.com/devtron-labs/devtron/pkg/auth/authorisation/casbin"
3737
"github.com/devtron-labs/devtron/pkg/auth/user"
@@ -51,35 +51,33 @@ type CommonDeploymentRestHandler interface {
5151
}
5252

5353
type CommonDeploymentRestHandlerImpl struct {
54-
Logger *zap.SugaredLogger
55-
userAuthService user.UserService
56-
enforcer casbin.Enforcer
57-
enforcerUtil rbac.EnforcerUtil
58-
enforcerUtilHelm rbac.EnforcerUtilHelm
59-
appStoreDeploymentService service.AppStoreDeploymentService
60-
appStoreDeploymentServiceC appStoreDeploymentCommon.AppStoreDeploymentCommonService
61-
validator *validator.Validate
62-
helmAppService client.HelmAppService
63-
helmAppRestHandler client.HelmAppRestHandler
64-
argoUserService argo.ArgoUserService
54+
Logger *zap.SugaredLogger
55+
userAuthService user.UserService
56+
enforcer casbin.Enforcer
57+
enforcerUtil rbac.EnforcerUtil
58+
enforcerUtilHelm rbac.EnforcerUtilHelm
59+
appStoreDeploymentService service.AppStoreDeploymentService
60+
validator *validator.Validate
61+
helmAppService service2.HelmAppService
62+
helmAppRestHandler client.HelmAppRestHandler
63+
argoUserService argo.ArgoUserService
6564
}
6665

6766
func NewCommonDeploymentRestHandlerImpl(Logger *zap.SugaredLogger, userAuthService user.UserService,
6867
enforcer casbin.Enforcer, enforcerUtil rbac.EnforcerUtil, enforcerUtilHelm rbac.EnforcerUtilHelm, appStoreDeploymentService service.AppStoreDeploymentService,
69-
validator *validator.Validate, helmAppService client.HelmAppService, appStoreDeploymentServiceC appStoreDeploymentCommon.AppStoreDeploymentCommonService,
68+
validator *validator.Validate, helmAppService service2.HelmAppService,
7069
helmAppRestHandler client.HelmAppRestHandler, argoUserService argo.ArgoUserService) *CommonDeploymentRestHandlerImpl {
7170
return &CommonDeploymentRestHandlerImpl{
72-
Logger: Logger,
73-
userAuthService: userAuthService,
74-
enforcer: enforcer,
75-
enforcerUtil: enforcerUtil,
76-
enforcerUtilHelm: enforcerUtilHelm,
77-
appStoreDeploymentService: appStoreDeploymentService,
78-
validator: validator,
79-
helmAppService: helmAppService,
80-
appStoreDeploymentServiceC: appStoreDeploymentServiceC,
81-
helmAppRestHandler: helmAppRestHandler,
82-
argoUserService: argoUserService,
71+
Logger: Logger,
72+
userAuthService: userAuthService,
73+
enforcer: enforcer,
74+
enforcerUtil: enforcerUtil,
75+
enforcerUtilHelm: enforcerUtilHelm,
76+
appStoreDeploymentService: appStoreDeploymentService,
77+
validator: validator,
78+
helmAppService: helmAppService,
79+
helmAppRestHandler: helmAppRestHandler,
80+
argoUserService: argoUserService,
8381
}
8482
}
8583
func (handler *CommonDeploymentRestHandlerImpl) getAppOfferingMode(installedAppId string, appId string) (string, *appStoreBean.InstallAppVersionDTO, error) {
@@ -91,9 +89,9 @@ func (handler *CommonDeploymentRestHandlerImpl) getAppOfferingMode(installedAppI
9189
err = &util.ApiError{HttpStatusCode: http.StatusBadRequest, UserMessage: "invalid app id"}
9290
return appOfferingMode, installedAppDto, err
9391
}
94-
installedAppDto, err = handler.appStoreDeploymentServiceC.GetInstalledAppByClusterNamespaceAndName(appIdentifier.ClusterId, appIdentifier.Namespace, appIdentifier.ReleaseName)
92+
installedAppDto, err = handler.appStoreDeploymentService.GetInstalledAppByClusterNamespaceAndName(appIdentifier.ClusterId, appIdentifier.Namespace, appIdentifier.ReleaseName)
9593
if err != nil {
96-
err = &util.ApiError{HttpStatusCode: http.StatusInternalServerError, UserMessage: "unable to find app in database"}
94+
err = &util.ApiError{HttpStatusCode: http.StatusBadRequest, UserMessage: "unable to find app in database"}
9795
return appOfferingMode, installedAppDto, err
9896
}
9997
// this is the case when hyperion apps does not linked yet
@@ -117,9 +115,9 @@ func (handler *CommonDeploymentRestHandlerImpl) getAppOfferingMode(installedAppI
117115
err = &util.ApiError{HttpStatusCode: http.StatusBadRequest, UserMessage: "invalid installed app id"}
118116
return appOfferingMode, installedAppDto, err
119117
}
120-
installedAppDto, err = handler.appStoreDeploymentServiceC.GetInstalledAppByInstalledAppId(installedAppId)
118+
installedAppDto, err = handler.appStoreDeploymentService.GetInstalledAppByInstalledAppId(installedAppId)
121119
if err != nil {
122-
err = &util.ApiError{HttpStatusCode: http.StatusInternalServerError, UserMessage: "unable to find app in database"}
120+
err = &util.ApiError{HttpStatusCode: http.StatusBadRequest, UserMessage: "unable to find app in database"}
123121
return appOfferingMode, installedAppDto, err
124122
}
125123
} else {

api/bean/GitOpsConfig.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ type GitOpsConfigDto struct {
1313
BitBucketWorkspaceId string `json:"bitBucketWorkspaceId"`
1414
BitBucketProjectKey string `json:"bitBucketProjectKey"`
1515

16+
// TODO refactoring: create different struct for internal fields
1617
GitRepoName string `json:"gitRepoName"`
1718
UserEmailId string `json:"userEmailId"`
1819
Description string `json:"description"`

api/cluster/EnvironmentRestHandler.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ type EnvironmentRestHandlerImpl struct {
6666
validator *validator.Validate
6767
enforcer casbin.Enforcer
6868
deleteService delete2.DeleteService
69-
k8sUtil *k8s2.K8sUtil
69+
k8sUtil *k8s2.K8sServiceImpl
7070
cfg *bean.Config
7171
}
7272

@@ -75,7 +75,7 @@ type ClusterReachableResponse struct {
7575
ClusterName string `json:"clusterName"`
7676
}
7777

78-
func NewEnvironmentRestHandlerImpl(svc request.EnvironmentService, logger *zap.SugaredLogger, userService user.UserService, validator *validator.Validate, enforcer casbin.Enforcer, deleteService delete2.DeleteService, k8sUtil *k8s2.K8sUtil, k8sCommonService k8s.K8sCommonService) *EnvironmentRestHandlerImpl {
78+
func NewEnvironmentRestHandlerImpl(svc request.EnvironmentService, logger *zap.SugaredLogger, userService user.UserService, validator *validator.Validate, enforcer casbin.Enforcer, deleteService delete2.DeleteService, k8sUtil *k8s2.K8sServiceImpl, k8sCommonService k8s.K8sCommonService) *EnvironmentRestHandlerImpl {
7979
cfg := &bean.Config{}
8080
err := env.Parse(cfg)
8181
if err != nil {

0 commit comments

Comments
 (0)