From 84bb8618686a7d92861202e73f4e0fc633650c25 Mon Sep 17 00:00:00 2001 From: Sally Young Date: Wed, 14 Aug 2024 09:58:48 +0100 Subject: [PATCH] Issue #112 #332: Seperate Security Checks and Replace Composer Lock Diff (#636) * Issue #112 #332: Seperate Security Checks and Replace Composer Lock Diff --- README.md | 17 ++++- drainpipe-dev/composer.json | 1 + scaffold/github/workflows/Security.yml | 86 ++++++++++++++++++++++++++ src/ScaffoldInstallerPlugin.php | 4 ++ tasks/test.yml | 7 ++- 5 files changed, 113 insertions(+), 2 deletions(-) create mode 100644 scaffold/github/workflows/Security.yml diff --git a/README.md b/README.md index 046247e39..1e8fc04e7 100644 --- a/README.md +++ b/README.md @@ -391,7 +391,22 @@ They are composite actions which can be used in any of your workflows e.g. Tests can be run locally with [act](https://github.com/nektos/act): `act -P ubuntu-latest=ghcr.io/catthehacker/ubuntu:runner-latest -j Static-Tests` -### Composer Lock Diff +### Security +```json +"extra": { + "drainpipe": { + "github": ["Security"] + } +} +``` + +Runs security checks for composer packages and Drupal contrib, as well as posting +a diff of `composer.lock` as a review comment. + +### Composer Lock Diff (Deprecated) + +**This is now provided as part of the Security workflow** + Update Pull Request descriptions with a markdown table of any changes detected in `composer.lock` using [composer-lock-diff](https://github.com/davidrjonas/composer-lock-diff). diff --git a/drainpipe-dev/composer.json b/drainpipe-dev/composer.json index 57642ae94..8d16d1328 100644 --- a/drainpipe-dev/composer.json +++ b/drainpipe-dev/composer.json @@ -15,6 +15,7 @@ "composer-plugin-api": "^2.0", "behat/mink": "^1.11.0", "behat/mink-browserkit-driver": "^2.2.0", + "davidrjonas/composer-lock-diff": "^1.7", "drupal/coder": "^8.3.24", "lullabot/drainpipe": "*", "mglaman/phpstan-drupal": "^1.2.12", diff --git a/scaffold/github/workflows/Security.yml b/scaffold/github/workflows/Security.yml new file mode 100644 index 000000000..e69eb7518 --- /dev/null +++ b/scaffold/github/workflows/Security.yml @@ -0,0 +1,86 @@ +name: "Security" + +on: + pull_request: + types: [opened, synchronize, reopened] + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +jobs: + Security: + runs-on: ubuntu-22.04 + permissions: + contents: read + pull-requests: write + steps: + - uses: actions/checkout@v4 + + - name: Checkout base branch + run: | + git fetch --no-tags --depth=1 origin ${{ github.base_ref }} + git checkout ${{ github.base_ref }} + git checkout - + + - uses: actions/cache@v4 + with: + path: ${{ github.workspace }}/.ddev/.drainpipe-composer-cache + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} + restore-keys: | + ${{ runner.os }}-composer- + + - uses: ./.github/actions/drainpipe/set-env + + - name: Install and Start DDEV + uses: ./.github/actions/drainpipe/ddev + with: + git-name: Drainpipe Bot + git-email: no-reply@example.com + ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }} + ssh-known-hosts: ${{ secrets.SSH_KNOWN_HOSTS }} + + - name: Build Project + run: ddev composer install + + - name: Run Security Checks + run: ddev task security composer_lock_diff_from=${{ github.base_ref }} composer_lock_diff=composer-lock-diff.md + + - name: Publish Results + run: | + COMPOSER_LOCK_DIFF=" + ## Composer Lock Diff + $(cat composer-lock-diff.md)" + COMPOSER_LOCK_DIFF=$(echo "$COMPOSER_LOCK_DIFF" | jq -Rsa .) + FIRST=true + echo $COMPOSER_LOCK_DIFF >> $GITHUB_STEP_SUMMARY + curl -s -L -f -X GET \ + -H "Accept: application/vnd.github+json" \ + -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \ + -H "X-GitHub-Api-Version: 2022-11-28" https://api.github.com/repos/${{ github.repository }}/pulls/$DRAINPIPE_PR_NUMBER/comments | jq -rc '.[]|select(.body | contains("")) | .id' | while read i; do + if [ "$FIRST" == "true" ]; then + FIRST=false + curl -L \ + -X PATCH \ + -H "Accept: application/vnd.github+json" \ + -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + https://api.github.com/repos/${{ github.repository }}/pulls/comments/$i \ + -d "{\"body\":$COMPOSER_LOCK_DIFF}" + fi + curl -L \ + -X DELETE \ + -H "Accept: application/vnd.github+json" \ + -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + https://api.github.com/repos/${{ github.repository }}/pulls/comments/$i + done + if [ "$FIRST" == "true" ]; then + curl -L -f \ + -X POST \ + -H "Accept: application/vnd.github+json" \ + -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + https://api.github.com/repos/${{ github.repository }}/pulls/$DRAINPIPE_PR_NUMBER/comments \ + -d "{\"body\":$COMPOSER_LOCK_DIFF,\"commit_id\":\"$DRAINPIPE_SHA\",\"path\":\"composer.lock\",\"subject_type\":\"file\",\"side\":\"RIGHT\"}" + fi diff --git a/src/ScaffoldInstallerPlugin.php b/src/ScaffoldInstallerPlugin.php index 95919068c..91735ebec 100644 --- a/src/ScaffoldInstallerPlugin.php +++ b/src/ScaffoldInstallerPlugin.php @@ -333,6 +333,10 @@ private function installGitHubActions(string $scaffoldPath): void { $fs->ensureDirectoryExists('./.github/workflows'); $fs->copy("$scaffoldPath/github/workflows/ComposerLockDiff.yml", './.github/workflows/ComposerLockDiff.yml'); } + else if ($github === 'Security') { + $fs->ensureDirectoryExists('./.github/workflows'); + $fs->copy("$scaffoldPath/github/workflows/Security.yml", './.github/workflows/Security.yml'); + } } } diff --git a/tasks/test.yml b/tasks/test.yml index d11aeadb6..7ed67a8bf 100644 --- a/tasks/test.yml +++ b/tasks/test.yml @@ -17,7 +17,7 @@ vars: tasks: static: desc: Runs all static tests - deps: [security, lint, phpstan, phpunit:static, phpcs] + deps: [lint, phpstan, phpunit:static, phpcs] functional: desc: Runs all tests that require a bootstrapped Drupal site deps: [config, phpunit:functional, nightwatch] @@ -41,6 +41,11 @@ tasks: ./vendor/bin/local-php-security-checker fi - composer audit + - | + ./vendor/bin/composer-lock-diff --from {{ shellQuote (.composer_lock_diff_from | default "main") }} --md + if [ "" != {{ shellQuote (.composer_lock_diff | default "") }} ]; then + ./vendor/bin/composer-lock-diff --from {{ shellQuote (.composer_lock_diff_from | default "main") }} --md > {{ shellQuote (.composer_lock_diff | default "") }} + fi lint: desc: Runs lint on composer, YAML, and Twig files # @todo JUnit output