" >> ${GITHUB_STEP_SUMMARY}
+ echo "Build Context | Value |
" >> ${GITHUB_STEP_SUMMARY}
+ echo "Helm chart version | ${{ steps.get_context.outputs.CHART_VERSION }} |
" >> ${GITHUB_STEP_SUMMARY}
+ echo "Original registry | ${{ steps.get_context.outputs.ORIGINAL_REGISTRY }} |
" >> ${GITHUB_STEP_SUMMARY}
+ echo "Original repository | ${{ steps.get_context.outputs.ORIGINAL_REPO }} |
" >> ${GITHUB_STEP_SUMMARY}
+ echo "Original tag | ${{ steps.get_context.outputs.ORIGINAL_TAG }} |
" >> ${GITHUB_STEP_SUMMARY}
+ echo "Original image | ${{ steps.get_context.outputs.ORIGINAL_IMAGE }} |
" >> ${GITHUB_STEP_SUMMARY}
+ echo "Build registry | ${{ steps.get_context.outputs.BUILD_REGISTRY }} |
" >> ${GITHUB_STEP_SUMMARY}
+ echo "Build repository | ${{ steps.get_context.outputs.BUILD_REPO }} |
" >> ${GITHUB_STEP_SUMMARY}
+ echo "Build tag | ${BUILD_TAG} |
" >> ${GITHUB_STEP_SUMMARY}
+ echo "Build image | ${BUILD_IMAGE} |
" >> ${GITHUB_STEP_SUMMARY}
+ echo "Ref tags | ${REF_TAGS} |
" >> ${GITHUB_STEP_SUMMARY}
+ echo "All build images | ${{ steps.meta.outputs.tags }} |
" >> ${GITHUB_STEP_SUMMARY}
+ echo "Build labels | ${{ steps.meta.outputs.labels }} |
" >> ${GITHUB_STEP_SUMMARY}
+ echo "
" >> ${GITHUB_STEP_SUMMARY}
+ echo "" >> ${GITHUB_STEP_SUMMARY}
+ echo "" >> ${GITHUB_STEP_SUMMARY}
+ echo "Setting | Value |
" >> ${GITHUB_STEP_SUMMARY}
+ echo "Run Docs | $(get_output ${{ steps.conditionals.outputs.skip_docs }}) |
" >> ${GITHUB_STEP_SUMMARY}
+ echo "Run Build | $(get_output ${{ steps.conditionals.outputs.skip_build }}) |
" >> ${GITHUB_STEP_SUMMARY}
+ echo "Run Compliance | $(get_output ${{ steps.conditionals.outputs.skip_compliance_checks }}) |
" >> ${GITHUB_STEP_SUMMARY}
+ echo "Run Unit Tests | $(get_output ${{ steps.conditionals.outputs.skip_unit_tests }}) |
" >> ${GITHUB_STEP_SUMMARY}
+ echo "Run SAST | $(get_output ${{ steps.conditionals.outputs.skip_sast }}) |
" >> ${GITHUB_STEP_SUMMARY}
+ echo "Run SCA | $(get_output ${{ steps.conditionals.outputs.skip_sca }}) |
" >> ${GITHUB_STEP_SUMMARY}
+ echo "Run Integration Tests | $(get_output ${{ steps.conditionals.outputs.skip_integration_tests }}) |
" >> ${GITHUB_STEP_SUMMARY}
+ echo "Report type | ${{ steps.conditionals.outputs.output_type }} |
" >> ${GITHUB_STEP_SUMMARY}
+ echo "
" >> ${GITHUB_STEP_SUMMARY}
+ echo "($(get_output 'none') - run all jobs, $(get_output 'non-required') - run important/required jobs only, $(get_output 'all') - skip jobs)" >> ${GITHUB_STEP_SUMMARY}
+ echo "" >> ${GITHUB_STEP_SUMMARY}
+
+ build:
+ uses: ./.github/workflows/.reusable-build.yml
+ needs: [conditionals]
+ # permissions: #TODO: reactivate for non-private
+ # packages: write
+ secrets: inherit
+ with:
+ skip: ${{ needs.conditionals.outputs.skip_build }}
+
+ compliance:
+ uses: ./.github/workflows/.reusable-compliance.yml
+ needs: [conditionals]
+ # permissions: #TODO: reactivate for non-private
+ # contents: write
+ # id-token: write
+ # security-events: write
+ # actions: read
+ # checks: read
+ # deployments: read
+ # issues: read
+ # discussions: read
+ # packages: read
+ # pages: read
+ # pull-requests: read
+ # repository-projects: read
+ # statuses: read
+ secrets: inherit
+ with:
+ skip: ${{ needs.conditionals.outputs.skip_compliance_checks }}
+
+ unit-test:
+ uses: ./.github/workflows/.reusable-unit-test.yml
+ needs: [conditionals]
+ with:
+ skip: ${{ needs.conditionals.outputs.skip_unit_tests }}
+
+ sast:
+ uses: ./.github/workflows/.reusable-sast.yml
+ needs: [conditionals]
+ # permissions: #TODO: reactivate for non-private
+ # security-events: write
+ # pull-requests: read
+ with:
+ skip: ${{ needs.conditionals.outputs.skip_sast }}
+ output: ${{ needs.conditionals.outputs.output_type }}
+
+ sca:
+ uses: ./.github/workflows/.reusable-sca.yml
+ needs: [conditionals, build]
+ # permissions: #TODO: reactivate for non-private
+ # contents: write
+ # security-events: write
+ # packages: read
+ secrets: inherit
+ with:
+ registry: ${{ needs.build.outputs.build_registry }}
+ repo_owner: ${{ github.repository_owner }}
+ image: ${{ needs.build.outputs.build_image }}
+ skip: ${{ needs.conditionals.outputs.skip_sca }}
+ output: ${{ needs.conditionals.outputs.output_type }}
+
+ docs:
+ uses: ./.github/workflows/.reusable-docs.yml
+ needs: [conditionals]
+ # permissions: #TODO: reactivate for non-private
+ # contents: write
+ with:
+ skip: ${{ needs.conditionals.outputs.skip_docs }}
+
+ integration-test:
+ uses: ./.github/workflows/.reusable-integration-test.yml
+ needs: [conditionals, build]
+ # permissions: #TODO: reactivate for non-private
+ # packages: read
+ secrets: inherit
+ with:
+ build_registry: ${{ needs.build.outputs.build_registry }}
+ repo_owner: ${{ github.repository_owner }}
+ build_image_repository: ${{ needs.build.outputs.build_registry }}/${{ needs.build.outputs.build_repo }}
+ build_tag: ${{ needs.build.outputs.build_tag }}
+ skip: ${{ needs.conditionals.outputs.skip_integration_tests }}
+ cosign_public_key: ${{ needs.build.outputs.cosign_public_key }}
diff --git a/.github/workflows/.reusable-cleanup-registry.yml b/.github/workflows/.reusable-cleanup-registry.yml
new file mode 100644
index 0000000..2bef523
--- /dev/null
+++ b/.github/workflows/.reusable-cleanup-registry.yml
@@ -0,0 +1,40 @@
+name: cleanup registry
+
+on:
+ workflow_call:
+
+permissions: {}
+
+jobs:
+ cleanup-registry:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Cleanup test images in 'connaisseur-test'
+ uses: snok/container-retention-policy@3d27e6a0361deed0b7dc5099a82eadd07924b177 # v2.1.3
+ with:
+ image-names: connaisseur-test
+ cut-off: three weeks ago UTC+1
+ timestamp-to-use: updated_at
+ account-type: org
+ org-name: sse-secure-systems
+ token: ${{ secrets.GHCR_PAT }}
+ - name: Cleanup dangling images without tag
+ uses: snok/container-retention-policy@3d27e6a0361deed0b7dc5099a82eadd07924b177 # v2.1.3
+ with:
+ image-names: connaisseur*
+ untagged-only: true
+ cut-off: four hours ago UTC+1
+ timestamp-to-use: updated_at
+ account-type: org
+ org-name: sse-secure-systems
+ token: ${{ secrets.GHCR_PAT }}
+ - name: Cleanup all connaisseur images
+ uses: snok/container-retention-policy@3d27e6a0361deed0b7dc5099a82eadd07924b177 # v2.1.3
+ with:
+ image-names: connaisseur
+ skip-tags: master, develop, v*, sha256-*
+ cut-off: four days ago UTC+1
+ timestamp-to-use: updated_at
+ account-type: org
+ org-name: sse-secure-systems
+ token: ${{ secrets.GHCR_PAT }}
diff --git a/.github/workflows/.reusable-compliance.yml b/.github/workflows/.reusable-compliance.yml
new file mode 100644
index 0000000..af38ccf
--- /dev/null
+++ b/.github/workflows/.reusable-compliance.yml
@@ -0,0 +1,87 @@
+name: compliance
+
+on:
+ workflow_call:
+ inputs:
+ skip:
+ description: "Want to skip running certain jobs 'none', 'non-required', 'all'?"
+ type: string
+ default: "none"
+
+#permissions: read-all
+
+jobs:
+ ossf-scorecard:
+ runs-on: ubuntu-latest
+ if: |
+ (github.ref_name == 'master' || github.event_name == 'pull_request') &&
+ inputs.skip != 'non-required' &&
+ inputs.skip != 'all'
+ # permissions: #TODO: reactivate for non-private
+ # security-events: write
+ # id-token: write
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ with:
+ persist-credentials: false
+ - name: Analyze
+ uses: ossf/scorecard-action@0864cf19026789058feabb7e87baa5f140aac736 # v2.3.1
+ with:
+ results_file: results.sarif
+ results_format: sarif
+ repo_token: ${{ secrets.SCORECARD_TOKEN }}
+ publish_results: ${{ github.ref_name == 'master' }}
+ - name: Upload
+ uses: github/codeql-action/upload-sarif@66b90a5db151a8042fa97405c6cf843bbe433f7b # v2.22.7
+ with:
+ sarif_file: results.sarif
+
+ dependency-review:
+ name: dependency review
+ runs-on: ubuntu-latest
+ if: |
+ github.event_name == 'pull_request' &&
+ inputs.skip != 'non-required' &&
+ inputs.skip != 'all'
+ # permissions: #TODO: reactivate for non-private
+ # contents: write
+ # pull-requests: write
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ - name: Review
+ uses: actions/dependency-review-action@7bbfa034e752445ea40215fff1c3bf9597993d3f # v3.1.3
+ with:
+ comment-summary-in-pr: always
+
+ check-commit-message:
+ runs-on: ubuntu-latest
+ if: |
+ github.event_name == 'pull_request' &&
+ inputs.skip != 'all'
+ # permissions: {} #TODO: reactivate for non-private
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ with:
+ ref: ${{ github.event.pull_request.head.sha }} # Otherwise will checkout merge commit, which isn't conform
+ fetch-depth: ${{ github.event.pull_request.commits }} # Fetch all commits of the MR, but only those
+ - name: Check commit messages for conformity
+ run: |
+ echo "Commits between dev branch and current SHA:"
+ COMMITS=$(git log --pretty=%H)
+ echo "${COMMITS}"
+ EXIT=0
+ COMMIT_MSGS=$(git log --pretty=%s) # show subject only
+ for commit in ${COMMITS}; do
+ MSG=$(git log ${commit} -n1 --pretty=%s)
+ TYPE=$(echo ${MSG} | awk '{{ print $1 }}')
+ if ! [[ "${TYPE}" =~ ^(build|ci|docs|feat|fix|refactor|test|update):$ ]]; then
+ EXIT=1
+ echo "Commit message of commit ${commit} doesn't conform to 'type: msg' format:"
+ echo "${MSG}"
+ echo "-------------------------"
+ fi
+ done
+ exit ${EXIT}
diff --git a/.github/workflows/.reusable-docs.yml b/.github/workflows/.reusable-docs.yml
new file mode 100644
index 0000000..fce6553
--- /dev/null
+++ b/.github/workflows/.reusable-docs.yml
@@ -0,0 +1,43 @@
+name: docs
+
+#permissions: {} #TODO: reactivate for non-private
+
+on:
+ workflow_call:
+ inputs:
+ skip:
+ description: "Want to skip running certain jobs 'none', 'non-required', 'all'?"
+ type: string
+ default: "none"
+
+jobs:
+ deploy:
+ runs-on: ubuntu-latest
+ if: inputs.skip != 'all'
+ permissions:
+ contents: write
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ with:
+ fetch-depth: 0
+ - name: Set release env
+ run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV
+ - name: Configure the git user
+ run: |
+ git config user.name "versioning_user"
+ git config user.email "connaisseur@securesystems.dev"
+ - name: Install
+ run: |
+ pip install -r docs/requirements.txt
+ - name: Deploy
+ if: inputs.skip != 'non-required'
+ run: |
+ if [[ "${GITHUB_REF}" == "refs/tags/v"* ]];
+ then
+ mike deploy --push --update-aliases ${RELEASE_VERSION} latest
+ elif [[ "${GITHUB_REF}" == "refs/heads/dev" ]]; then
+ mike deploy --push ${RELEASE_VERSION}
+ else
+ mkdocs build
+ fi
diff --git a/.github/workflows/.reusable-integration-test.yml b/.github/workflows/.reusable-integration-test.yml
new file mode 100644
index 0000000..43a8708
--- /dev/null
+++ b/.github/workflows/.reusable-integration-test.yml
@@ -0,0 +1,41 @@
+name: integration-test
+
+#permissions: {} #TODO: reactivate for non-private
+
+on:
+ workflow_call:
+ inputs:
+ build_registry:
+ description: "Workflow build registry used for testing"
+ type: string
+ repo_owner:
+ description: 'Name of repository owner, e.g. "inputs.repo_owner" for ghcr.io'
+ type: string
+ build_image_repository:
+ description: "Workflow build image used for testing, excluding the tag i.e. registry + repository"
+ type: string
+ build_tag:
+ description: "Tag of build image used for testing"
+ type: string
+ skip:
+ description: "Want to skip running certain jobs 'none', 'non-required', 'all'?"
+ type: string
+ default: "none"
+ cosign_public_key:
+ description: "Cosign public key used for signing the build image"
+ type: string
+
+env:
+ IMAGEPULLSECRET: dockerconfigjson-ghcr
+
+jobs:
+ do-nothing:
+ name: functional
+ runs-on: ubuntu-latest
+ if: inputs.skip != 'all'
+ # permissions: #TODO: reactivate for non-private
+ # packages: read
+ steps:
+ - name: Do nothing
+ run: |
+ sleep 1
diff --git a/.github/workflows/.reusable-sast.yml b/.github/workflows/.reusable-sast.yml
new file mode 100644
index 0000000..68d9451
--- /dev/null
+++ b/.github/workflows/.reusable-sast.yml
@@ -0,0 +1,235 @@
+name: sast
+
+on:
+ workflow_call:
+ inputs:
+ skip:
+ description: "Want to skip running certain jobs 'none', 'non-required', 'all'?"
+ type: string
+ default: "none"
+ output:
+ description: 'Output either "sarif" (GITHUB_TOKEN with security-events:write) or print results as "table" and fail on error'
+ type: string
+ required: false
+ default: 'sarif'
+
+#permissions: {} #TODO: reactivate for non-private
+
+jobs:
+ bandit:
+ runs-on: ubuntu-latest
+ if: |
+ (github.actor != 'dependabot[bot]') &&
+ inputs.skip != 'all'
+ permissions:
+ security-events: write
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ - name: Install Packages
+ run: pip3 install -r tests/requirements.txt
+ - name: Run Bandit
+ if: inputs.output == 'table'
+ run: bandit -r -f screen semgr8s/
+ - name: Run Bandit
+ if: inputs.output == 'sarif'
+ run: bandit -r -f sarif -o bandit-results.sarif semgr8s/ --exit-zero
+ - name: Upload
+ if: inputs.output == 'sarif'
+ uses: github/codeql-action/upload-sarif@407ffafae6a767df3e0230c3df91b6443ae8df75 # v2.22.8
+ with:
+ sarif_file: 'bandit-results.sarif'
+
+ black:
+ runs-on: ubuntu-latest
+ if: |
+ (github.actor != 'dependabot[bot]') &&
+ inputs.skip != 'non-required' &&
+ inputs.skip != 'all'
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ - name: Install packages
+ run: pip3 install -r tests/requirements.txt
+ - name: Test formatting
+ run: |
+ python3 -m black . 2>&1 | grep -q "reformatted" && { echo 'Not properly formatted.'; exit 1; } || true
+
+ checkov:
+ runs-on: ubuntu-latest
+ if: |
+ (github.actor != 'dependabot[bot]') &&
+ inputs.skip != 'non-required' &&
+ inputs.skip != 'all'
+ # permissions: #TODO: reactivate for non-private
+ # security-events: write
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ - name: Render Helm charts
+ run: |
+ rm -rf test # remove 'test' folder from scan #TODO: fix once final
+ rm -rf tests # remove 'tests' folder from scan
+ mkdir deployment
+ helm template charts/semgr8s > deployment/deployment.yaml
+ shell: bash
+ - name: Scan
+ if: inputs.output == 'table'
+ uses: bridgecrewio/checkov-action@558f721c4bd65a6fc59b02448ffc792eb721cb9b # v12.2580.0
+ with:
+ output_format: cli
+ soft_fail: false
+ - name: Scan
+ if: inputs.output == 'sarif'
+ uses: bridgecrewio/checkov-action@558f721c4bd65a6fc59b02448ffc792eb721cb9b # v12.2580.0
+ with:
+ output_file_path: console,checkov-results.sarif
+ output_format: cli,sarif
+ soft_fail: true
+ - name: Upload
+ if: inputs.output == 'sarif'
+ uses: github/codeql-action/upload-sarif@66b90a5db151a8042fa97405c6cf843bbe433f7b # v2.22.7
+ with:
+ sarif_file: checkov-results.sarif
+
+ codeql:
+ runs-on: ubuntu-latest
+ if: |
+ (github.actor != 'dependabot[bot]') &&
+ inputs.skip != 'non-required' &&
+ inputs.skip != 'all'
+ permissions:
+ security-events: write
+ pull-requests: read
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ - name: Initialize CodeQL
+ uses: github/codeql-action/init@407ffafae6a767df3e0230c3df91b6443ae8df75 # v2.22.8
+ with:
+ languages: 'python'
+ - name: Analyze
+ uses: github/codeql-action/analyze@407ffafae6a767df3e0230c3df91b6443ae8df75 # v2.22.8
+
+ hadolint:
+ runs-on: ubuntu-latest
+ if: |
+ (github.actor != 'dependabot[bot]') &&
+ inputs.skip != 'non-required' &&
+ inputs.skip != 'all'
+ # permissions: #TODO: reactivate for non-private
+ # security-events: write
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ - name: Scan
+ uses: hadolint/hadolint-action@54c9adbab1582c2ef04b2016b760714a4bfde3cf # v3.1.0
+ if: inputs.output == 'table'
+ with:
+ dockerfile: build/Dockerfile
+ format: tty
+ no-fail: false
+ - name: Scan
+ uses: hadolint/hadolint-action@54c9adbab1582c2ef04b2016b760714a4bfde3cf # v3.1.0
+ if: inputs.output == 'sarif'
+ with:
+ dockerfile: build/Dockerfile
+ format: sarif
+ no-fail: true
+ output-file: hadolint-results.sarif
+ - name: Upload
+ uses: github/codeql-action/upload-sarif@66b90a5db151a8042fa97405c6cf843bbe433f7b # v2.22.7
+ if: inputs.output == 'sarif'
+ with:
+ sarif_file: 'hadolint-results.sarif'
+
+ kubelinter:
+ runs-on: ubuntu-latest
+ if: |
+ (github.actor != 'dependabot[bot]') &&
+ inputs.skip != 'non-required' &&
+ inputs.skip != 'all'
+ # permissions: #TODO: reactivate for non-private
+ # security-events: write
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ - name: Scan
+ uses: stackrox/kube-linter-action@ca0d55b925470deb5b04b556e6c4276ea94d03c3 # v1.0.4
+ if: inputs.output == 'table'
+ with:
+ config: .kube-linter/config.yaml
+ directory: charts/semgr8s
+ format: plain
+ - name: Scan
+ uses: stackrox/kube-linter-action@ca0d55b925470deb5b04b556e6c4276ea94d03c3 # v1.0.4
+ if: inputs.output == 'sarif'
+ with:
+ config: .kube-linter/config.yaml
+ directory: charts/semgr8s
+ format: sarif
+ output-file: kubelinter-results.sarif
+ - name: Upload
+ uses: github/codeql-action/upload-sarif@66b90a5db151a8042fa97405c6cf843bbe433f7b # v2.22.7
+ if: inputs.output == 'sarif'
+ with:
+ sarif_file: 'kubelinter-results.sarif'
+
+ pylint:
+ runs-on: ubuntu-latest
+ if: |
+ (github.actor != 'dependabot[bot]') &&
+ inputs.skip != 'all'
+ container:
+ image: python:3.11-slim
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ - name: Install
+ run: |
+ pip3 install -r tests/requirements.txt
+ - name: Lint
+ run: pylint --ignore-patterns=tests,coverage semgr8s
+
+ semgrep:
+ runs-on: ubuntu-latest
+ if: |
+ (github.actor != 'dependabot[bot]') &&
+ inputs.skip != 'non-required' &&
+ inputs.skip != 'all'
+ # permissions: #TODO: reactivate for non-private
+ # security-events: write
+ container:
+ image: returntocorp/semgrep
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ - name: Scan
+ if: inputs.output == 'table'
+ run: semgrep ci --config=auto --suppress-errors --text
+ - name: Scan
+ if: inputs.output == 'sarif'
+ run: semgrep ci --config=auto --suppress-errors --sarif --output=semgrep-results.sarif || exit 0
+ - name: Upload
+ uses: github/codeql-action/upload-sarif@66b90a5db151a8042fa97405c6cf843bbe433f7b # v2.22.7
+ if: inputs.output == 'sarif'
+ with:
+ sarif_file: semgrep-results.sarif
+
+ trivy-config-scan:
+ name: trivy config
+ runs-on: ubuntu-latest
+ if: |
+ (github.actor != 'dependabot[bot]') &&
+ inputs.skip != 'non-required' &&
+ inputs.skip != 'all'
+ # permissions: #TODO: reactivate for non-private
+ # security-events: write
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ - name: Run Trivy
+ uses: ./.github/actions/trivy-config
+ with:
+ output: ${{ inputs.output }}
+
diff --git a/.github/workflows/.reusable-sca.yml b/.github/workflows/.reusable-sca.yml
new file mode 100644
index 0000000..66c5d76
--- /dev/null
+++ b/.github/workflows/.reusable-sca.yml
@@ -0,0 +1,100 @@
+name: sca
+
+#permissions: {} #TODO: reactivate for non-private
+
+on:
+ workflow_call:
+ inputs:
+ image:
+ description: "Image used for testing, i.e. registry + repository + tag"
+ type: string
+ required: true
+ registry:
+ description: 'Registry to login to pull image, e.g. "ghcr.io" for GHCR, leave empty if image is public'
+ type: string
+ required: false
+ default: ''
+ repo_owner:
+ description: 'Name of repository owner, e.g. "github.repository_owner" for ghcr.io'
+ type: string
+ required: false
+ default: ''
+ skip:
+ description: "Want to skip running certain jobs 'none', 'non-required', 'all'?"
+ type: string
+ default: "none"
+ output:
+ description: 'Output either "sarif" (GITHUB_TOKEN with security-events:write) or print results as "table" and fail on error'
+ type: string
+ required: false
+ default: 'sarif'
+
+jobs:
+ trivy-image-scan:
+ name: trivy image
+ runs-on: ubuntu-latest
+ if: inputs.skip != 'all'
+ # permissions: #TODO: reactivate for non-private
+ # packages: read
+ # security-events: write
+ container:
+ image: docker:stable
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ - name: Run
+ uses: ./.github/actions/trivy-image
+ with:
+ image: ${{ inputs.image }}
+ registry: ${{ inputs.registry }}
+ repo_owner: ${{ inputs.repo_owner }}
+ repo_token: ${{ secrets.GITHUB_TOKEN }}
+ output: ${{ inputs.output }}
+
+ grype:
+ name: grype
+ runs-on: ubuntu-latest
+ if: |
+ inputs.skip != 'non-required' &&
+ inputs.skip != 'all'
+ # permissions: #TODO: reactivate for non-private
+ # packages: read
+ # security-events: write
+ container:
+ image: docker:stable
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ - name: Run
+ uses: ./.github/actions/grype
+ with:
+ image: ${{ inputs.image }}
+ registry: ${{ inputs.registry }}
+ repo_owner: ${{ inputs.repo_owner }}
+ repo_token: ${{ secrets.GITHUB_TOKEN }}
+ output: ${{ inputs.output }}
+
+# WIP: Syft issue seems to cause error (https://github.com/anchore/syft/issues/1622)
+ dependency-submission:
+ name: syft / dependency review
+ runs-on: ubuntu-latest
+ if: |
+ inputs.skip != 'non-required' &&
+ inputs.skip != 'all'
+ # permissions: #TODO: reactivate for non-private
+ # packages: read
+ # contents: write
+ steps:
+ - name: Login with registry
+ if: inputs.registry != ''
+ uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0
+ with:
+ registry: ${{ inputs.registry }}
+ username: ${{ inputs.repo_owner }}
+ password: ${{ secrets.GITHUB_TOKEN }}
+ - name: Run
+ uses: anchore/sbom-action@78fc58e266e87a38d4194b2137a3d4e9bcaf7ca1 # v0.14.3
+ with:
+ image: ${{ inputs.image }}
+ format: cyclonedx-json
+ dependency-snapshot: ${{ inputs.output == 'sarif' }}
diff --git a/.github/workflows/.reusable-unit-test.yml b/.github/workflows/.reusable-unit-test.yml
new file mode 100644
index 0000000..6f7e711
--- /dev/null
+++ b/.github/workflows/.reusable-unit-test.yml
@@ -0,0 +1,29 @@
+name: unit-test
+
+#permissions: {} #TODO: reactivate for non-private
+
+on:
+ workflow_call:
+ inputs:
+ skip:
+ description: "Want to skip running certain jobs 'none', 'non-required', 'all'?"
+ type: string
+ default: "none"
+
+jobs:
+ gotest:
+ name: unit tests
+ runs-on: ubuntu-latest
+ if: inputs.skip != 'all'
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ - name: Install
+ run: |
+ pip3 install -r tests/requirements.txt && pip3 install .
+ - name: Test
+ run: pytest --cov=semgr8s --cov-report=xml tests/
+ - name: Upload
+ uses: codecov/codecov-action@eaaf4bedf32dbdc6b720b63067d99c4d77d6047d # v3.1.4
+ with:
+ file: coverage.xml
diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml
new file mode 100644
index 0000000..4c39e0c
--- /dev/null
+++ b/.github/workflows/pr.yml
@@ -0,0 +1,29 @@
+name: pr
+
+#permissions: {} #TODO: reactivate for non-private
+
+on:
+ pull_request:
+ branches:
+ - main
+ - dev
+
+defaults:
+ run:
+ shell: bash
+
+jobs:
+ ci:
+ uses: ./.github/workflows/.reusable-ci.yml
+ # permissions: #TODO: adjust for non-private
+ secrets: inherit
+ with:
+ #TODO: adjust for non private
+ skip_build: 'none'
+ skip_compliance_checks: 'none'
+ skip_unit_tests: 'all'
+ skip_sast: 'none'
+ skip_sca: 'none'
+ skip_docs: 'non-required'
+ skip_integration_tests: 'none'
+ output_type: 'sarif'
diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml
new file mode 100644
index 0000000..1c5516b
--- /dev/null
+++ b/.github/workflows/push.yml
@@ -0,0 +1,29 @@
+name: push
+
+#permissions: {} #TODO: reactivate for non-private
+
+on:
+ push:
+ branches:
+ - main
+ - dev
+
+defaults:
+ run:
+ shell: bash
+
+jobs:
+ ci:
+ uses: ./.github/workflows/.reusable-ci.yml
+ # permissions: #TODO: adjust for non-private
+ secrets: inherit
+ with:
+ #TODO: adjust for non private
+ skip_build: 'none'
+ skip_compliance_checks: 'none'
+ skip_unit_tests: 'all'
+ skip_sast: 'non-required'
+ skip_sca: 'non-required'
+ skip_docs: 'none'
+ skip_integration_tests: 'non-required'
+ output_type: 'sarif'
diff --git a/.github/workflows/tag.yml b/.github/workflows/tag.yml
new file mode 100644
index 0000000..138c21c
--- /dev/null
+++ b/.github/workflows/tag.yml
@@ -0,0 +1,28 @@
+name: tag
+
+#permissions: {} #TODO: reactivate for non-private
+
+on:
+ push:
+ tags:
+ - "v*"
+
+defaults:
+ run:
+ shell: bash
+
+jobs:
+ ci:
+ uses: ./.github/workflows/.reusable-ci.yml
+ # permissions: #TODO: adjust for non-private
+ secrets: inherit
+ with:
+ #TODO: adjust for non private
+ skip_build: 'none'
+ skip_compliance_checks: 'none'
+ skip_unit_tests: 'all'
+ skip_sast: 'none'
+ skip_sca: 'none'
+ skip_docs: 'none'
+ skip_integration_tests: 'non-required'
+ output_type: 'sarif'
diff --git a/.kube-linter/config.yaml b/.kube-linter/config.yaml
new file mode 100644
index 0000000..6b4d6ea
--- /dev/null
+++ b/.kube-linter/config.yaml
@@ -0,0 +1,2 @@
+checks:
+ doNotAutoAddDefaults: false
diff --git a/Makefile b/Makefile
index eb01dbc..c078174 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
webhookName := semgr8s
-image := $(shell yq e '.deployment.image.repository' helm/values.yaml)
-version := $(shell yq e '.appVersion' helm/Chart.yaml)
+image := $(shell yq e '.deployment.image.repository' charts/semgr8s/values.yaml)
+version := $(shell yq e '.appVersion' charts/semgr8s/Chart.yaml)
tag := $(image):$(version)
ns := semgr8ns
@@ -12,7 +12,7 @@ build:
@echo "####################"
@echo "## $(@)"
@echo "####################"
- docker build --platform=linux/amd64 -t $(tag) -f docker/Dockerfile .
+ docker buildx build --platform=linux/amd64 -t $(tag) -f build/Dockerfile .
.PHONY:push
push:
diff --git a/README.md b/README.md
index 79fe996..8dff3f0 100644
--- a/README.md
+++ b/README.md
@@ -1,37 +1,17 @@
-