From 2118843f0d43a0d04a923d273d0bac6234e0e11a Mon Sep 17 00:00:00 2001 From: Erik Schierboom Date: Wed, 20 Nov 2024 09:04:03 +0100 Subject: [PATCH] Fix no important files script (#199) --- .../check-no-important-files-changed.yml | 76 +++++++++++++------ 1 file changed, 52 insertions(+), 24 deletions(-) diff --git a/.github/workflows/check-no-important-files-changed.yml b/.github/workflows/check-no-important-files-changed.yml index dc926a5..bfa0ff2 100644 --- a/.github/workflows/check-no-important-files-changed.yml +++ b/.github/workflows/check-no-important-files-changed.yml @@ -20,39 +20,67 @@ jobs: name: No important files changed runs-on: ubuntu-22.04 steps: - - name: Checkout code - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 - with: - repository: ${{ inputs.repository }} - ref: ${{ inputs.ref }} - - name: Check if important files changed id: check - run: | - set -exo pipefail + uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea + with: + script: | + const { owner, repo } = context.repo; + const pull_number = context.issue.number + + return github.rest.pulls.listFiles({ owner, repo, pull_number }) + .then(async ({ data: files }) => { + const filenames = files.map(file => file.filename); + console.log(`Files in PR: ${filenames}`); + + // Cache the parsed exercise config file's invalidator files + let exerciseInvalidatorFiles = {}; + + return filenames.some(async (filename) => { + const match = /^exercises\/(?practice|concept)\/(?[^\/]+)\/(?.+)$/i.exec(filename); + if (match?.groups === undefined) { + console.log(`${filename}: skipped (can't invalidate test results)`); + return false; + } + + const { type, slug, path } = match.groups; + const configFile = `exercises/${type}/${slug}/.meta/config.json`; - git remote add upstream "https://github.com/${GITHUB_REPOSITORY}.git" - git fetch --depth 1 upstream main + const parseInvalidatorFiles = (path) => { + return github.rest.repos + .getContent({ owner, repo, path }) + .then(({ data: { content } }) => JSON.parse(Buffer.from(content, "base64").toString())) + .then((config) => { + const files = config.files; + if (files === undefined) { + return []; + } - git diff --diff-filter=M --name-only upstream/main + return [].concat( + files["invalidator"] || [], + files["test"] || [], + files["editor"] || [] + ); + }) + .catch((err) => []); + }; - for changed_file in $(git diff --diff-filter=M --name-only upstream/main); do - slug="$(echo "${changed_file}" | sed --regexp-extended 's#exercises/[^/]+/([^/]+)/.*#\1#' )" - path_before_slug="$(echo "${changed_file}" | sed --regexp-extended "s#(.*)/${slug}/.*#\\1#" )" - path_after_slug="$( echo "${changed_file}" | sed --regexp-extended "s#.*/${slug}/(.*)#\\1#" )" - config_json_file="${path_before_slug}/${slug}/.meta/config.json" + exerciseInvalidatorFiles[slug] ||= await parseInvalidatorFiles(configFile); + const invalidatesTests = exerciseInvalidatorFiles[slug].includes(path) - if ! [ -f "${config_json_file}" ]; then - # cannot determine if important files changed without .meta/config.json - continue - fi + if (invalidatesTests) { + console.log(`${filename}: invalidates test results`); + } else { + console.log(`${filename}: does not invalidate test results`); + } - changed=$(jq --arg path "${path_after_slug}" '[.files.test, .files.invalidator, .files.editor] | flatten | index($path) != null' "${config_json_file}") - echo "important_files_changed=${changed}" >> "$GITHUB_OUTPUT" - done + return invalidatesTests; + }); + }) + .catch((err) => false); - name: Suggest to add [no important files changed] - if: steps.check.outputs.important_files_changed == 'true' + if: steps.check.outputs.result == 'true' uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea with: script: |