VirusTotal Scan #95
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: VirusTotal Scan | |
| on: | |
| workflow_dispatch: | |
| schedule: | |
| - cron: "0 17 * * *" | |
| pull_request_target: | |
| types: [opened, synchronize] | |
| permissions: | |
| contents: read # Restrict GITHUB_TOKEN | |
| jobs: | |
| vt-plugin-scan-changes-check: | |
| if: github.event_name == 'pull_request_target' | |
| runs-on: ubuntu-latest | |
| outputs: | |
| plugins: ${{ steps.filter.outputs.plugins }} | |
| non_plugin_files: ${{ steps.filter.outputs.non_plugin_files }} | |
| steps: | |
| - name: Check out repository code | |
| uses: actions/checkout@v6 | |
| with: | |
| ref: ${{ github.event.pull_request.head.sha }} | |
| - uses: dorny/paths-filter@v4 | |
| id: filter | |
| with: | |
| predicate-quantifier: 'every' | |
| filters: | | |
| plugins: | |
| - 'plugins/*.json' | |
| non_plugin_files: | |
| - '**' | |
| - '!plugins/*.json' | |
| - name: Fail if non-plugin files changed | |
| if: github.event_name == 'pull_request_target' && steps.filter.outputs.plugins == 'true' && steps.filter.outputs.non_plugin_files == 'true' | |
| run: | | |
| echo "This PR contains changes to files outside the plugins directory." | |
| echo "Plugin submission PRs must only create/modify plugin manifest files in the plugins directory." | |
| exit 1 | |
| vt-plugin-scan: | |
| needs: vt-plugin-scan-changes-check | |
| if: | | |
| always() && ( | |
| (github.event_name == 'pull_request_target' && needs.vt-plugin-scan-changes-check.outputs.plugins == 'true' && needs.vt-plugin-scan-changes-check.outputs.non_plugin_files == 'false') || | |
| github.event_name == 'workflow_dispatch' || | |
| github.event_name == 'schedule' | |
| ) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Check out repository code | |
| uses: actions/checkout@v6 | |
| # To actually check out and run the plugin downloader from the fork's PR | |
| with: | |
| ref: ${{ github.event.pull_request.head.sha }} | |
| - name: Set up Python | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: "3.11" | |
| - name: Install dependencies | |
| run: pip install requests | |
| # Avoid repeat downloads which bump the plugins' download count | |
| - name: Restore downloaded plugin cache | |
| uses: actions/cache/restore@v5 | |
| # No need to restore cache, PR's plugin is downloaded and scanned each time. | |
| # Plugin dev may repeatedly only update one version | |
| if: github.event_name != 'pull_request_target' | |
| with: | |
| path: | | |
| scan-files/ | |
| plugin-download-cache.json | |
| key: plugin-zips-restore-not-used | |
| restore-keys: plugin-zips- | |
| - name: Download plugin submitted in this PR | |
| if: github.event_name == 'pull_request_target' | |
| run: python ci/src/download_plugins.py --mode new --output-dir scan-files | |
| - name: Download all plugins with cache metadata | |
| if: github.event_name != 'pull_request_target' | |
| run: python ci/src/download_plugins.py --output-dir scan-files --cache-meta plugin-download-cache.json | |
| - name: Restore VirusTotal scan cache from previous runs | |
| uses: actions/cache/restore@v5 | |
| # Don't use cache, upload/retrieve report from VirustTotal each time for new submissions | |
| if: github.event_name != 'pull_request_target' | |
| with: | |
| path: vt_cache.json | |
| key: vt-cache-restore-not-used | |
| restore-keys: vt-cache- | |
| - name: Run VirusTotal scan | |
| uses: jjw24/virustotal-scanner-action@v1.0.1 | |
| with: | |
| api-key: ${{ secrets.VT_API_KEY }} | |
| scan-paths: | | |
| ./scan-files/ | |
| no-cache: false | |
| cache-path: vt_cache.json | |
| whitelist-path: vt_whitelist.json | |
| report-path: vt_report.json | |
| request-interval-sec: 15 | |
| analysis-poll-timeout-sec: 600 | |
| download-timeout-sec: 120 | |
| max-report-age-days: 30 | |
| - name: Save VirusTotal scan cache for future runs | |
| uses: actions/cache/save@v5 | |
| # Cache not used for PR plugin submissions | |
| if: always() && github.event_name != 'pull_request_target' | |
| with: | |
| path: vt_cache.json | |
| key: vt-cache-${{ hashFiles('vt_cache.json') }} | |
| - name: Save plugin ZIPs and cache metadata for future runs | |
| uses: actions/cache/save@v5 | |
| # Upload even if scan fails | |
| if: always() && github.event_name != 'pull_request_target' | |
| with: | |
| path: | | |
| scan-files/ | |
| plugin-download-cache.json | |
| key: plugin-zips-${{ hashFiles('plugin-download-cache.json') }} | |
| - name: Upload VirusTotal scan report as viewable artifact | |
| uses: actions/upload-artifact@v7 | |
| if: always() | |
| with: | |
| path: vt_report.json | |
| archive: false | |
| - name: Upload VirusTotal scan cache as viewable artifact | |
| uses: actions/upload-artifact@v7 | |
| # Cache not used for PR plugin submissions | |
| if: always() && github.event_name != 'pull_request_target' | |
| with: | |
| path: vt_cache.json | |
| archive: false | |
| - name: Upload plugin download cache metadata as viewable artifact | |
| uses: actions/upload-artifact@v7 | |
| # Upload even if scan fails | |
| if: always() && github.event_name != 'pull_request_target' | |
| with: | |
| path: plugin-download-cache.json | |
| archive: false |