11name : VirusTotal
22
33on :
4- release :
5- types :
6- - published
74 workflow_dispatch :
85 inputs :
96 release_tag :
@@ -29,27 +26,15 @@ jobs:
2926 env :
3027 GH_TOKEN : ${{ secrets.GITHUB_TOKEN }}
3128 run : |
32- if [ '${{ github.event_name }}' = 'workflow_dispatch' ]; then
33- TAG_NAME="$(printf '%s' '${{ inputs.release_tag }}' | xargs)"
34- if [ -z "$TAG_NAME" ]; then
35- TAG_NAME="$(gh release view --repo "$GITHUB_REPOSITORY" --json tagName --jq '.tagName')"
36- fi
37- else
38- TAG_NAME="${GITHUB_REF#refs/tags/}"
29+ TAG_NAME="$(printf '%s' '${{ inputs.release_tag }}' | xargs)"
30+ if [ -z "$TAG_NAME" ]; then
31+ TAG_NAME="$(gh release view --repo "$GITHUB_REPOSITORY" --json tagName --jq '.tagName')"
3932 fi
4033 printf 'Using tag: %s\n' "$TAG_NAME"
4134 echo "tag-name=$TAG_NAME" >>"$GITHUB_OUTPUT"
42- BODY="$(gh release view --repo "$GITHUB_REPOSITORY" "$TAG_NAME" --json body -q .body)"
43- if printf '%s' "$BODY" | grep -q 'virustotal\.com'; then
44- echo "Release body already contains VirusTotal report"
45- echo 'update-body=false' >>"$GITHUB_OUTPUT"
46- else
47- echo "Release body does not contain VirusTotal report"
48- echo 'update-body=true' >>"$GITHUB_OUTPUT"
49- fi
5035 -
5136 name : Download release assets
52- if : env.HAS_VT_API_KEY == 'true' && github.event_name == 'workflow_dispatch'
37+ if : env.HAS_VT_API_KEY == 'true'
5338 env :
5439 GH_TOKEN : ${{ secrets.GITHUB_TOKEN }}
5540 run : |
@@ -62,12 +47,72 @@ jobs:
6247 -
6348 name : Submit to VirusTotal
6449 if : env.HAS_VT_API_KEY == 'true'
50+ id : submit
6551 uses : crazy-max/ghaction-virustotal@v4
6652 with :
6753 vt_api_key : ${{ secrets.VIRUSTOTAL_API_KEY }}
68- github_token : ${{ secrets.GITHUB_TOKEN }}
69- update_release_body : ${{ steps.setup.outputs.update-body }}
54+ update_release_body : false
7055 request_rate : 4
7156 files : |
7257 *.exe
7358 *.zip
59+ -
60+ name : Update release body with VirusTotal report
61+ if : steps.submit.outputs.analysis
62+ uses : actions/github-script@v8
63+ env :
64+ TAG_NAME : ${{ steps.setup.outputs.tag-name }}
65+ ANALYSIS_RESULT : ${{ steps.submit.outputs.analysis }}
66+ with :
67+ script : |
68+ const tagName = process.env.TAG_NAME;
69+ const analysisResult = (process.env.ANALYSIS_RESULT || '').trim();
70+ if (analysisResult === '') {
71+ core.setFailed('Analysis output is empty');
72+ return;
73+ }
74+ const {owner, repo} = context.repo;
75+ const release = await github.rest.repos.getReleaseByTag({
76+ owner,
77+ repo,
78+ tag: tagName,
79+ });
80+ const originalBody = release.data.body || '';
81+ if (originalBody.trim() === '') {
82+ core.setFailed('Release body is empty');
83+ return;
84+ }
85+ const SUMMARY = '<summary>VirusTotal analysis</summary>'
86+ if (originalBody.includes(SUMMARY)) {
87+ core.info('Release body already contains VirusTotal analysis, skipping update.');
88+ return;
89+ }
90+ let detailsLines = [];
91+ const analysisLines = analysisResult
92+ .split(',')
93+ .map(line => line.trim())
94+ .filter(line => line !== '')
95+ ;
96+ analysisLines.forEach(analysisLine => {
97+ const match = analysisLine.match(/^\s*(.+?)\s*=\s*(https?:\/\/\S+)\s*$/);
98+ if (!match) {
99+ core.warning(`Skipping invalid analysis line: ${analysisLine}`);
100+ return;
101+ }
102+ const [_, filename, analysisURL] = match;
103+ detailsLines.push(` * [${filename}](${analysisURL})`);
104+ });
105+ if (detailsLines.length === 0) {
106+ core.warning('No valid analysis lines found, skipping update.');
107+ return;
108+ }
109+ const newBody = originalBody + `\n\n<details>\n ${SUMMARY}\n\n${detailsLines.join('\n')}\n</details>\n`;
110+ core.startGroup('New release body');
111+ core.info(newBody);
112+ core.endGroup();
113+ await github.rest.repos.updateRelease({
114+ owner,
115+ repo,
116+ release_id: release.data.id,
117+ body: newBody,
118+ });
0 commit comments