diff --git a/.github/workflows/code-path-changes.yml b/.github/workflows/code-path-changes.yml index f543394f479..8c3b346bf50 100644 --- a/.github/workflows/code-path-changes.yml +++ b/.github/workflows/code-path-changes.yml @@ -16,6 +16,7 @@ env: permissions: contents: read + pull-requests: read jobs: notify: @@ -30,8 +31,15 @@ jobs: node-version: '18' - name: Install dependencies + if: ${{ env.OAUTH2_CLIENT_ID != '' && env.OAUTH2_CLIENT_SECRET != '' && env.OAUTH2_REFRESH_TOKEN != '' }} run: npm install axios nodemailer + - name: Skip notification when mail secrets are missing + if: ${{ env.OAUTH2_CLIENT_ID == '' || env.OAUTH2_CLIENT_SECRET == '' || env.OAUTH2_REFRESH_TOKEN == '' }} + run: | + echo "Mail OAuth secrets are not configured. Skipping notification run." + - name: Run Notification Script + if: ${{ env.OAUTH2_CLIENT_ID != '' && env.OAUTH2_CLIENT_SECRET != '' && env.OAUTH2_REFRESH_TOKEN != '' }} run: | node .github/workflows/scripts/send-notification-on-change.js diff --git a/.github/workflows/scripts/send-notification-on-change.js b/.github/workflows/scripts/send-notification-on-change.js index 57079ef37cb..271623a8091 100644 --- a/.github/workflows/scripts/send-notification-on-change.js +++ b/.github/workflows/scripts/send-notification-on-change.js @@ -10,6 +10,15 @@ const path = require('path'); const axios = require('axios'); const nodemailer = require('nodemailer'); +function escapeHtml(value) { + return String(value) + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"') + .replace(/'/g, '''); +} + async function getAccessToken(clientId, clientSecret, refreshToken) { try { const response = await axios.post('https://oauth2.googleapis.com/token', { @@ -37,11 +46,16 @@ async function getAccessToken(clientId, clientSecret, refreshToken) { const refreshToken = process.env.OAUTH2_REFRESH_TOKEN; // validate params - if (!repo || !prNumber || !token || !clientId || !clientSecret || !refreshToken) { + if (!repo || !prNumber || !token) { console.error('Missing required environment variables.'); process.exit(1); } + if (!clientId || !clientSecret || !refreshToken) { + console.log('Mail OAuth secrets are not configured. Skipping notifications.'); + process.exit(0); + } + // the whole process is in a big try/catch. e.g. if the config file doesn't exist, github is down, etc. try { // Read and process the configuration file @@ -109,12 +123,14 @@ async function getAccessToken(clientId, clientSecret, refreshToken) { // Send one email per recipient for (const [email, files] of Object.entries(matchesByEmail)) { + const safeFiles = files.map(file => `
  • ${escapeHtml(file)}
  • `).join(''); + const prUrl = `https://github.com/${owner}/${repoName}/pull/${encodeURIComponent(prNumber)}`; const emailBody = ` - ${email}, + ${escapeHtml(email)},

    - Files relevant to your integration have been changed in open source ${repo}. The pull request is #${prNumber}. These are the files you monitor that have been modified: + Files relevant to your integration have been changed in open source ${escapeHtml(repo)}. The pull request is #${escapeHtml(prNumber)}. These are the files you monitor that have been modified:

    `; @@ -127,7 +143,6 @@ async function getAccessToken(clientId, clientSecret, refreshToken) { }); console.log(`Email sent successfully to ${email}`); - console.log(`${emailBody}`); } catch (error) { console.error(`Failed to send email to ${email}:`, error.message); }