diff --git a/.github/workflows/pr-issue-validator.yaml b/.github/workflows/pr-issue-validator.yaml index 0a053f6ed0..e75dd437a6 100644 --- a/.github/workflows/pr-issue-validator.yaml +++ b/.github/workflows/pr-issue-validator.yaml @@ -29,6 +29,10 @@ jobs: steps: - name: Checkout repository uses: actions/checkout@v2 + with: + ref: ${{ github.event.pull_request.head.sha }} + fetch-depth: 0 + - name: Validate Issue Reference env: @@ -150,3 +154,84 @@ jobs: gh pr edit $PRNUM --remove-label "PR:Ready-to-Review" exit 1 fi + - name: Check SQL file format and duplicates + shell: bash + env: + pr_no: ${{ github.event.pull_request.number }} + GH_TOKEN: ${{ github.token }} + run: | + + # Fetch the latest changes from the main branch + git fetch origin main + + # Get the list of changed files + git diff origin/main...HEAD --name-only > diff + + echo "Changed files:" + cat diff + + echo "Changed SQL files-:" + # Filter SQL files from the list of changed files + awk '/scripts\/sql\//' diff + + # Count the number of changed SQL files in the 'scripts/sql' directory + count=$(awk '/scripts\/sql\//' diff | wc -l) + + # Check if no SQL files were changed + if [[ $count == "0" ]]; then + echo "No SQL files were added, Exiting from this action." + exit 0 + fi + + # Iterate through each changed SQL file + for filename in $(awk '/scripts\/sql\//' diff); do + echo "Checking File: $filename" + + # Check if the SQL file name is in the correct format (i.e., it ends with either '.up.sql' or '.down.sql') + if [[ "$filename" =~ \.(up|down)\.sql$ ]]; then + + # Print a message that the file name is in the correct format + echo "File name: $filename is in the correct format" + else + # Print an error message + echo "Error: The SQL file name is not in the correct format: $filename." + + # Post a comment on a GitHub pull request with the error message + gh pr comment $pr_no --body "The SQL file name: $filename is not in the correct format." + + # Exit the script with a non-zero status code + exit 1 + fi + + # Navigate to the SQL files directory + sql_dir="scripts/sql" + echo "Current directory: $(pwd)" + cd "$sql_dir" + echo "SQL files directory: $(pwd)" + + # Extract the migration number from the SQL file name + migration_no=$(echo "$filename" | cut -d "/" -f 3 | cut -d "_" -f 1) + echo "Migration Number: $migration_no" + + # Count the number of files with the same migration number + migration_files_present_of_this_no=$(ls | cut -d "_" -f 1 | grep -w -c "$migration_no") + + # Navigate back to the original directory + cd ../.. + + # Check the conditions based on the number of files with the same migration number + if [[ $migration_files_present_of_this_no == "2" ]]; then + echo "All looks good for this migration number." + elif [[ $migration_files_present_of_this_no == "1" ]]; then + # Only one file is present for this migration number + echo "Only single migration file was present for migration no.: $migration_no. either up or down migration is missing! EXITING" + gh pr comment $pr_no --body "Error: Only a single migration file was present for this number: $migration_no." + exit 1 + else + # Migration number is repeated + echo "Error: Migration number is repeated." + gh pr comment $pr_no --body "Error: The SQL file number: $migration_no is duplicated" + exit 1 + fi + done + diff --git a/assets/copa-plugin-icon.png b/assets/copa-plugin-icon.png new file mode 100644 index 0000000000..0039b17c00 Binary files /dev/null and b/assets/copa-plugin-icon.png differ diff --git a/scripts/sql/214_copacetic_plugin_v1_0_0.down.sql b/scripts/sql/214_copacetic_plugin_v1_0_0.down.sql new file mode 100644 index 0000000000..5f9933bc86 --- /dev/null +++ b/scripts/sql/214_copacetic_plugin_v1_0_0.down.sql @@ -0,0 +1,8 @@ +DELETE FROM plugin_step_variable WHERE plugin_step_id=(SELECT ps.id FROM plugin_metadata p INNER JOIN plugin_step ps on ps.plugin_id=p.id WHERE p.name='Copacetic v1.0.0' and ps."index"=1 and ps.deleted=false); +DELETE FROM plugin_step WHERE plugin_id=(SELECT id FROM plugin_metadata WHERE name='Copacetic v1.0.0'); +DELETE FROM plugin_stage_mapping WHERE plugin_id=(SELECT id FROM plugin_metadata WHERE name='Copacetic v1.0.0'); +DELETE FROM pipeline_stage_step_variable WHERE pipeline_stage_step_id in (SELECT pipeline_stage_id FROM pipeline_stage_step WHERE name='Copacetic v1.0.0'); +DELETE FROM pipeline_stage_step_variable WHERE pipeline_stage_step_id in (SELECT id FROM pipeline_stage_step WHERE name='Copacetic v1.0.0'); +DELETE FROM pipeline_stage_step WHERE name ='Copacetic v1.0.0'; +DELETE FROM plugin_tag_relation WHERE plugin_id=(SELECT id FROM plugin_metadata WHERE name='Copacetic v1.0.0'); +DELETE FROM plugin_metadata WHERE name='Copacetic v1.0.0'; \ No newline at end of file diff --git a/scripts/sql/214_copacetic_plugin_v1_0_0.up.sql b/scripts/sql/214_copacetic_plugin_v1_0_0.up.sql new file mode 100644 index 0000000000..db969a2a1d --- /dev/null +++ b/scripts/sql/214_copacetic_plugin_v1_0_0.up.sql @@ -0,0 +1,81 @@ +INSERT INTO plugin_metadata (id,name,description,type,icon,deleted,created_on,created_by,updated_on,updated_by) +VALUES (nextval('id_seq_plugin_metadata'),'Copacetic v1.0.0','This plugin is used to patch the container image vulnerabilities (Patching for Multi Architecture Builds not supported currently).','PRESET','https://raw.githubusercontent.com/devtron-labs/devtron/main/assets/copa-plugin-icon.png',false,'now()',1,'now()',1); + +INSERT INTO "plugin_tag_relation" ("id", "tag_id", "plugin_id", "created_on", "created_by", "updated_on", "updated_by") VALUES (nextval('id_seq_plugin_tag_relation'), (SELECT id FROM plugin_tag WHERE name='Security'), (SELECT id FROM plugin_metadata WHERE name='Copacetic v1.0.0'),'now()', 1, 'now()', 1); +INSERT INTO "plugin_tag_relation" ("id", "tag_id", "plugin_id", "created_on", "created_by", "updated_on", "updated_by") VALUES (nextval('id_seq_plugin_tag_relation'), (SELECT id FROM plugin_tag WHERE name='DevSecOps'), (SELECT id FROM plugin_metadata WHERE name='Copacetic v1.0.0'),'now()', 1, 'now()', 1); + +INSERT INTO plugin_stage_mapping (id,plugin_id,stage_type,created_on,created_by,updated_on,updated_by) +VALUES (nextval('id_seq_plugin_stage_mapping'),(SELECT id from plugin_metadata where name='Copacetic v1.0.0'), 0,'now()',1,'now()',1); + +INSERT INTO "plugin_pipeline_script" ("id", "script","type","deleted","created_on", "created_by", "updated_on", "updated_by") +VALUES ( + nextval('id_seq_plugin_pipeline_script'), + $$#!/bin/sh + +export appName=$(echo $CI_CD_EVENT | jq --raw-output .commonWorkflowRequest.appName) +export registry=$(echo $CI_CD_EVENT | jq --raw-output .commonWorkflowRequest.dockerRegistryURL) +export repo=$(echo $CI_CD_EVENT | jq --raw-output .commonWorkflowRequest.dockerRepository) +export tag=$(echo $CI_CD_EVENT | jq --raw-output .commonWorkflowRequest.dockerImageTag) +export platform=$(echo $CI_CD_EVENT | jq --raw-output .commonWorkflowRequest.ciBuildConfig.dockerBuildConfig.targetPlatform) + +if [[ $platform == "linux/arm64,linux/amd64" ]] ; then + echo "platform = $platform" + echo "------------------------------------------------------------------------------------------------------------------------" + echo "######### Patching Multi Architecture Image not supported #########" + echo "------------------------------------------------------------------------------------------------------------------------" + echo "error: can't use copacetic plugin for muti-architecture builds" + exit 1; +else + curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin v0.46.1 + + uname_arch() { + arch=$(uname -m) + case $arch in + x86_64) arch="amd64" ;; + aarch64) arch="arm64" ;; + esac + echo ${arch} + } + os=$(uname | tr "[:upper:]" "[:lower:]") + uname_arch + wget https://github.com/project-copacetic/copacetic/releases/download/v0.5.1/copa_0.5.1_${os}_${arch}.tar.gz + tar -xvzf copa_0.5.1_${os}_${arch}.tar.gz + mv copa /usr/local/bin/ + + trivy image --vuln-type os --ignore-unfixed $registry/$repo:$tag | grep -i total + trivy image --vuln-type os --ignore-unfixed -f json -o $appName.json $registry/$repo:$tag + + export BUILDKIT_VERSION=v0.12.0 + docker run \ + --detach \ + --rm \ + --privileged \ + --name buildkitd \ + --entrypoint buildkitd \ + "moby/buildkit:$BUILDKIT_VERSION" + + copa patch -i $registry/$repo:$tag -r $appName.json -t $tag --addr docker-container://buildkitd --timeout "$CopaTimeout" + if [ $? -eq 0 ] ; then + trivy image --vuln-type os --ignore-unfixed $registry/$repo:$tag | grep -i total + docker push $registry/$repo:$tag + else + echo "------------------------------------------------------------------------------------------------------------------------" + echo "BUILD FAILED: non zero exit status during copa patch..." + echo "------------------------------------------------------------------------------------------------------------------------" + exit 1; + fi +fi +$$, + 'SHELL', + 'f', + 'now()', + 1, + 'now()', + 1 +); + +INSERT INTO "plugin_step" ("id", "plugin_id","name","description","index","step_type","script_id","deleted", "created_on", "created_by", "updated_on", "updated_by") +VALUES (nextval('id_seq_plugin_step'), (SELECT id FROM plugin_metadata WHERE name='Copacetic v1.0.0'),'Step 1','Step 1 - Copacetic v1.0.0','1','INLINE',(SELECT last_value FROM id_seq_plugin_pipeline_script),'f','now()', 1, 'now()', 1); + +INSERT INTO plugin_step_variable (id,plugin_step_id,name,format,description,is_exposed,allow_empty_value,default_value,value,variable_type,value_type,previous_step_index,variable_step_index,variable_step_index_in_plugin,reference_variable_name,deleted,created_on,created_by,updated_on,updated_by) +VALUES (nextval('id_seq_plugin_step_variable'),(SELECT ps.id FROM plugin_metadata p inner JOIN plugin_step ps on ps.plugin_id=p.id WHERE p.name='Copacetic v1.0.0' and ps."index"=1 and ps.deleted=false),'CopaTimeout','STRING','Timeout for copa patch command, default timeout is 5 minutes. For ex: 10m','t','t','5m',null,'INPUT','NEW',null,1,null,null,'f','now()',1,'now()',1);