mirror of
https://github.com/github/codeql-action.git
synced 2026-05-30 02:14:32 +00:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 2041daafe4 | |||
| 807ce4efd0 | |||
| bd0f7a95e7 |
@@ -41,38 +41,7 @@ runs:
|
|||||||
git add .
|
git add .
|
||||||
git commit -m "Update changelog and version after ${VERSION}"
|
git commit -m "Update changelog and version after ${VERSION}"
|
||||||
|
|
||||||
# Update the build artifacts with the new version number
|
git push origin "${NEW_BRANCH}"
|
||||||
- name: Rebuild the Action
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
set -exu
|
|
||||||
npm ci
|
|
||||||
npm run build
|
|
||||||
|
|
||||||
- name: Check for rebuild changes
|
|
||||||
id: rebuild_changes
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
set -exu
|
|
||||||
git add --all
|
|
||||||
if git diff --cached --quiet; then
|
|
||||||
echo "has_changes=false" >> "${GITHUB_OUTPUT}"
|
|
||||||
else
|
|
||||||
echo "has_changes=true" >> "${GITHUB_OUTPUT}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Commit rebuild
|
|
||||||
if: steps.rebuild_changes.outputs.has_changes == 'true'
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
set -exu
|
|
||||||
git commit -m "Rebuild"
|
|
||||||
|
|
||||||
- name: Push mergeback branch
|
|
||||||
shell: bash
|
|
||||||
env:
|
|
||||||
NEW_BRANCH: "${{ inputs.branch }}"
|
|
||||||
run: git push origin "${NEW_BRANCH}"
|
|
||||||
|
|
||||||
- name: Create PR
|
- name: Create PR
|
||||||
shell: bash
|
shell: bash
|
||||||
@@ -91,6 +60,8 @@ runs:
|
|||||||
|
|
||||||
Please do the following:
|
Please do the following:
|
||||||
|
|
||||||
|
- [ ] Remove and re-add the "Rebuild" label to the PR to trigger just this workflow.
|
||||||
|
- [ ] Wait for the "Rebuild" workflow to push a commit updating the distribution files.
|
||||||
- [ ] Mark the PR as ready for review to trigger the full set of PR checks.
|
- [ ] Mark the PR as ready for review to trigger the full set of PR checks.
|
||||||
- [ ] Approve and merge the PR. When merging the PR, make sure "Create a merge commit" is
|
- [ ] Approve and merge the PR. When merging the PR, make sure "Create a merge commit" is
|
||||||
selected rather than "Squash and merge" or "Rebase and merge".
|
selected rather than "Squash and merge" or "Rebase and merge".
|
||||||
@@ -103,6 +74,7 @@ runs:
|
|||||||
--head "${NEW_BRANCH}" \
|
--head "${NEW_BRANCH}" \
|
||||||
--base "${BASE_BRANCH}" \
|
--base "${BASE_BRANCH}" \
|
||||||
--title "${pr_title}" \
|
--title "${pr_title}" \
|
||||||
|
--label "Rebuild" \
|
||||||
--body "${pr_body}" \
|
--body "${pr_body}" \
|
||||||
--assignee "${GITHUB_ACTOR}" \
|
--assignee "${GITHUB_ACTOR}" \
|
||||||
--draft
|
--draft
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ runs:
|
|||||||
- name: Set up Node
|
- name: Set up Node
|
||||||
uses: actions/setup-node@v6
|
uses: actions/setup-node@v6
|
||||||
with:
|
with:
|
||||||
node-version: 24
|
node-version: 20
|
||||||
cache: 'npm'
|
cache: 'npm'
|
||||||
|
|
||||||
- name: Set up Python
|
- name: Set up Python
|
||||||
|
|||||||
@@ -16,27 +16,12 @@ No user facing changes.
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
# NB: This exact commit message is used to find commits for reverting during backports.
|
# NB: This exact commit message is used to find commits for reverting during backports.
|
||||||
# Changing it requires a transition period where both old and new versions are supported.
|
# Changing it requires a transition period where both old and new versions are supported.
|
||||||
BACKPORT_COMMIT_MESSAGE = 'Update version and changelog for v'
|
BACKPORT_COMMIT_MESSAGE = 'Update version and changelog for v'
|
||||||
|
|
||||||
# Commit message used for rebuild commits, both those produced by this script and those produced
|
|
||||||
# by the `Rebuild Action` workflow (`.github/workflows/rebuild.yml`).
|
|
||||||
REBUILD_COMMIT_MESSAGE = 'Rebuild'
|
|
||||||
|
|
||||||
# Name of the remote
|
# Name of the remote
|
||||||
ORIGIN = 'origin'
|
ORIGIN = 'origin'
|
||||||
|
|
||||||
# Environment variables to check for a GitHub API token.
|
|
||||||
TOKEN_ENVIRONMENT_VARIABLES = ('GH_TOKEN', 'GITHUB_TOKEN')
|
|
||||||
|
|
||||||
# Gets a GitHub API token from one of the supported environment variables.
|
|
||||||
def get_github_token():
|
|
||||||
for variable_name in TOKEN_ENVIRONMENT_VARIABLES:
|
|
||||||
token = os.environ.get(variable_name, '').strip()
|
|
||||||
if token:
|
|
||||||
return token
|
|
||||||
raise Exception('Missing GitHub token. Set GITHUB_TOKEN or GH_TOKEN.')
|
|
||||||
|
|
||||||
# Runs git with the given args and returns the stdout.
|
# Runs git with the given args and returns the stdout.
|
||||||
# Raises an error if git does not exit successfully (unless passed
|
# Raises an error if git does not exit successfully (unless passed
|
||||||
# allow_non_zero_exit_code=True).
|
# allow_non_zero_exit_code=True).
|
||||||
@@ -47,28 +32,6 @@ def run_git(*args, allow_non_zero_exit_code=False):
|
|||||||
raise Exception(f'Call to {" ".join(cmd)} exited with code {p.returncode} stderr: {p.stderr.decode("ascii")}.')
|
raise Exception(f'Call to {" ".join(cmd)} exited with code {p.returncode} stderr: {p.stderr.decode("ascii")}.')
|
||||||
return p.stdout.decode('ascii')
|
return p.stdout.decode('ascii')
|
||||||
|
|
||||||
# Runs the given command, streaming output to the console.
|
|
||||||
# Raises an error if the command does not exit successfully.
|
|
||||||
def run_command(*args):
|
|
||||||
cmd = list(args)
|
|
||||||
print(f'Running `{" ".join(cmd)}`.')
|
|
||||||
subprocess.run(cmd, check=True)
|
|
||||||
|
|
||||||
# Rebuilds the action and commits any changes.
|
|
||||||
def rebuild_action():
|
|
||||||
# For backports, the only source-level change vs the source branch is the new version number,
|
|
||||||
# so we just need to refresh the version embedded in `lib/`.
|
|
||||||
run_command('npm', 'ci')
|
|
||||||
run_command('npm', 'run', 'build')
|
|
||||||
|
|
||||||
run_git('add', '--all')
|
|
||||||
# `git diff --cached --quiet` exits 0 if there are no staged changes, 1 if there are.
|
|
||||||
if subprocess.run(['git', 'diff', '--cached', '--quiet']).returncode == 0:
|
|
||||||
print('Rebuild produced no changes; skipping Rebuild commit.')
|
|
||||||
else:
|
|
||||||
run_git('commit', '-m', REBUILD_COMMIT_MESSAGE)
|
|
||||||
print('Created Rebuild commit.')
|
|
||||||
|
|
||||||
# Returns true if the given branch exists on the origin remote
|
# Returns true if the given branch exists on the origin remote
|
||||||
def branch_exists_on_remote(branch_name):
|
def branch_exists_on_remote(branch_name):
|
||||||
return run_git('ls-remote', '--heads', ORIGIN, branch_name).strip() != ''
|
return run_git('ls-remote', '--heads', ORIGIN, branch_name).strip() != ''
|
||||||
@@ -124,11 +87,9 @@ def open_pr(
|
|||||||
body.append('Please do the following:')
|
body.append('Please do the following:')
|
||||||
if len(conflicted_files) > 0:
|
if len(conflicted_files) > 0:
|
||||||
body.append(' - [ ] Ensure `package.json` file contains the correct version.')
|
body.append(' - [ ] Ensure `package.json` file contains the correct version.')
|
||||||
body.append(' - [ ] Add a commit to this branch to resolve the merge conflicts ' +
|
body.append(' - [ ] Add commits to this branch to resolve the merge conflicts ' +
|
||||||
'in the following files:')
|
'in the following files:')
|
||||||
body.extend([f' - `{file}`' for file in conflicted_files])
|
body.extend([f' - [ ] `{file}`' for file in conflicted_files])
|
||||||
body.append(' - [ ] Rebuild the Action locally (`npm run build`) and push any changes to the ' +
|
|
||||||
f'built output in `lib` as a separate commit named exactly `{REBUILD_COMMIT_MESSAGE}`.')
|
|
||||||
body.append(' - [ ] Ensure another maintainer has reviewed the additional commits you added to this ' +
|
body.append(' - [ ] Ensure another maintainer has reviewed the additional commits you added to this ' +
|
||||||
'branch to resolve the merge conflicts.')
|
'branch to resolve the merge conflicts.')
|
||||||
body.append(' - [ ] Ensure the CHANGELOG displays the correct version and date.')
|
body.append(' - [ ] Ensure the CHANGELOG displays the correct version and date.')
|
||||||
@@ -136,6 +97,10 @@ def open_pr(
|
|||||||
body.append(f' - [ ] Check that there are not any unexpected commits being merged into the `{target_branch}` branch.')
|
body.append(f' - [ ] Check that there are not any unexpected commits being merged into the `{target_branch}` branch.')
|
||||||
body.append(' - [ ] Ensure the docs team is aware of any documentation changes that need to be released.')
|
body.append(' - [ ] Ensure the docs team is aware of any documentation changes that need to be released.')
|
||||||
|
|
||||||
|
if not is_primary_release:
|
||||||
|
body.append(' - [ ] Remove and re-add the "Rebuild" label to the PR to trigger just this workflow.')
|
||||||
|
body.append(' - [ ] Wait for the "Rebuild" workflow to push a commit updating the distribution files.')
|
||||||
|
|
||||||
body.append(' - [ ] Mark the PR as ready for review to trigger the full set of PR checks.')
|
body.append(' - [ ] Mark the PR as ready for review to trigger the full set of PR checks.')
|
||||||
body.append(' - [ ] Approve and merge this PR. Make sure `Create a merge commit` is selected rather than `Squash and merge` or `Rebase and merge`.')
|
body.append(' - [ ] Approve and merge this PR. Make sure `Create a merge commit` is selected rather than `Squash and merge` or `Rebase and merge`.')
|
||||||
|
|
||||||
@@ -144,11 +109,13 @@ def open_pr(
|
|||||||
body.append(' - [ ] Merge all backport PRs to older release branches, that will automatically be created once this PR is merged.')
|
body.append(' - [ ] Merge all backport PRs to older release branches, that will automatically be created once this PR is merged.')
|
||||||
|
|
||||||
title = f'Merge {source_branch} into {target_branch}'
|
title = f'Merge {source_branch} into {target_branch}'
|
||||||
|
labels = ['Rebuild'] if not is_primary_release else []
|
||||||
|
|
||||||
# Create the pull request
|
# Create the pull request
|
||||||
# PR checks won't be triggered on PRs created by Actions. Therefore mark the PR as draft so that
|
# PR checks won't be triggered on PRs created by Actions. Therefore mark the PR as draft so that
|
||||||
# a maintainer can take the PR out of draft, thereby triggering the PR checks.
|
# a maintainer can take the PR out of draft, thereby triggering the PR checks.
|
||||||
pr = repo.create_pull(title=title, body='\n'.join(body), head=new_branch_name, base=target_branch, draft=True)
|
pr = repo.create_pull(title=title, body='\n'.join(body), head=new_branch_name, base=target_branch, draft=True)
|
||||||
|
pr.add_to_labels(*labels)
|
||||||
print(f'Created PR #{str(pr.number)}')
|
print(f'Created PR #{str(pr.number)}')
|
||||||
|
|
||||||
# Assign the conductor
|
# Assign the conductor
|
||||||
@@ -303,6 +270,12 @@ def update_changelog(version):
|
|||||||
def main():
|
def main():
|
||||||
parser = argparse.ArgumentParser('update-release-branch.py')
|
parser = argparse.ArgumentParser('update-release-branch.py')
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
'--github-token',
|
||||||
|
type=str,
|
||||||
|
required=True,
|
||||||
|
help='GitHub token, typically from GitHub Actions.'
|
||||||
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'--repository-nwo',
|
'--repository-nwo',
|
||||||
type=str,
|
type=str,
|
||||||
@@ -340,7 +313,7 @@ def main():
|
|||||||
target_branch = args.target_branch
|
target_branch = args.target_branch
|
||||||
is_primary_release = args.is_primary_release
|
is_primary_release = args.is_primary_release
|
||||||
|
|
||||||
repo = Github(get_github_token()).get_repo(args.repository_nwo)
|
repo = Github(args.github_token).get_repo(args.repository_nwo)
|
||||||
|
|
||||||
# the target branch will be of the form releases/vN, where N is the major version number
|
# the target branch will be of the form releases/vN, where N is the major version number
|
||||||
target_branch_major_version = target_branch.strip('releases/v')
|
target_branch_major_version = target_branch.strip('releases/v')
|
||||||
@@ -407,9 +380,8 @@ def main():
|
|||||||
# releases.
|
# releases.
|
||||||
run_git('revert', vOlder_update_commits[0], '--no-edit')
|
run_git('revert', vOlder_update_commits[0], '--no-edit')
|
||||||
|
|
||||||
# Also revert the "Rebuild" commit, whether created by this script or by the
|
# Also revert the "Rebuild" commit created by Actions.
|
||||||
# `Rebuild Action` workflow.
|
rebuild_commit = run_git('log', '--grep', '^Rebuild$', '--format=%H').split()[0]
|
||||||
rebuild_commit = run_git('log', '--grep', f'^{REBUILD_COMMIT_MESSAGE}$', '--format=%H').split()[0]
|
|
||||||
print(f' Reverting {rebuild_commit}')
|
print(f' Reverting {rebuild_commit}')
|
||||||
run_git('revert', rebuild_commit, '--no-edit')
|
run_git('revert', rebuild_commit, '--no-edit')
|
||||||
|
|
||||||
@@ -424,10 +396,9 @@ def main():
|
|||||||
run_git('add', '.')
|
run_git('add', '.')
|
||||||
run_git('commit', '--no-edit')
|
run_git('commit', '--no-edit')
|
||||||
|
|
||||||
# Migrate the package version number from a vLatest version number to a vOlder version number.
|
# Migrate the package version number from a vLatest version number to a vOlder version number
|
||||||
# `package-lock.json` is updated as part of the subsequent rebuild step (see `rebuild_action`).
|
|
||||||
print(f'Setting version number to {version} in package.json')
|
print(f'Setting version number to {version} in package.json')
|
||||||
replace_version_package_json(get_current_version(), version)
|
replace_version_package_json(get_current_version(), version) # We rely on the `Rebuild` workflow to update package-lock.json
|
||||||
run_git('add', 'package.json')
|
run_git('add', 'package.json')
|
||||||
|
|
||||||
# Migrate the changelog notes from vLatest version numbers to vOlder version numbers
|
# Migrate the changelog notes from vLatest version numbers to vOlder version numbers
|
||||||
@@ -450,13 +421,6 @@ def main():
|
|||||||
run_git('add', 'CHANGELOG.md')
|
run_git('add', 'CHANGELOG.md')
|
||||||
run_git('commit', '-m', f'Update changelog for v{version}')
|
run_git('commit', '-m', f'Update changelog for v{version}')
|
||||||
|
|
||||||
if not is_primary_release:
|
|
||||||
if len(conflicted_files) == 0:
|
|
||||||
print('Rebuilding the Action.')
|
|
||||||
rebuild_action()
|
|
||||||
else:
|
|
||||||
print(f'Skipping automatic rebuild because the merge produced conflicts in {conflicted_files}.')
|
|
||||||
|
|
||||||
run_git('push', ORIGIN, new_branch_name)
|
run_git('push', ORIGIN, new_branch_name)
|
||||||
|
|
||||||
# Open a PR to update the branch
|
# Open a PR to update the branch
|
||||||
|
|||||||
+4
-4
@@ -49,6 +49,10 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
|
- os: ubuntu-latest
|
||||||
|
version: stable-v2.17.6
|
||||||
|
- os: ubuntu-latest
|
||||||
|
version: stable-v2.18.4
|
||||||
- os: ubuntu-latest
|
- os: ubuntu-latest
|
||||||
version: stable-v2.19.4
|
version: stable-v2.19.4
|
||||||
- os: ubuntu-latest
|
- os: ubuntu-latest
|
||||||
@@ -57,10 +61,6 @@ jobs:
|
|||||||
version: stable-v2.21.4
|
version: stable-v2.21.4
|
||||||
- os: ubuntu-latest
|
- os: ubuntu-latest
|
||||||
version: stable-v2.22.4
|
version: stable-v2.22.4
|
||||||
- os: ubuntu-latest
|
|
||||||
version: stable-v2.23.9
|
|
||||||
- os: ubuntu-latest
|
|
||||||
version: stable-v2.24.3
|
|
||||||
- os: ubuntu-latest
|
- os: ubuntu-latest
|
||||||
version: default
|
version: default
|
||||||
- os: ubuntu-latest
|
- os: ubuntu-latest
|
||||||
|
|||||||
+4
-4
@@ -49,6 +49,10 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
|
- os: ubuntu-latest
|
||||||
|
version: stable-v2.17.6
|
||||||
|
- os: ubuntu-latest
|
||||||
|
version: stable-v2.18.4
|
||||||
- os: ubuntu-latest
|
- os: ubuntu-latest
|
||||||
version: stable-v2.19.4
|
version: stable-v2.19.4
|
||||||
- os: ubuntu-latest
|
- os: ubuntu-latest
|
||||||
@@ -57,10 +61,6 @@ jobs:
|
|||||||
version: stable-v2.21.4
|
version: stable-v2.21.4
|
||||||
- os: ubuntu-latest
|
- os: ubuntu-latest
|
||||||
version: stable-v2.22.4
|
version: stable-v2.22.4
|
||||||
- os: ubuntu-latest
|
|
||||||
version: stable-v2.23.9
|
|
||||||
- os: ubuntu-latest
|
|
||||||
version: stable-v2.24.3
|
|
||||||
- os: ubuntu-latest
|
- os: ubuntu-latest
|
||||||
version: default
|
version: default
|
||||||
- os: ubuntu-latest
|
- os: ubuntu-latest
|
||||||
|
|||||||
+4
-4
@@ -49,6 +49,10 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
|
- os: ubuntu-latest
|
||||||
|
version: stable-v2.17.6
|
||||||
|
- os: ubuntu-latest
|
||||||
|
version: stable-v2.18.4
|
||||||
- os: ubuntu-latest
|
- os: ubuntu-latest
|
||||||
version: stable-v2.19.4
|
version: stable-v2.19.4
|
||||||
- os: ubuntu-latest
|
- os: ubuntu-latest
|
||||||
@@ -57,10 +61,6 @@ jobs:
|
|||||||
version: stable-v2.21.4
|
version: stable-v2.21.4
|
||||||
- os: ubuntu-latest
|
- os: ubuntu-latest
|
||||||
version: stable-v2.22.4
|
version: stable-v2.22.4
|
||||||
- os: ubuntu-latest
|
|
||||||
version: stable-v2.23.9
|
|
||||||
- os: ubuntu-latest
|
|
||||||
version: stable-v2.24.3
|
|
||||||
- os: ubuntu-latest
|
- os: ubuntu-latest
|
||||||
version: default
|
version: default
|
||||||
- os: ubuntu-latest
|
- os: ubuntu-latest
|
||||||
|
|||||||
+15
-15
@@ -59,41 +59,41 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
|
- os: ubuntu-latest
|
||||||
|
version: stable-v2.17.6
|
||||||
|
- os: macos-latest
|
||||||
|
version: stable-v2.17.6
|
||||||
|
- os: ubuntu-latest
|
||||||
|
version: stable-v2.18.4
|
||||||
|
- os: macos-latest
|
||||||
|
version: stable-v2.18.4
|
||||||
- os: ubuntu-latest
|
- os: ubuntu-latest
|
||||||
version: stable-v2.19.4
|
version: stable-v2.19.4
|
||||||
- os: macos-latest-xlarge
|
- os: macos-latest
|
||||||
version: stable-v2.19.4
|
version: stable-v2.19.4
|
||||||
- os: ubuntu-latest
|
- os: ubuntu-latest
|
||||||
version: stable-v2.20.7
|
version: stable-v2.20.7
|
||||||
- os: macos-latest-xlarge
|
- os: macos-latest
|
||||||
version: stable-v2.20.7
|
version: stable-v2.20.7
|
||||||
- os: ubuntu-latest
|
- os: ubuntu-latest
|
||||||
version: stable-v2.21.4
|
version: stable-v2.21.4
|
||||||
- os: macos-latest-xlarge
|
- os: macos-latest
|
||||||
version: stable-v2.21.4
|
version: stable-v2.21.4
|
||||||
- os: ubuntu-latest
|
- os: ubuntu-latest
|
||||||
version: stable-v2.22.4
|
version: stable-v2.22.4
|
||||||
- os: macos-latest-xlarge
|
- os: macos-latest
|
||||||
version: stable-v2.22.4
|
version: stable-v2.22.4
|
||||||
- os: ubuntu-latest
|
|
||||||
version: stable-v2.23.9
|
|
||||||
- os: macos-latest-xlarge
|
|
||||||
version: stable-v2.23.9
|
|
||||||
- os: ubuntu-latest
|
|
||||||
version: stable-v2.24.3
|
|
||||||
- os: macos-latest-xlarge
|
|
||||||
version: stable-v2.24.3
|
|
||||||
- os: ubuntu-latest
|
- os: ubuntu-latest
|
||||||
version: default
|
version: default
|
||||||
- os: macos-latest-xlarge
|
- os: macos-latest
|
||||||
version: default
|
version: default
|
||||||
- os: ubuntu-latest
|
- os: ubuntu-latest
|
||||||
version: linked
|
version: linked
|
||||||
- os: macos-latest-xlarge
|
- os: macos-latest
|
||||||
version: linked
|
version: linked
|
||||||
- os: ubuntu-latest
|
- os: ubuntu-latest
|
||||||
version: nightly-latest
|
version: nightly-latest
|
||||||
- os: macos-latest-xlarge
|
- os: macos-latest
|
||||||
version: nightly-latest
|
version: nightly-latest
|
||||||
name: Multi-language repository
|
name: Multi-language repository
|
||||||
if: github.triggering_actor != 'dependabot[bot]'
|
if: github.triggering_actor != 'dependabot[bot]'
|
||||||
|
|||||||
+1
-1
@@ -59,7 +59,7 @@ jobs:
|
|||||||
use-all-platform-bundle: 'false'
|
use-all-platform-bundle: 'false'
|
||||||
setup-kotlin: 'true'
|
setup-kotlin: 'true'
|
||||||
- name: Set up Ruby
|
- name: Set up Ruby
|
||||||
uses: ruby/setup-ruby@c4e5b1316158f92e3d49443a9d58b31d25ac0f8f # v1.306.0
|
uses: ruby/setup-ruby@0cb964fd540e0a24c900370abf38a33466142735 # v1.305.0
|
||||||
with:
|
with:
|
||||||
ruby-version: 2.6
|
ruby-version: 2.6
|
||||||
- name: Install Code Scanning integration
|
- name: Install Code Scanning integration
|
||||||
|
|||||||
Generated
+1
-1
@@ -40,7 +40,7 @@ jobs:
|
|||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- os: ubuntu-latest
|
- os: ubuntu-latest
|
||||||
version: stable-v2.19.4
|
version: stable-v2.19.3
|
||||||
- os: ubuntu-latest
|
- os: ubuntu-latest
|
||||||
version: stable-v2.22.1
|
version: stable-v2.22.1
|
||||||
- os: ubuntu-latest
|
- os: ubuntu-latest
|
||||||
|
|||||||
Generated
+1
-1
@@ -39,7 +39,7 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- os: macos-latest-xlarge
|
- os: macos-latest
|
||||||
version: nightly-latest
|
version: nightly-latest
|
||||||
name: Swift analysis using autobuild
|
name: Swift analysis using autobuild
|
||||||
if: github.triggering_actor != 'dependabot[bot]'
|
if: github.triggering_actor != 'dependabot[bot]'
|
||||||
|
|||||||
@@ -9,10 +9,6 @@ on:
|
|||||||
# by other workflows.
|
# by other workflows.
|
||||||
types: [opened, synchronize, reopened, ready_for_review]
|
types: [opened, synchronize, reopened, ready_for_review]
|
||||||
|
|
||||||
concurrency:
|
|
||||||
cancel-in-progress: ${{ github.event_name == 'pull_request' || false }}
|
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
|
||||||
|
|
||||||
defaults:
|
defaults:
|
||||||
run:
|
run:
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
os: [ubuntu-22.04,ubuntu-24.04,windows-2022,windows-2025,macos-14-xlarge,macos-15-xlarge]
|
os: [ubuntu-22.04,ubuntu-24.04,windows-2022,windows-2025,macos-14,macos-15]
|
||||||
tools: ${{ fromJson(needs.check-codeql-versions.outputs.versions) }}
|
tools: ${{ fromJson(needs.check-codeql-versions.outputs.versions) }}
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,13 @@ env:
|
|||||||
# Diff informed queries add an additional query filter which is not yet
|
# Diff informed queries add an additional query filter which is not yet
|
||||||
# taken into account by these tests.
|
# taken into account by these tests.
|
||||||
CODEQL_ACTION_DIFF_INFORMED_QUERIES: false
|
CODEQL_ACTION_DIFF_INFORMED_QUERIES: false
|
||||||
|
# Specify overlay enablement manually to ensure stability around the exclude-from-incremental
|
||||||
|
# query filter. Here we only enable for the default code scanning suite.
|
||||||
|
CODEQL_ACTION_OVERLAY_ANALYSIS: true
|
||||||
|
CODEQL_ACTION_OVERLAY_ANALYSIS_JAVASCRIPT: false
|
||||||
|
CODEQL_ACTION_OVERLAY_ANALYSIS_CODE_SCANNING_JAVASCRIPT: true
|
||||||
|
CODEQL_ACTION_OVERLAY_ANALYSIS_STATUS_CHECK: false
|
||||||
|
CODEQL_ACTION_OVERLAY_ANALYSIS_SKIP_RESOURCE_CHECKS: true
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
@@ -24,10 +31,6 @@ on:
|
|||||||
- cron: '0 5 * * *'
|
- cron: '0 5 * * *'
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
concurrency:
|
|
||||||
cancel-in-progress: ${{ github.event_name == 'pull_request' || false }}
|
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
|
||||||
|
|
||||||
defaults:
|
defaults:
|
||||||
run:
|
run:
|
||||||
shell: bash
|
shell: bash
|
||||||
@@ -76,13 +79,33 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
version: ${{ matrix.version }}
|
version: ${{ matrix.version }}
|
||||||
|
|
||||||
- name: Empty file
|
# On PRs, overlay analysis may change the config that is passed to the CLI.
|
||||||
|
# Therefore, we have two variants of the following test, one for PRs and one for other events.
|
||||||
|
- name: Empty file (non-PR)
|
||||||
|
if: github.event_name != 'pull_request'
|
||||||
uses: ./../action/.github/actions/check-codescanning-config
|
uses: ./../action/.github/actions/check-codescanning-config
|
||||||
with:
|
with:
|
||||||
expected-config-file-contents: "{}"
|
expected-config-file-contents: "{}"
|
||||||
languages: javascript
|
languages: javascript
|
||||||
tools: ${{ steps.prepare-test.outputs.tools-url }}
|
tools: ${{ steps.prepare-test.outputs.tools-url }}
|
||||||
|
|
||||||
|
- name: Empty file (PR)
|
||||||
|
if: github.event_name == 'pull_request'
|
||||||
|
uses: ./../action/.github/actions/check-codescanning-config
|
||||||
|
with:
|
||||||
|
expected-config-file-contents: |
|
||||||
|
{
|
||||||
|
"query-filters": [
|
||||||
|
{
|
||||||
|
"exclude": {
|
||||||
|
"tags": "exclude-from-incremental"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
languages: javascript
|
||||||
|
tools: ${{ steps.prepare-test.outputs.tools-url }}
|
||||||
|
|
||||||
- name: Packs from input
|
- name: Packs from input
|
||||||
if: success() || failure()
|
if: success() || failure()
|
||||||
uses: ./../action/.github/actions/check-codescanning-config
|
uses: ./../action/.github/actions/check-codescanning-config
|
||||||
|
|||||||
@@ -20,10 +20,6 @@ on:
|
|||||||
- cron: '0 5 * * *'
|
- cron: '0 5 * * *'
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
concurrency:
|
|
||||||
cancel-in-progress: ${{ github.event_name == 'pull_request' || false }}
|
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
|
||||||
|
|
||||||
defaults:
|
defaults:
|
||||||
run:
|
run:
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|||||||
@@ -19,10 +19,6 @@ on:
|
|||||||
- cron: '0 5 * * *'
|
- cron: '0 5 * * *'
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
concurrency:
|
|
||||||
cancel-in-progress: ${{ github.event_name == 'pull_request' || false }}
|
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
|
||||||
|
|
||||||
defaults:
|
defaults:
|
||||||
run:
|
run:
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|||||||
@@ -48,9 +48,6 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
fetch-depth: 0 # ensure we have all tags and can push commits
|
fetch-depth: 0 # ensure we have all tags and can push commits
|
||||||
- uses: actions/setup-node@v6
|
- uses: actions/setup-node@v6
|
||||||
with:
|
|
||||||
node-version: 24
|
|
||||||
cache: 'npm'
|
|
||||||
- uses: actions/setup-python@v6
|
- uses: actions/setup-python@v6
|
||||||
with:
|
with:
|
||||||
python-version: '3.12'
|
python-version: '3.12'
|
||||||
@@ -134,7 +131,7 @@ jobs:
|
|||||||
echo "::endgroup::"
|
echo "::endgroup::"
|
||||||
|
|
||||||
- name: Generate token
|
- name: Generate token
|
||||||
uses: actions/create-github-app-token@v3.2.0
|
uses: actions/create-github-app-token@v3.1.1
|
||||||
id: app-token
|
id: app-token
|
||||||
with:
|
with:
|
||||||
app-id: ${{ vars.AUTOMATION_APP_ID }}
|
app-id: ${{ vars.AUTOMATION_APP_ID }}
|
||||||
|
|||||||
+32
-116
@@ -10,10 +10,6 @@ on:
|
|||||||
types: [checks_requested]
|
types: [checks_requested]
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
concurrency:
|
|
||||||
cancel-in-progress: ${{ github.event_name == 'pull_request' || false }}
|
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
|
||||||
|
|
||||||
defaults:
|
defaults:
|
||||||
run:
|
run:
|
||||||
shell: bash
|
shell: bash
|
||||||
@@ -33,10 +29,6 @@ jobs:
|
|||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
timeout-minutes: 45
|
timeout-minutes: 45
|
||||||
|
|
||||||
concurrency:
|
|
||||||
cancel-in-progress: ${{ github.event_name == 'pull_request' || false }}
|
|
||||||
group: pr-checks-unit-tests-${{ github.ref }}-${{ github.event_name }}-${{ matrix.os }}-node${{ matrix['node-version'] }}
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Prepare git (Windows)
|
- name: Prepare git (Windows)
|
||||||
if: runner.os == 'Windows'
|
if: runner.os == 'Windows'
|
||||||
@@ -75,21 +67,22 @@ jobs:
|
|||||||
sarif_file: eslint.sarif
|
sarif_file: eslint.sarif
|
||||||
category: eslint
|
category: eslint
|
||||||
|
|
||||||
# These checks do not need to be run as part of the same matrix that we use for the `unit-tests`
|
# Verifying the PR checks are up-to-date requires Node 24. The PR checks are not dependent
|
||||||
# job.
|
# on the main codebase and therefore do not need to be run as part of the same matrix that
|
||||||
other-checks:
|
# we use for the `unit-tests` job.
|
||||||
name: Other checks
|
verify-pr-checks:
|
||||||
|
name: Verify PR checks
|
||||||
if: github.triggering_actor != 'dependabot[bot]'
|
if: github.triggering_actor != 'dependabot[bot]'
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-slim
|
||||||
timeout-minutes: 10
|
timeout-minutes: 10
|
||||||
|
|
||||||
concurrency:
|
|
||||||
cancel-in-progress: ${{ github.event_name == 'pull_request' || false }}
|
|
||||||
group: pr-checks-pr-checks-${{ github.ref }}-${{ github.event_name }}
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
- name: Prepare git (Windows)
|
||||||
|
if: runner.os == 'Windows'
|
||||||
|
run: git config --global core.autocrlf false
|
||||||
|
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v6
|
uses: actions/checkout@v6
|
||||||
|
|
||||||
@@ -100,22 +93,34 @@ jobs:
|
|||||||
cache: 'npm'
|
cache: 'npm'
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
id: install-deps
|
|
||||||
run: npm ci
|
run: npm ci
|
||||||
|
|
||||||
- name: Verify PR checks up to date
|
- name: Verify PR checks up to date
|
||||||
if: ${{ !cancelled() && steps.install-deps.outcome == 'success' }}
|
if: always()
|
||||||
run: .github/workflows/script/verify-pr-checks.sh
|
run: .github/workflows/script/verify-pr-checks.sh
|
||||||
|
|
||||||
- name: Run pr-checks tests
|
- name: Run pr-checks tests
|
||||||
if: ${{ !cancelled() && steps.install-deps.outcome == 'success' }}
|
if: always()
|
||||||
working-directory: pr-checks
|
working-directory: pr-checks
|
||||||
run: npx tsx --test
|
run: npx tsx --test
|
||||||
|
|
||||||
- name: Verify all Actions use the same Node version
|
check-node-version:
|
||||||
id: head-version
|
if: github.triggering_actor != 'dependabot[bot]'
|
||||||
|
name: Check Action Node versions
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
timeout-minutes: 45
|
||||||
|
env:
|
||||||
|
BASE_REF: ${{ github.base_ref }}
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v6
|
||||||
|
- id: head-version
|
||||||
|
name: Verify all Actions use the same Node version
|
||||||
run: |
|
run: |
|
||||||
NODE_VERSION=$(find . -path "*/node_modules" -prune -o -name "action.yml" -exec yq -o=json '.runs.using' {} \; | jq -rs '[.[] | select(. != null and startswith("node"))] | unique | .[]')
|
NODE_VERSION=$(find . -name "action.yml" -exec yq -e '.runs.using' {} \; | grep node | sort | uniq)
|
||||||
echo "NODE_VERSION: ${NODE_VERSION}"
|
echo "NODE_VERSION: ${NODE_VERSION}"
|
||||||
if [[ $(echo "$NODE_VERSION" | wc -l) -gt 1 ]]; then
|
if [[ $(echo "$NODE_VERSION" | wc -l) -gt 1 ]]; then
|
||||||
echo "::error::More than one node version used in 'action.yml' files."
|
echo "::error::More than one node version used in 'action.yml' files."
|
||||||
@@ -123,111 +128,22 @@ jobs:
|
|||||||
fi
|
fi
|
||||||
echo "node_version=${NODE_VERSION}" >> $GITHUB_OUTPUT
|
echo "node_version=${NODE_VERSION}" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
- name: Fetch base commit
|
- id: checkout-base
|
||||||
id: fetch-base
|
name: 'Backport: Check out base ref'
|
||||||
# Forks and Dependabot PRs don't have permission to write comments, so skip the repo size
|
|
||||||
# check in those cases.
|
|
||||||
if: >-
|
|
||||||
github.event_name == 'pull_request' &&
|
|
||||||
github.event.pull_request.head.repo.full_name == github.repository &&
|
|
||||||
github.event.pull_request.user.login != 'dependabot[bot]'
|
|
||||||
env:
|
|
||||||
BASE_SHA: ${{ github.event.pull_request.base.sha }}
|
|
||||||
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
|
|
||||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
run: |
|
|
||||||
# Compare against the merge base so the size delta reflects only the commits actually
|
|
||||||
# added by this PR, ignoring any changes that have landed on the base branch since the
|
|
||||||
# PR branched off.
|
|
||||||
merge_base=$(gh api "repos/$GITHUB_REPOSITORY/compare/$BASE_SHA...$HEAD_SHA" --jq '.merge_base_commit.sha')
|
|
||||||
echo "merge_base=$merge_base" >> "$GITHUB_OUTPUT"
|
|
||||||
git fetch --no-tags --depth=1 origin "$merge_base" "$HEAD_SHA"
|
|
||||||
|
|
||||||
- name: Check repo size
|
|
||||||
if: steps.fetch-base.outcome == 'success'
|
|
||||||
working-directory: pr-checks
|
|
||||||
env:
|
|
||||||
BASE_REF: ${{ github.event.pull_request.base.ref }}
|
|
||||||
BASE_SHA: ${{ steps.fetch-base.outputs.merge_base }}
|
|
||||||
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
|
|
||||||
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
|
||||||
run: npx tsx check-repo-size.ts --output-dir "$RUNNER_TEMP/repo-size"
|
|
||||||
|
|
||||||
- name: Upload repo size comment
|
|
||||||
if: steps.fetch-base.outcome == 'success'
|
|
||||||
uses: actions/upload-artifact@v7
|
|
||||||
with:
|
|
||||||
name: repo-size-comment
|
|
||||||
path: ${{ runner.temp }}/repo-size/
|
|
||||||
if-no-files-found: error
|
|
||||||
|
|
||||||
- name: 'Backport: Check out base ref'
|
|
||||||
id: checkout-base
|
|
||||||
if: ${{ startsWith(github.head_ref, 'backport-') }}
|
if: ${{ startsWith(github.head_ref, 'backport-') }}
|
||||||
uses: actions/checkout@v6
|
uses: actions/checkout@v6
|
||||||
with:
|
with:
|
||||||
ref: ${{ github.base_ref }}
|
ref: ${{ env.BASE_REF }}
|
||||||
|
|
||||||
- name: 'Backport: Verify Node versions unchanged'
|
- name: 'Backport: Verify Node versions unchanged'
|
||||||
if: steps.checkout-base.outcome == 'success'
|
if: steps.checkout-base.outcome == 'success'
|
||||||
env:
|
env:
|
||||||
HEAD_VERSION: ${{ steps.head-version.outputs.node_version }}
|
HEAD_VERSION: ${{ steps.head-version.outputs.node_version }}
|
||||||
run: |
|
run: |
|
||||||
BASE_VERSION=$(find . -path "*/node_modules" -prune -o -name "action.yml" -exec yq -o=json '.runs.using' {} \; | jq -rs '[.[] | select(. != null and startswith("node"))] | unique | .[]')
|
BASE_VERSION=$(find . -name "action.yml" -exec yq -e '.runs.using' {} \; | grep node | sort | uniq)
|
||||||
echo "HEAD_VERSION: ${HEAD_VERSION}"
|
echo "HEAD_VERSION: ${HEAD_VERSION}"
|
||||||
echo "BASE_VERSION: ${BASE_VERSION}"
|
echo "BASE_VERSION: ${BASE_VERSION}"
|
||||||
if [[ "$BASE_VERSION" != "$HEAD_VERSION" ]]; then
|
if [[ "$BASE_VERSION" != "$HEAD_VERSION" ]]; then
|
||||||
echo "::error::Cannot change the Node version of an Action in a backport PR."
|
echo "::error::Cannot change the Node version of an Action in a backport PR."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
post-repo-size-comment:
|
|
||||||
name: Post repo size comment
|
|
||||||
needs: other-checks
|
|
||||||
# Keep write permissions isolated from the job that checks out and tests PR code. This job only
|
|
||||||
# posts the candidate comment body produced by the read-only `pr-checks` job.
|
|
||||||
if: >-
|
|
||||||
github.event_name == 'pull_request' &&
|
|
||||||
github.event.pull_request.head.repo.full_name == github.repository &&
|
|
||||||
github.event.pull_request.user.login != 'dependabot[bot]' &&
|
|
||||||
needs.other-checks.result == 'success'
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
pull-requests: write
|
|
||||||
runs-on: ubuntu-slim
|
|
||||||
timeout-minutes: 10
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
cancel-in-progress: true
|
|
||||||
group: check-repo-size-${{ github.event.pull_request.number }}
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Download repo size comment
|
|
||||||
uses: actions/download-artifact@v8
|
|
||||||
with:
|
|
||||||
name: repo-size-comment
|
|
||||||
path: repo-size-comment
|
|
||||||
|
|
||||||
- name: Post repo size comment
|
|
||||||
env:
|
|
||||||
COMMENT_MARKER: "<!-- repo-size-diff-bot -->"
|
|
||||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
PR_NUMBER: ${{ github.event.pull_request.number }}
|
|
||||||
run: |
|
|
||||||
significant=$(jq -r '.significant' repo-size-comment/metadata.json)
|
|
||||||
comment_id=$(
|
|
||||||
gh api "repos/$GITHUB_REPOSITORY/issues/$PR_NUMBER/comments" \
|
|
||||||
--paginate \
|
|
||||||
--jq ".[] | select(.body | contains(\"$COMMENT_MARKER\")) | .id" \
|
|
||||||
| head -n 1
|
|
||||||
)
|
|
||||||
|
|
||||||
if [[ -n "$comment_id" ]]; then
|
|
||||||
echo "Updating existing comment $comment_id."
|
|
||||||
gh api --method PATCH "repos/$GITHUB_REPOSITORY/issues/comments/$comment_id" --field body=@repo-size-comment/body.md
|
|
||||||
elif [[ "$significant" == "true" ]]; then
|
|
||||||
echo "Creating new repo size comment."
|
|
||||||
gh api --method POST "repos/$GITHUB_REPOSITORY/issues/$PR_NUMBER/comments" --field body=@repo-size-comment/body.md
|
|
||||||
else
|
|
||||||
echo "Skipping repo size comment because the delta is below the threshold and no sticky comment exists."
|
|
||||||
fi
|
|
||||||
|
|||||||
@@ -14,10 +14,6 @@ on:
|
|||||||
- cron: '0 0 * * 1'
|
- cron: '0 0 * * 1'
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
concurrency:
|
|
||||||
cancel-in-progress: ${{ github.event_name == 'pull_request' || false }}
|
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
|
||||||
|
|
||||||
defaults:
|
defaults:
|
||||||
run:
|
run:
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|||||||
@@ -17,10 +17,6 @@ on:
|
|||||||
- cron: '0 5 * * *'
|
- cron: '0 5 * * *'
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
concurrency:
|
|
||||||
cancel-in-progress: ${{ github.event_name == 'pull_request' || false }}
|
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
|
||||||
|
|
||||||
defaults:
|
defaults:
|
||||||
run:
|
run:
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|||||||
@@ -136,7 +136,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Generate token
|
- name: Generate token
|
||||||
if: github.event_name == 'workflow_dispatch'
|
if: github.event_name == 'workflow_dispatch'
|
||||||
uses: actions/create-github-app-token@v3.2.0
|
uses: actions/create-github-app-token@v3.1.1
|
||||||
id: app-token
|
id: app-token
|
||||||
with:
|
with:
|
||||||
app-id: ${{ vars.AUTOMATION_APP_ID }}
|
app-id: ${{ vars.AUTOMATION_APP_ID }}
|
||||||
|
|||||||
@@ -18,11 +18,6 @@ on:
|
|||||||
schedule:
|
schedule:
|
||||||
- cron: '0 5 * * *'
|
- cron: '0 5 * * *'
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
concurrency:
|
|
||||||
cancel-in-progress: ${{ github.event_name == 'pull_request' || false }}
|
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
|
||||||
|
|
||||||
defaults:
|
defaults:
|
||||||
run:
|
run:
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|||||||
@@ -64,12 +64,11 @@ jobs:
|
|||||||
|
|
||||||
- name: Update current release branch
|
- name: Update current release branch
|
||||||
if: github.event_name == 'workflow_dispatch'
|
if: github.event_name == 'workflow_dispatch'
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
run: |
|
run: |
|
||||||
echo SOURCE_BRANCH=${REF_NAME}
|
echo SOURCE_BRANCH=${REF_NAME}
|
||||||
echo TARGET_BRANCH=releases/${MAJOR_VERSION}
|
echo TARGET_BRANCH=releases/${MAJOR_VERSION}
|
||||||
python .github/update-release-branch.py \
|
python .github/update-release-branch.py \
|
||||||
|
--github-token ${{ secrets.GITHUB_TOKEN }} \
|
||||||
--repository-nwo ${{ github.repository }} \
|
--repository-nwo ${{ github.repository }} \
|
||||||
--source-branch '${{ env.REF_NAME }}' \
|
--source-branch '${{ env.REF_NAME }}' \
|
||||||
--target-branch 'releases/${{ env.MAJOR_VERSION }}' \
|
--target-branch 'releases/${{ env.MAJOR_VERSION }}' \
|
||||||
@@ -94,7 +93,7 @@ jobs:
|
|||||||
pull-requests: write # needed to create pull request
|
pull-requests: write # needed to create pull request
|
||||||
steps:
|
steps:
|
||||||
- name: Generate token
|
- name: Generate token
|
||||||
uses: actions/create-github-app-token@v3.2.0
|
uses: actions/create-github-app-token@v3.1.1
|
||||||
id: app-token
|
id: app-token
|
||||||
with:
|
with:
|
||||||
app-id: ${{ vars.AUTOMATION_APP_ID }}
|
app-id: ${{ vars.AUTOMATION_APP_ID }}
|
||||||
@@ -108,12 +107,11 @@ jobs:
|
|||||||
- uses: ./.github/actions/release-initialise
|
- uses: ./.github/actions/release-initialise
|
||||||
|
|
||||||
- name: Update older release branch
|
- name: Update older release branch
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
run: |
|
run: |
|
||||||
echo SOURCE_BRANCH=${SOURCE_BRANCH}
|
echo SOURCE_BRANCH=${SOURCE_BRANCH}
|
||||||
echo TARGET_BRANCH=${TARGET_BRANCH}
|
echo TARGET_BRANCH=${TARGET_BRANCH}
|
||||||
python .github/update-release-branch.py \
|
python .github/update-release-branch.py \
|
||||||
|
--github-token ${{ secrets.GITHUB_TOKEN }} \
|
||||||
--repository-nwo ${{ github.repository }} \
|
--repository-nwo ${{ github.repository }} \
|
||||||
--source-branch ${SOURCE_BRANCH} \
|
--source-branch ${SOURCE_BRANCH} \
|
||||||
--target-branch ${TARGET_BRANCH} \
|
--target-branch ${TARGET_BRANCH} \
|
||||||
|
|||||||
Vendored
+1
-1
@@ -19,7 +19,7 @@
|
|||||||
"scope": "javascript, typescript",
|
"scope": "javascript, typescript",
|
||||||
"prefix": "testMacro",
|
"prefix": "testMacro",
|
||||||
"body": [
|
"body": [
|
||||||
"const ${1:nameMacro} = makeMacro({",
|
"const ${1:nameMacro} = test.macro({",
|
||||||
" exec: async (t: ExecutionContext<unknown>) => {},",
|
" exec: async (t: ExecutionContext<unknown>) => {},",
|
||||||
"",
|
"",
|
||||||
" title: (providedTitle = \"\") => `${2:common title} - \\${providedTitle}`,",
|
" title: (providedTitle = \"\") => `${2:common title} - \\${providedTitle}`,",
|
||||||
|
|||||||
@@ -6,23 +6,6 @@ See the [releases page](https://github.com/github/codeql-action/releases) for th
|
|||||||
|
|
||||||
No user facing changes.
|
No user facing changes.
|
||||||
|
|
||||||
## 4.36.0 - 22 May 2026
|
|
||||||
|
|
||||||
- _Breaking change_: Bump the minimum required CodeQL bundle version to 2.19.4. [#3894](https://github.com/github/codeql-action/pull/3894)
|
|
||||||
- Add support for SHA-256 Git object IDs. [#3893](https://github.com/github/codeql-action/pull/3893)
|
|
||||||
- Update default CodeQL bundle version to [2.25.5](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.25.5). [#3926](https://github.com/github/codeql-action/pull/3926)
|
|
||||||
|
|
||||||
## 4.35.5 - 15 May 2026
|
|
||||||
|
|
||||||
- We have improved how the JavaScript bundles for the CodeQL Action are generated to avoid duplication across bundles and reduce the size of the repository by around 70%. This should have no effect on the runtime behaviour of the CodeQL Action. [#3899](https://github.com/github/codeql-action/pull/3899)
|
|
||||||
- For performance and accuracy reasons, [improved incremental analysis](https://github.com/github/roadmap/issues/1158) will now only be enabled on a pull request when diff-informed analysis is also enabled for that run. If diff-informed analysis is unavailable (for example, because the PR diff ranges could not be computed), the action will fall back to a full analysis. [#3791](https://github.com/github/codeql-action/pull/3791)
|
|
||||||
- If multiple inputs are provided for the GitHub-internal `analysis-kinds` input, only `code-scanning` will be enabled. The `analysis-kinds` input is experimental, for GitHub-internal use only, and may change without notice at any time. [#3892](https://github.com/github/codeql-action/pull/3892)
|
|
||||||
- Added an experimental change which, when running a Code Scanning analysis for a PR with [improved incremental analysis](https://github.com/github/roadmap/issues/1158) enabled, prefers CodeQL CLI versions that have a cached overlay-base database for the configured languages. This speeds up analysis for a repository when there is not yet a cached overlay-base database for the latest CLI version. We expect to roll this change out to everyone in May. [#3880](https://github.com/github/codeql-action/pull/3880)
|
|
||||||
|
|
||||||
## 4.35.4 - 07 May 2026
|
|
||||||
|
|
||||||
- Update default CodeQL bundle version to [2.25.4](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.25.4). [#3881](https://github.com/github/codeql-action/pull/3881)
|
|
||||||
|
|
||||||
## 4.35.3 - 01 May 2026
|
## 4.35.3 - 01 May 2026
|
||||||
|
|
||||||
- _Upcoming breaking change_: Add a deprecation warning for customers using CodeQL version 2.19.3 and earlier. These versions of CodeQL were discontinued on 9 April 2026 alongside GitHub Enterprise Server 3.15, and will be unsupported by the next minor release of the CodeQL Action. [#3837](https://github.com/github/codeql-action/pull/3837)
|
- _Upcoming breaking change_: Add a deprecation warning for customers using CodeQL version 2.19.3 and earlier. These versions of CodeQL were discontinued on 9 April 2026 alongside GitHub Enterprise Server 3.15, and will be unsupported by the next minor release of the CodeQL Action. [#3837](https://github.com/github/codeql-action/pull/3837)
|
||||||
|
|||||||
+1
-1
@@ -71,7 +71,7 @@ Once the mergeback and backport pull request have been merged, the release is co
|
|||||||
|
|
||||||
Since the `codeql-action` runs most of its testing through individual Actions workflows, there are over two hundred required jobs that need to pass in order for a PR to turn green. It would be too tedious to maintain that list manually. You can regenerate the set of required checks automatically by running the [sync-checks.ts](pr-checks/sync-checks.ts) script:
|
Since the `codeql-action` runs most of its testing through individual Actions workflows, there are over two hundred required jobs that need to pass in order for a PR to turn green. It would be too tedious to maintain that list manually. You can regenerate the set of required checks automatically by running the [sync-checks.ts](pr-checks/sync-checks.ts) script:
|
||||||
|
|
||||||
- At a minimum, you must provide a token with permissions to update branch protection rules. For example, `gh auth token | pr-checks/sync-checks.ts --token-stdin` uses the same token that `gh` uses. You can also set the `GH_TOKEN` or `GITHUB_TOKEN` environment variable. If no token is provided or the token has insufficient permissions, the script will fail.
|
- At a minimum, you must provide an argument for the `--token` input. For example, `--token "$(gh auth token)"` to use the same token that `gh` uses. If no token is provided or the token has insufficient permissions, the script will fail.
|
||||||
- By default, the script performs a dry run and outputs information about the changes it would make to the branch protection rules. To actually apply the changes, specify the `--apply` flag.
|
- By default, the script performs a dry run and outputs information about the changes it would make to the branch protection rules. To actually apply the changes, specify the `--apply` flag.
|
||||||
- If you run the script without any other arguments, it will retrieve the set of workflows that ran for the latest commit on `main`.
|
- If you run the script without any other arguments, it will retrieve the set of workflows that ran for the latest commit on `main`.
|
||||||
- You can specify a different git ref with the `--ref` input. You will likely want to use this if you have a PR that removes or adds PR checks. For example, `--ref "some/branch/name"` to use the HEAD of the `some/branch/name` branch.
|
- You can specify a different git ref with the `--ref` input. You will likely want to use this if you have a PR that removes or adds PR checks. For example, `--ref "some/branch/name"` to use the HEAD of the `some/branch/name` branch.
|
||||||
|
|||||||
@@ -78,6 +78,8 @@ We typically release new minor versions of the CodeQL Action and Bundle when a n
|
|||||||
| `v3.28.21` | `2.21.3` | Enterprise Server 3.18 | |
|
| `v3.28.21` | `2.21.3` | Enterprise Server 3.18 | |
|
||||||
| `v3.28.12` | `2.20.7` | Enterprise Server 3.17 | |
|
| `v3.28.12` | `2.20.7` | Enterprise Server 3.17 | |
|
||||||
| `v3.28.6` | `2.20.3` | Enterprise Server 3.16 | |
|
| `v3.28.6` | `2.20.3` | Enterprise Server 3.16 | |
|
||||||
|
| `v3.28.6` | `2.20.3` | Enterprise Server 3.15 | |
|
||||||
|
| `v3.28.6` | `2.20.3` | Enterprise Server 3.14 | |
|
||||||
|
|
||||||
See the full list of GHES release and deprecation dates at [GitHub Enterprise Server releases](https://docs.github.com/en/enterprise-server/admin/all-releases#releases-of-github-enterprise-server).
|
See the full list of GHES release and deprecation dates at [GitHub Enterprise Server releases](https://docs.github.com/en/enterprise-server/admin/all-releases#releases-of-github-enterprise-server).
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -95,5 +95,5 @@ outputs:
|
|||||||
description: The ID of the uploaded SARIF file.
|
description: The ID of the uploaded SARIF file.
|
||||||
runs:
|
runs:
|
||||||
using: node24
|
using: node24
|
||||||
main: "../lib/analyze-entry.js"
|
main: "../lib/analyze-action.js"
|
||||||
post: "../lib/analyze-post-entry.js"
|
post: "../lib/analyze-action-post.js"
|
||||||
|
|||||||
@@ -16,4 +16,4 @@ inputs:
|
|||||||
required: false
|
required: false
|
||||||
runs:
|
runs:
|
||||||
using: node24
|
using: node24
|
||||||
main: '../lib/autobuild-entry.js'
|
main: '../lib/autobuild-action.js'
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { copyFile, readFile, rm, writeFile } from "node:fs/promises";
|
import { copyFile, rm, writeFile } from "node:fs/promises";
|
||||||
import { basename, dirname, join } from "node:path";
|
import { dirname, join } from "node:path";
|
||||||
import { fileURLToPath } from "node:url";
|
import { fileURLToPath } from "node:url";
|
||||||
|
|
||||||
import * as esbuild from "esbuild";
|
import * as esbuild from "esbuild";
|
||||||
@@ -62,153 +62,18 @@ const onEndPlugin = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
/** The name of the virtual `entry-points` module. */
|
|
||||||
const SHARED_ENTRYPOINT = "entry-points";
|
|
||||||
|
|
||||||
/** The property name under which `upload-lib`'s namespace is exposed in `entry-points`. */
|
|
||||||
const UPLOAD_LIB_EXPORT = "uploadLib";
|
|
||||||
|
|
||||||
/** The relative source path of the `upload-lib` module that we re-export from `entry-points`. */
|
|
||||||
const UPLOAD_LIB_SRC = "./src/upload-lib";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This plugin finds all source files that contain Action entry points. It then generates the
|
|
||||||
* virtual `entry-points` module which imports all identified files, and re-exports their
|
|
||||||
* `runWrapper` functions with suitable aliases.
|
|
||||||
*
|
|
||||||
* The virtual module additionally re-exports `upload-lib` under the `uploadLib` namespace so that
|
|
||||||
* external consumers can access it via the small `lib/upload-lib.js` stub emitted below.
|
|
||||||
*
|
|
||||||
* A tiny stub file is emitted for each Action entrypoint, and one for `upload-lib`. Each stub
|
|
||||||
* imports the shared bundle and calls/re-exports from the respective entry point.
|
|
||||||
*
|
|
||||||
* @type {esbuild.Plugin}
|
|
||||||
*/
|
|
||||||
const entryPointsPlugin = {
|
|
||||||
name: "entry-points",
|
|
||||||
setup(build) {
|
|
||||||
const namespace = "actions";
|
|
||||||
const actions = [];
|
|
||||||
|
|
||||||
const toPascal = (s) =>
|
|
||||||
s.replace(/(^|-)([a-z0-9])/gi, (_, __, c) => c.toUpperCase());
|
|
||||||
|
|
||||||
// Find the source files containing Action entry points.
|
|
||||||
build.onStart(() => {
|
|
||||||
const actionFiles = globSync("src/*-action{,-post}.ts");
|
|
||||||
for (const actionFile of actionFiles) {
|
|
||||||
const match = basename(actionFile).match(/(.*)-action(-post)?/);
|
|
||||||
|
|
||||||
if (match.length < 2) {
|
|
||||||
throw new Error(`'${actionFile}' didn't match expected pattern.`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const actionName = match[1];
|
|
||||||
const isPost = match[2] !== undefined;
|
|
||||||
|
|
||||||
actions.push({
|
|
||||||
path: actionFile,
|
|
||||||
name: actionName,
|
|
||||||
isPost,
|
|
||||||
pascalCaseName: `${toPascal(actionName)}${isPost ? "Post" : ""}Action`,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Resolve the virtual `entry-points` file and set the corresponding namespace.
|
|
||||||
// Ideally, we'd `RegExp.escape` the entrypoint here, but that API isn't supported in Node 20.
|
|
||||||
// Since we're dealing with a hardcoded string, this isn't too much of a problem.
|
|
||||||
build.onResolve({ filter: new RegExp(`^${SHARED_ENTRYPOINT}$`) }, () => {
|
|
||||||
return { path: SHARED_ENTRYPOINT, namespace };
|
|
||||||
});
|
|
||||||
|
|
||||||
// Generate the virtual `entry-points` file based on the Actions we discovered.
|
|
||||||
// Restrict using the namespace. The path filter does not need to discriminate any further.
|
|
||||||
build.onLoad({ filter: /.*/, namespace }, async () => {
|
|
||||||
const wrapperTemplatePath = "entry-wrapper.js.tpl";
|
|
||||||
const wrapperTemplate = await readFile(
|
|
||||||
join(SRC_DIR, wrapperTemplatePath),
|
|
||||||
"utf-8",
|
|
||||||
);
|
|
||||||
|
|
||||||
const actionsSorted = actions.sort((a, b) =>
|
|
||||||
a.name.localeCompare(b.name),
|
|
||||||
);
|
|
||||||
const imports = actionsSorted
|
|
||||||
.map(
|
|
||||||
(action) =>
|
|
||||||
`import * as ${action.pascalCaseName} from "./src/${basename(action.path)}";`,
|
|
||||||
)
|
|
||||||
.join("\n");
|
|
||||||
const wrappers = actionsSorted
|
|
||||||
.map((action) =>
|
|
||||||
wrapperTemplate.replaceAll("__ACTION__", action.pascalCaseName),
|
|
||||||
)
|
|
||||||
.join("\n\n");
|
|
||||||
|
|
||||||
// Also re-export the `upload-lib` namespace so that external consumers can reach it
|
|
||||||
// via the `lib/upload-lib.js` stub without us having to bundle a second copy.
|
|
||||||
const uploadLibReExport = `export * as ${UPLOAD_LIB_EXPORT} from "${UPLOAD_LIB_SRC}";`;
|
|
||||||
|
|
||||||
return {
|
|
||||||
contents: `"use strict";\n${imports}\n\n${uploadLibReExport}\n\n${wrappers}\n`,
|
|
||||||
resolveDir: ".",
|
|
||||||
loader: "ts",
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
// Emit entry point stubs for each Action using the entry template.
|
|
||||||
build.onEnd(async () => {
|
|
||||||
const makeHeader = (templatePath, sourceFile) =>
|
|
||||||
`// Automatically generated from '${templatePath}' for 'src/${basename(sourceFile)}'.\n\n`;
|
|
||||||
|
|
||||||
// Read the entry point template.
|
|
||||||
const actionTemplatePath = "action-entry.js.tpl";
|
|
||||||
const actionTemplate = await readFile(
|
|
||||||
join(SRC_DIR, actionTemplatePath),
|
|
||||||
"utf-8",
|
|
||||||
);
|
|
||||||
|
|
||||||
// Write entry point stubs for each Action.
|
|
||||||
for (const action of actions) {
|
|
||||||
await writeFile(
|
|
||||||
join(
|
|
||||||
OUT_DIR,
|
|
||||||
`${action.name}${action.isPost ? "-post" : ""}-entry.js`,
|
|
||||||
),
|
|
||||||
makeHeader(actionTemplatePath, action.path) +
|
|
||||||
actionTemplate.replaceAll("__ACTION__", action.pascalCaseName),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write a small stub for `upload-lib` that re-exports it from the shared bundle.
|
|
||||||
// External callers (e.g. internal testing environments) `require("./lib/upload-lib")`
|
|
||||||
// and expect the same shape as before, so we expose the namespace as `module.exports`.
|
|
||||||
const uploadLibStubTemplatePath = "upload-lib-stub.js.tpl";
|
|
||||||
const uploadLibStubTemplate = await readFile(
|
|
||||||
join(SRC_DIR, uploadLibStubTemplatePath),
|
|
||||||
"utf-8",
|
|
||||||
);
|
|
||||||
await writeFile(
|
|
||||||
join(OUT_DIR, "upload-lib.js"),
|
|
||||||
makeHeader(uploadLibStubTemplatePath, `${UPLOAD_LIB_SRC}.ts`) +
|
|
||||||
uploadLibStubTemplate.replaceAll(
|
|
||||||
"__UPLOAD_LIB_EXPORT__",
|
|
||||||
UPLOAD_LIB_EXPORT,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const context = await esbuild.context({
|
const context = await esbuild.context({
|
||||||
entryPoints: [{ in: SHARED_ENTRYPOINT, out: SHARED_ENTRYPOINT }],
|
// Include upload-lib.ts as an entry point for use in testing environments.
|
||||||
|
entryPoints: globSync([
|
||||||
|
`${SRC_DIR}/*-action.ts`,
|
||||||
|
`${SRC_DIR}/*-action-post.ts`,
|
||||||
|
"src/upload-lib.ts",
|
||||||
|
]),
|
||||||
bundle: true,
|
bundle: true,
|
||||||
format: "cjs",
|
format: "cjs",
|
||||||
outdir: OUT_DIR,
|
outdir: OUT_DIR,
|
||||||
platform: "node",
|
platform: "node",
|
||||||
external: ["./entry-points"],
|
plugins: [cleanPlugin, copyDefaultsPlugin, onEndPlugin],
|
||||||
plugins: [cleanPlugin, copyDefaultsPlugin, entryPointsPlugin, onEndPlugin],
|
|
||||||
target: ["node20"],
|
target: ["node20"],
|
||||||
define: {
|
define: {
|
||||||
__CODEQL_ACTION_VERSION__: JSON.stringify(pkg.version),
|
__CODEQL_ACTION_VERSION__: JSON.stringify(pkg.version),
|
||||||
|
|||||||
@@ -140,18 +140,6 @@ export default [
|
|||||||
"no-async-foreach/no-async-foreach": "error",
|
"no-async-foreach/no-async-foreach": "error",
|
||||||
"no-sequences": "error",
|
"no-sequences": "error",
|
||||||
"no-shadow": "off",
|
"no-shadow": "off",
|
||||||
|
|
||||||
// A basic check that we don't use `exportVariable` from `@actions/core`. This rule depends on
|
|
||||||
// the module being imported as `core`, but that is a good enough check for us.
|
|
||||||
"no-restricted-syntax": [
|
|
||||||
"error",
|
|
||||||
{
|
|
||||||
selector:
|
|
||||||
"MemberExpression[object.name='core'][property.name='exportVariable']",
|
|
||||||
message: "Use `exportVariable` from `environment.ts` instead.",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
|
|
||||||
// This is overly restrictive with unsetting `EnvVar`s
|
// This is overly restrictive with unsetting `EnvVar`s
|
||||||
"@typescript-eslint/no-dynamic-delete": "off",
|
"@typescript-eslint/no-dynamic-delete": "off",
|
||||||
"@typescript-eslint/no-shadow": "error",
|
"@typescript-eslint/no-shadow": "error",
|
||||||
@@ -169,15 +157,6 @@ export default [
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
files: ["src/environment.ts"],
|
|
||||||
|
|
||||||
// We allow `exportVariable` from `@actions/core` to be used in this file
|
|
||||||
// since it defines the wrapper around it that other modules use.
|
|
||||||
rules: {
|
|
||||||
"no-restricted-syntax": "off",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
files: ["**/*.ts", "**/*.js"],
|
files: ["**/*.ts", "**/*.js"],
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -171,5 +171,5 @@ outputs:
|
|||||||
description: The version of the CodeQL binary used for analysis
|
description: The version of the CodeQL binary used for analysis
|
||||||
runs:
|
runs:
|
||||||
using: node24
|
using: node24
|
||||||
main: '../lib/init-entry.js'
|
main: '../lib/init-action.js'
|
||||||
post: '../lib/init-post-entry.js'
|
post: '../lib/init-action-post.js'
|
||||||
|
|||||||
Generated
+164097
File diff suppressed because one or more lines are too long
Generated
+114006
File diff suppressed because one or more lines are too long
Generated
-6
@@ -1,6 +0,0 @@
|
|||||||
// Automatically generated from 'action-entry.js.tpl' for 'src/analyze-action.ts'.
|
|
||||||
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
const import_entry_points = require("./entry-points");
|
|
||||||
void (0, import_entry_points.runAnalyzeAction)();
|
|
||||||
Generated
-6
@@ -1,6 +0,0 @@
|
|||||||
// Automatically generated from 'action-entry.js.tpl' for 'src/analyze-action-post.ts'.
|
|
||||||
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
const import_entry_points = require("./entry-points");
|
|
||||||
void (0, import_entry_points.runAnalyzePostAction)();
|
|
||||||
Generated
+106399
File diff suppressed because one or more lines are too long
Generated
-6
@@ -1,6 +0,0 @@
|
|||||||
// Automatically generated from 'action-entry.js.tpl' for 'src/autobuild-action.ts'.
|
|
||||||
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
const import_entry_points = require("./entry-points");
|
|
||||||
void (0, import_entry_points.runAutobuildAction)();
|
|
||||||
+4
-4
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"bundleVersion": "codeql-bundle-v2.25.5",
|
"bundleVersion": "codeql-bundle-v2.25.3",
|
||||||
"cliVersion": "2.25.5",
|
"cliVersion": "2.25.3",
|
||||||
"priorBundleVersion": "codeql-bundle-v2.25.4",
|
"priorBundleVersion": "codeql-bundle-v2.25.2",
|
||||||
"priorCliVersion": "2.25.4"
|
"priorCliVersion": "2.25.2"
|
||||||
}
|
}
|
||||||
|
|||||||
+80559
-70316
File diff suppressed because one or more lines are too long
Generated
+110989
File diff suppressed because one or more lines are too long
Generated
-6
@@ -1,6 +0,0 @@
|
|||||||
// Automatically generated from 'action-entry.js.tpl' for 'src/init-action.ts'.
|
|
||||||
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
const import_entry_points = require("./entry-points");
|
|
||||||
void (0, import_entry_points.runInitAction)();
|
|
||||||
Generated
-6
@@ -1,6 +0,0 @@
|
|||||||
// Automatically generated from 'action-entry.js.tpl' for 'src/init-action-post.ts'.
|
|
||||||
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
const import_entry_points = require("./entry-points");
|
|
||||||
void (0, import_entry_points.runInitPostAction)();
|
|
||||||
Generated
+105958
File diff suppressed because one or more lines are too long
Generated
-6
@@ -1,6 +0,0 @@
|
|||||||
// Automatically generated from 'action-entry.js.tpl' for 'src/resolve-environment-action.ts'.
|
|
||||||
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
const import_entry_points = require("./entry-points");
|
|
||||||
void (0, import_entry_points.runResolveEnvironmentAction)();
|
|
||||||
Generated
+107467
File diff suppressed because one or more lines are too long
Generated
-6
@@ -1,6 +0,0 @@
|
|||||||
// Automatically generated from 'action-entry.js.tpl' for 'src/setup-codeql-action.ts'.
|
|
||||||
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
const import_entry_points = require("./entry-points");
|
|
||||||
void (0, import_entry_points.runSetupCodeqlAction)();
|
|
||||||
Generated
+162909
File diff suppressed because one or more lines are too long
Generated
+123219
File diff suppressed because one or more lines are too long
Generated
-6
@@ -1,6 +0,0 @@
|
|||||||
// Automatically generated from 'action-entry.js.tpl' for 'src/start-proxy-action.ts'.
|
|
||||||
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
const import_entry_points = require("./entry-points");
|
|
||||||
void (0, import_entry_points.runStartProxyAction)();
|
|
||||||
Generated
-6
@@ -1,6 +0,0 @@
|
|||||||
// Automatically generated from 'action-entry.js.tpl' for 'src/start-proxy-action-post.ts'.
|
|
||||||
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
const import_entry_points = require("./entry-points");
|
|
||||||
void (0, import_entry_points.runStartProxyPostAction)();
|
|
||||||
Generated
+111670
-3
File diff suppressed because one or more lines are too long
Generated
+162934
File diff suppressed because one or more lines are too long
Generated
+112357
File diff suppressed because one or more lines are too long
Generated
-6
@@ -1,6 +0,0 @@
|
|||||||
// Automatically generated from 'action-entry.js.tpl' for 'src/upload-sarif-action.ts'.
|
|
||||||
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
const import_entry_points = require("./entry-points");
|
|
||||||
void (0, import_entry_points.runUploadSarifAction)();
|
|
||||||
Generated
-6
@@ -1,6 +0,0 @@
|
|||||||
// Automatically generated from 'action-entry.js.tpl' for 'src/upload-sarif-action-post.ts'.
|
|
||||||
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
const import_entry_points = require("./entry-points");
|
|
||||||
void (0, import_entry_points.runUploadSarifPostAction)();
|
|
||||||
Generated
+474
-363
File diff suppressed because it is too large
Load Diff
+13
-14
@@ -1,19 +1,18 @@
|
|||||||
{
|
{
|
||||||
"name": "codeql",
|
"name": "codeql",
|
||||||
"version": "4.36.1",
|
"version": "4.35.4",
|
||||||
"private": true,
|
"private": true,
|
||||||
"description": "CodeQL action",
|
"description": "CodeQL action",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"_build_comment": "echo 'Run the full build so we typecheck the project and can reuse the transpiled files in npm test'",
|
"_build_comment": "echo 'Run the full build so we typecheck the project and can reuse the transpiled files in npm test'",
|
||||||
"build": "./scripts/check-node-modules.sh && npm run transpile && node build.mjs",
|
"build": "./scripts/check-node-modules.sh && npm run transpile && node build.mjs && npx tsx ./pr-checks/bundle-metadata.ts",
|
||||||
"lint": "eslint --report-unused-disable-directives --max-warnings=0 .",
|
"lint": "eslint --report-unused-disable-directives --max-warnings=0 .",
|
||||||
"lint-ci": "SARIF_ESLINT_IGNORE_SUPPRESSED=true eslint --report-unused-disable-directives --max-warnings=0 . --format @microsoft/eslint-formatter-sarif --output-file=eslint.sarif",
|
"lint-ci": "SARIF_ESLINT_IGNORE_SUPPRESSED=true eslint --report-unused-disable-directives --max-warnings=0 . --format @microsoft/eslint-formatter-sarif --output-file=eslint.sarif",
|
||||||
"lint-fix": "eslint --report-unused-disable-directives --max-warnings=0 . --fix",
|
"lint-fix": "eslint --report-unused-disable-directives --max-warnings=0 . --fix",
|
||||||
"ava": "npm run transpile && ava --verbose",
|
"ava": "npm run transpile && ava --verbose",
|
||||||
"test": "npm run ava -- src/",
|
"test": "npm run ava -- src/",
|
||||||
"test-debug": "npm run test -- --timeout=20m",
|
"test-debug": "npm run test -- --timeout=20m",
|
||||||
"transpile": "tsc --build --verbose tsconfig.json",
|
"transpile": "tsc --build --verbose tsconfig.json"
|
||||||
"update-pr-checks": "./pr-checks/sync.sh"
|
|
||||||
},
|
},
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"workspaces": [
|
"workspaces": [
|
||||||
@@ -44,32 +43,32 @@
|
|||||||
"uuid": "^14.0.0"
|
"uuid": "^14.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@ava/typescript": "6.0.0",
|
"@ava/typescript": "7.0.0",
|
||||||
"@eslint/compat": "^2.0.5",
|
"@eslint/compat": "^2.0.5",
|
||||||
"@microsoft/eslint-formatter-sarif": "^3.1.0",
|
"@microsoft/eslint-formatter-sarif": "^3.1.0",
|
||||||
"@octokit/types": "^16.0.0",
|
"@octokit/types": "^16.0.0",
|
||||||
"@types/archiver": "^7.0.0",
|
"@types/archiver": "^7.0.0",
|
||||||
"@types/follow-redirects": "^1.14.4",
|
"@types/follow-redirects": "^1.14.4",
|
||||||
"@types/js-yaml": "^4.0.9",
|
"@types/js-yaml": "^4.0.9",
|
||||||
"@types/node": "^20.19.39",
|
"@types/node": "^20.19.9",
|
||||||
"@types/node-forge": "^1.3.14",
|
"@types/node-forge": "^1.3.14",
|
||||||
"@types/sarif": "^2.1.7",
|
"@types/sarif": "^2.1.7",
|
||||||
"@types/semver": "^7.7.1",
|
"@types/semver": "^7.7.1",
|
||||||
"@types/sinon": "^21.0.1",
|
"@types/sinon": "^21.0.1",
|
||||||
"ava": "^6.4.1",
|
"ava": "^7.0.0",
|
||||||
"esbuild": "^0.28.0",
|
"esbuild": "^0.28.0",
|
||||||
"eslint": "^9.39.4",
|
"eslint": "^9.39.2",
|
||||||
"eslint-import-resolver-typescript": "^4.4.4",
|
"eslint-import-resolver-typescript": "^4.4.4",
|
||||||
"eslint-plugin-github": "^6.0.0",
|
"eslint-plugin-github": "^6.0.0",
|
||||||
"eslint-plugin-import-x": "^4.16.2",
|
"eslint-plugin-import-x": "^4.16.2",
|
||||||
"eslint-plugin-jsdoc": "^62.9.0",
|
"eslint-plugin-jsdoc": "^62.9.0",
|
||||||
"eslint-plugin-no-async-foreach": "^0.1.1",
|
"eslint-plugin-no-async-foreach": "^0.1.1",
|
||||||
"glob": "^11.1.0",
|
"glob": "^11.1.0",
|
||||||
"globals": "^17.6.0",
|
"globals": "^17.5.0",
|
||||||
"nock": "^14.0.12",
|
"nock": "^14.0.12",
|
||||||
"sinon": "^22.0.0",
|
"sinon": "^21.1.2",
|
||||||
"typescript": "^6.0.3",
|
"typescript": "^6.0.2",
|
||||||
"typescript-eslint": "^8.59.2"
|
"typescript-eslint": "^8.58.2"
|
||||||
},
|
},
|
||||||
"overrides": {
|
"overrides": {
|
||||||
"@actions/tool-cache": {
|
"@actions/tool-cache": {
|
||||||
@@ -90,7 +89,7 @@
|
|||||||
"eslint-plugin-jsx-a11y": {
|
"eslint-plugin-jsx-a11y": {
|
||||||
"semver": ">=6.3.1"
|
"semver": ">=6.3.1"
|
||||||
},
|
},
|
||||||
"glob": "^11.1.0",
|
"brace-expansion@2.0.1": "2.0.2",
|
||||||
"undici": "^6.24.0"
|
"glob": "^11.1.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,259 +0,0 @@
|
|||||||
#!/usr/bin/env npx tsx
|
|
||||||
|
|
||||||
/*
|
|
||||||
Tests for check-repo-size.ts.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import * as assert from "node:assert/strict";
|
|
||||||
import { execFileSync } from "node:child_process";
|
|
||||||
import { randomBytes } from "node:crypto";
|
|
||||||
import * as fs from "node:fs";
|
|
||||||
import * as os from "node:os";
|
|
||||||
import * as path from "node:path";
|
|
||||||
import { afterEach, beforeEach, describe, it } from "node:test";
|
|
||||||
|
|
||||||
import {
|
|
||||||
COMMENT_MARKER,
|
|
||||||
DEFAULT_BASE_REF,
|
|
||||||
buildCommentBody,
|
|
||||||
formatBytes,
|
|
||||||
formatPercent,
|
|
||||||
isDeltaSignificant,
|
|
||||||
measureArchiveSize,
|
|
||||||
readArgs,
|
|
||||||
} from "./check-repo-size";
|
|
||||||
|
|
||||||
describe("formatBytes", async () => {
|
|
||||||
const cases: Array<[number, boolean, string]> = [
|
|
||||||
// Unsigned values, including sub-KiB amounts which round to 0.00.
|
|
||||||
[0, false, "0.00 KiB"],
|
|
||||||
[512, false, "0.50 KiB"],
|
|
||||||
[1024, false, "1.00 KiB"],
|
|
||||||
[1024 * 1024, false, "1024.00 KiB"],
|
|
||||||
[2 * 1024 * 1024, false, "2048.00 KiB"],
|
|
||||||
// Negative values always use a leading minus.
|
|
||||||
[-2 * 1024 * 1024, false, "-2048.00 KiB"],
|
|
||||||
// signed=true prepends a + to non-negative values.
|
|
||||||
[0, true, "+0.00 KiB"],
|
|
||||||
[2 * 1024 * 1024, true, "+2048.00 KiB"],
|
|
||||||
[-2 * 1024 * 1024, true, "-2048.00 KiB"],
|
|
||||||
];
|
|
||||||
for (const [bytes, signed, expected] of cases) {
|
|
||||||
await it(`formats ${bytes} (signed=${signed}) as ${expected}`, () => {
|
|
||||||
assert.equal(formatBytes(bytes, signed), expected);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("formatPercent", async () => {
|
|
||||||
await it("formats positive fractions with a leading +", () => {
|
|
||||||
assert.equal(formatPercent(0.1), "+10.00%");
|
|
||||||
assert.equal(formatPercent(0.0123), "+1.23%");
|
|
||||||
});
|
|
||||||
|
|
||||||
await it("formats negative fractions with a leading -", () => {
|
|
||||||
assert.equal(formatPercent(-0.1), "-10.00%");
|
|
||||||
});
|
|
||||||
|
|
||||||
await it("formats zero without a sign", () => {
|
|
||||||
assert.equal(formatPercent(0), "0.00%");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("isDeltaSignificant", async () => {
|
|
||||||
const cases: Array<[number, number, number, boolean]> = [
|
|
||||||
// At and above threshold (both signs).
|
|
||||||
[100, 1000, 0.1, true],
|
|
||||||
[101, 1000, 0.1, true],
|
|
||||||
[-100, 1000, 0.1, true],
|
|
||||||
// Below threshold (both signs, plus exact zero).
|
|
||||||
[99, 1000, 0.1, false],
|
|
||||||
[-99, 1000, 0.1, false],
|
|
||||||
[0, 1000, 0.1, false],
|
|
||||||
];
|
|
||||||
for (const [delta, base, fraction, expected] of cases) {
|
|
||||||
await it(`returns ${expected} for delta=${delta}, base=${base}, fraction=${fraction}`, () => {
|
|
||||||
assert.equal(isDeltaSignificant(delta, base, fraction), expected);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("buildCommentBody", async () => {
|
|
||||||
await it("includes the marker, the base/PR/delta rows, and the run URL", () => {
|
|
||||||
const body = buildCommentBody({
|
|
||||||
baseRef: "main",
|
|
||||||
baseSize: 2_000_000,
|
|
||||||
prSize: 2_300_000,
|
|
||||||
runUrl: "https://example.test/run",
|
|
||||||
});
|
|
||||||
|
|
||||||
assert.match(body, new RegExp(`^${escapeRegExp(COMMENT_MARKER)}`));
|
|
||||||
assert.match(body, /Base \(`main`\) \| 1953\.13 KiB \(2000000 bytes\)/);
|
|
||||||
assert.match(body, /This PR \| 2246\.09 KiB \(2300000 bytes\)/);
|
|
||||||
assert.match(
|
|
||||||
body,
|
|
||||||
/\*\*Delta\*\* \| \*\*\+292\.97 KiB \(\+300000 bytes, \+15\.00%\)\*\*/,
|
|
||||||
);
|
|
||||||
assert.match(body, /\[workflow run\]\(https:\/\/example\.test\/run\)/);
|
|
||||||
});
|
|
||||||
|
|
||||||
await it("formats negative deltas with a leading minus and omits the run URL when missing", () => {
|
|
||||||
const body = buildCommentBody({
|
|
||||||
baseRef: "main",
|
|
||||||
baseSize: 2_000_000,
|
|
||||||
prSize: 1_800_000,
|
|
||||||
});
|
|
||||||
assert.match(
|
|
||||||
body,
|
|
||||||
/\*\*Delta\*\* \| \*\*-195\.31 KiB \(-200000 bytes, -10\.00%\)\*\*/,
|
|
||||||
);
|
|
||||||
assert.doesNotMatch(body, /workflow run/);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("readArgs", async () => {
|
|
||||||
await it("defaults the base ref and head commit for local runs", () => {
|
|
||||||
const originalEnv = process.env;
|
|
||||||
const originalArgv = process.argv;
|
|
||||||
|
|
||||||
try {
|
|
||||||
process.env = {};
|
|
||||||
process.argv = ["node", "check-repo-size.ts", "--output-dir", "/tmp/out"];
|
|
||||||
|
|
||||||
const args = readArgs();
|
|
||||||
|
|
||||||
assert.equal(args.baseRef, DEFAULT_BASE_REF);
|
|
||||||
assert.equal(args.baseCommitish, `origin/${DEFAULT_BASE_REF}`);
|
|
||||||
assert.equal(args.headCommitish, "HEAD");
|
|
||||||
assert.equal(args.outputDir, "/tmp/out");
|
|
||||||
assert.equal(args.runUrl, undefined);
|
|
||||||
} finally {
|
|
||||||
process.env = originalEnv;
|
|
||||||
process.argv = originalArgv;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
await it("uses the base and head SHAs when provided by the workflow", () => {
|
|
||||||
const originalEnv = process.env;
|
|
||||||
const originalArgv = process.argv;
|
|
||||||
|
|
||||||
try {
|
|
||||||
process.env = {
|
|
||||||
BASE_REF: "main",
|
|
||||||
BASE_SHA: "abc123",
|
|
||||||
HEAD_SHA: "def456",
|
|
||||||
RUN_URL: "https://example.test/run",
|
|
||||||
};
|
|
||||||
process.argv = ["node", "check-repo-size.ts", "--output-dir", "/tmp/out"];
|
|
||||||
|
|
||||||
const args = readArgs();
|
|
||||||
|
|
||||||
assert.equal(args.baseRef, "main");
|
|
||||||
assert.equal(args.baseCommitish, "abc123");
|
|
||||||
assert.equal(args.headCommitish, "def456");
|
|
||||||
assert.equal(args.outputDir, "/tmp/out");
|
|
||||||
assert.equal(args.runUrl, "https://example.test/run");
|
|
||||||
} finally {
|
|
||||||
process.env = originalEnv;
|
|
||||||
process.argv = originalArgv;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
await it("throws when --output-dir is missing", () => {
|
|
||||||
const originalEnv = process.env;
|
|
||||||
const originalArgv = process.argv;
|
|
||||||
|
|
||||||
try {
|
|
||||||
process.env = {};
|
|
||||||
process.argv = ["node", "check-repo-size.ts"];
|
|
||||||
assert.throws(() => readArgs(), /--output-dir is required/);
|
|
||||||
} finally {
|
|
||||||
process.env = originalEnv;
|
|
||||||
process.argv = originalArgv;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
let repoDir: string;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
repoDir = fs.mkdtempSync(path.join(os.tmpdir(), "check-repo-size-test-"));
|
|
||||||
execFileSync("git", ["init", "--initial-branch=main", "-q"], {
|
|
||||||
cwd: repoDir,
|
|
||||||
});
|
|
||||||
execFileSync("git", ["config", "user.email", "test@example.test"], {
|
|
||||||
cwd: repoDir,
|
|
||||||
});
|
|
||||||
execFileSync("git", ["config", "user.name", "Test"], { cwd: repoDir });
|
|
||||||
execFileSync("git", ["config", "commit.gpgsign", "false"], { cwd: repoDir });
|
|
||||||
});
|
|
||||||
|
|
||||||
afterEach(() => {
|
|
||||||
fs.rmSync(repoDir, { recursive: true, force: true });
|
|
||||||
});
|
|
||||||
|
|
||||||
function commit(name: string, content: string, message: string) {
|
|
||||||
fs.writeFileSync(path.join(repoDir, name), content);
|
|
||||||
execFileSync("git", ["add", name], { cwd: repoDir });
|
|
||||||
execFileSync("git", ["commit", "-q", "-m", message], { cwd: repoDir });
|
|
||||||
}
|
|
||||||
|
|
||||||
describe("measureArchiveSize", async () => {
|
|
||||||
await it("returns a positive byte count for a non-empty repo", async () => {
|
|
||||||
commit("a.txt", "hello world\n", "first");
|
|
||||||
const size = await measureArchiveSize("HEAD", repoDir);
|
|
||||||
assert.ok(size > 0, `expected size > 0, got ${size}`);
|
|
||||||
});
|
|
||||||
|
|
||||||
await it("returns the same size on repeated runs (deterministic)", async () => {
|
|
||||||
commit("a.txt", "hello world\n", "first");
|
|
||||||
const a = await measureArchiveSize("HEAD", repoDir);
|
|
||||||
const b = await measureArchiveSize("HEAD", repoDir);
|
|
||||||
assert.equal(a, b);
|
|
||||||
});
|
|
||||||
|
|
||||||
await it("returns a larger size when more content is added", async () => {
|
|
||||||
commit("a.txt", "hello world\n", "first");
|
|
||||||
const small = await measureArchiveSize("HEAD", repoDir);
|
|
||||||
|
|
||||||
// Use random bytes so the new content is incompressible and the archive
|
|
||||||
// is guaranteed to grow even after gzip.
|
|
||||||
commit("b.bin", randomBytes(8192).toString("base64"), "second");
|
|
||||||
const big = await measureArchiveSize("HEAD", repoDir);
|
|
||||||
assert.ok(
|
|
||||||
big > small,
|
|
||||||
`expected ${big} > ${small} after adding more content`,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
await it("ignores untracked files (e.g. node_modules)", async () => {
|
|
||||||
commit("a.txt", "hello\n", "first");
|
|
||||||
commit(".gitignore", "node_modules/\n", "ignore node_modules");
|
|
||||||
const sizeBefore = await measureArchiveSize("HEAD", repoDir);
|
|
||||||
|
|
||||||
fs.mkdirSync(path.join(repoDir, "node_modules"));
|
|
||||||
fs.writeFileSync(
|
|
||||||
path.join(repoDir, "node_modules", "huge.bin"),
|
|
||||||
"x".repeat(1_000_000),
|
|
||||||
);
|
|
||||||
|
|
||||||
const sizeAfter = await measureArchiveSize("HEAD", repoDir);
|
|
||||||
assert.equal(
|
|
||||||
sizeAfter,
|
|
||||||
sizeBefore,
|
|
||||||
"untracked node_modules should not affect the archive size",
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
await it("rejects when the ref does not exist", async () => {
|
|
||||||
commit("a.txt", "hello\n", "first");
|
|
||||||
await assert.rejects(
|
|
||||||
() => measureArchiveSize("does-not-exist", repoDir),
|
|
||||||
/git archive does-not-exist exited with code/,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
function escapeRegExp(s: string): string {
|
|
||||||
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
||||||
}
|
|
||||||
@@ -1,223 +0,0 @@
|
|||||||
#!/usr/bin/env npx tsx
|
|
||||||
|
|
||||||
/*
|
|
||||||
Measures the difference in the `.tar.gz`'d checkout size of the repo between the PR head and the PR
|
|
||||||
base. This size is relevant because it corresponds to the duration of the "Download action
|
|
||||||
repository" step that happens at the start of every job that uses this Action.
|
|
||||||
|
|
||||||
Writes the candidate sticky-comment body and a small metadata file to `--output-dir`. A separate
|
|
||||||
workflow job consumes those artifacts and decides whether to create or update a PR comment.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { spawn } from "node:child_process";
|
|
||||||
import * as fs from "node:fs";
|
|
||||||
import * as path from "node:path";
|
|
||||||
import { parseArgs } from "node:util";
|
|
||||||
|
|
||||||
import { REPO_ROOT } from "./config";
|
|
||||||
|
|
||||||
/** Hidden marker used to find the existing sticky comment on a PR. */
|
|
||||||
export const COMMENT_MARKER = "<!-- repo-size-diff-bot -->";
|
|
||||||
|
|
||||||
export const DEFAULT_BASE_REF = "main";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fraction of the base archive size at which a delta is considered significant enough to warrant
|
|
||||||
* a new sticky comment. We always update an existing comment regardless, so the comment stays in
|
|
||||||
* sync as the diff evolves.
|
|
||||||
*/
|
|
||||||
export const SIGNIFICANT_DELTA_FRACTION = 0.1;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stream `git archive --format=tar.gz <ref>` and count the compressed bytes.
|
|
||||||
*
|
|
||||||
* `git archive` only includes tracked files, so untracked directories like `node_modules` and
|
|
||||||
* `build` aren't counted in the size downloaded when starting up a CodeQL job.
|
|
||||||
*/
|
|
||||||
export async function measureArchiveSize(
|
|
||||||
ref: string,
|
|
||||||
cwd: string,
|
|
||||||
): Promise<number> {
|
|
||||||
const git = spawn("git", ["archive", "--format=tar.gz", ref], { cwd });
|
|
||||||
|
|
||||||
let stderr = "";
|
|
||||||
git.stderr.on("data", (chunk: Buffer) => {
|
|
||||||
stderr += chunk.toString();
|
|
||||||
});
|
|
||||||
|
|
||||||
let size = 0;
|
|
||||||
git.stdout.on("data", (chunk: Buffer) => {
|
|
||||||
size += chunk.length;
|
|
||||||
});
|
|
||||||
|
|
||||||
const exitCode = await new Promise<number>((resolve, reject) => {
|
|
||||||
git.on("error", reject);
|
|
||||||
git.on("close", resolve);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (exitCode !== 0) {
|
|
||||||
throw new Error(
|
|
||||||
`git archive ${ref} exited with code ${exitCode}: ${stderr.trim()}`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Format a byte count as KiB. If `signed` is true, a leading `+` is prepended for non-negative
|
|
||||||
* values so gains and losses are visually distinct.
|
|
||||||
*/
|
|
||||||
export function formatBytes(bytes: number, signed = false): string {
|
|
||||||
const sign = bytes < 0 ? "-" : signed ? "+" : "";
|
|
||||||
const kib = Math.abs(bytes) / 1024;
|
|
||||||
return `${sign}${kib.toFixed(2)} KiB`;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Format a fraction as a signed percentage with 2 decimal places. */
|
|
||||||
export function formatPercent(fraction: number): string {
|
|
||||||
const pct = fraction * 100;
|
|
||||||
const sign = pct > 0 ? "+" : "";
|
|
||||||
return `${sign}${pct.toFixed(2)}%`;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface CommentBodyOptions {
|
|
||||||
baseRef: string;
|
|
||||||
baseSize: number;
|
|
||||||
prSize: number;
|
|
||||||
/** Optional URL of the workflow run, included in the comment footer. */
|
|
||||||
runUrl?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function buildCommentBody(opts: CommentBodyOptions): string {
|
|
||||||
const { baseRef, baseSize, prSize, runUrl } = opts;
|
|
||||||
const delta = prSize - baseSize;
|
|
||||||
const signedDelta = delta >= 0 ? `+${delta}` : `${delta}`;
|
|
||||||
const runUrlLine = runUrl
|
|
||||||
? ` See the [workflow run](${runUrl}) for details.`
|
|
||||||
: "";
|
|
||||||
|
|
||||||
return [
|
|
||||||
COMMENT_MARKER,
|
|
||||||
"### Repository checkout size",
|
|
||||||
"",
|
|
||||||
"| | Compressed archive size |",
|
|
||||||
"|---|---|",
|
|
||||||
`| Base (\`${baseRef}\`) | ${formatBytes(baseSize)} (${baseSize} bytes) |`,
|
|
||||||
`| This PR | ${formatBytes(prSize)} (${prSize} bytes) |`,
|
|
||||||
`| **Delta** | **${formatBytes(delta, true)} (${signedDelta} bytes, ${formatPercent(delta / baseSize)})** |`,
|
|
||||||
"",
|
|
||||||
"Sizes are measured by streaming `git archive --format=tar.gz <ref>`, " +
|
|
||||||
"which includes tracked files and excludes untracked files such as " +
|
|
||||||
"`node_modules`. The compressed checkout is " +
|
|
||||||
"downloaded by every consumer of this Action, so changes here directly " +
|
|
||||||
`affect Action download time.${runUrlLine}`,
|
|
||||||
].join("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true when the absolute delta is at least `fraction` of the base size. Both increases and
|
|
||||||
* decreases are considered significant, so we report wins as well as losses.
|
|
||||||
*/
|
|
||||||
export function isDeltaSignificant(
|
|
||||||
delta: number,
|
|
||||||
baseSize: number,
|
|
||||||
fraction: number,
|
|
||||||
): boolean {
|
|
||||||
return Math.abs(delta) >= baseSize * fraction;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface MainArgs {
|
|
||||||
/** Base ref of the PR. Defaults to `main`. Used as the label in the PR comment. */
|
|
||||||
baseRef: string;
|
|
||||||
/** Base commit-ish to archive. Defaults to `origin/<baseRef>` for local runs. */
|
|
||||||
baseCommitish: string;
|
|
||||||
/** Head commit-ish to archive. Defaults to `HEAD` for local runs. */
|
|
||||||
headCommitish: string;
|
|
||||||
/** Optional URL of the workflow run, surfaced in the comment footer. */
|
|
||||||
runUrl?: string;
|
|
||||||
/** Directory where `body.md` and `metadata.json` are written. */
|
|
||||||
outputDir: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function readArgs(): MainArgs {
|
|
||||||
const { values } = parseArgs({
|
|
||||||
options: {
|
|
||||||
"output-dir": { type: "string" },
|
|
||||||
},
|
|
||||||
strict: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
const outputDir = values["output-dir"];
|
|
||||||
if (!outputDir) {
|
|
||||||
throw new Error("--output-dir is required");
|
|
||||||
}
|
|
||||||
|
|
||||||
const baseRef = process.env.BASE_REF ?? DEFAULT_BASE_REF;
|
|
||||||
const baseCommitish = process.env.BASE_SHA ?? `origin/${baseRef}`;
|
|
||||||
const headCommitish = process.env.HEAD_SHA ?? "HEAD";
|
|
||||||
|
|
||||||
return {
|
|
||||||
baseRef,
|
|
||||||
baseCommitish,
|
|
||||||
headCommitish,
|
|
||||||
runUrl: process.env.RUN_URL,
|
|
||||||
outputDir,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
async function main(): Promise<number> {
|
|
||||||
const args = readArgs();
|
|
||||||
|
|
||||||
console.log(`Measuring base archive size for ${args.baseCommitish}...`);
|
|
||||||
const baseSize = await measureArchiveSize(args.baseCommitish, REPO_ROOT);
|
|
||||||
console.log(` ${baseSize} bytes`);
|
|
||||||
|
|
||||||
console.log(`Measuring PR archive size for ${args.headCommitish}...`);
|
|
||||||
const prSize = await measureArchiveSize(args.headCommitish, REPO_ROOT);
|
|
||||||
console.log(` ${prSize} bytes`);
|
|
||||||
|
|
||||||
const delta = prSize - baseSize;
|
|
||||||
const significant = isDeltaSignificant(
|
|
||||||
delta,
|
|
||||||
baseSize,
|
|
||||||
SIGNIFICANT_DELTA_FRACTION,
|
|
||||||
);
|
|
||||||
console.log(
|
|
||||||
`Delta: ${delta} bytes (significant=${significant}, threshold=${(
|
|
||||||
SIGNIFICANT_DELTA_FRACTION * 100
|
|
||||||
).toFixed(2)}%)`,
|
|
||||||
);
|
|
||||||
|
|
||||||
const body = buildCommentBody({
|
|
||||||
baseRef: args.baseRef,
|
|
||||||
baseSize,
|
|
||||||
prSize,
|
|
||||||
runUrl: args.runUrl,
|
|
||||||
});
|
|
||||||
|
|
||||||
fs.mkdirSync(args.outputDir, { recursive: true });
|
|
||||||
fs.writeFileSync(path.join(args.outputDir, "body.md"), body);
|
|
||||||
fs.writeFileSync(
|
|
||||||
path.join(args.outputDir, "metadata.json"),
|
|
||||||
`${JSON.stringify(
|
|
||||||
{ significant, baseRef: args.baseRef, baseSize, prSize, delta },
|
|
||||||
null,
|
|
||||||
2,
|
|
||||||
)}\n`,
|
|
||||||
);
|
|
||||||
console.log(`Wrote body.md and metadata.json to ${args.outputDir}.`);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function run(): Promise<void> {
|
|
||||||
try {
|
|
||||||
process.exit(await main());
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err instanceof Error ? err.message : String(err));
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (require.main === module) {
|
|
||||||
void run();
|
|
||||||
}
|
|
||||||
@@ -2,8 +2,7 @@ name: "Multi-language repository"
|
|||||||
description: "An end-to-end integration test of a multi-language repository using automatic language detection"
|
description: "An end-to-end integration test of a multi-language repository using automatic language detection"
|
||||||
operatingSystems:
|
operatingSystems:
|
||||||
- ubuntu
|
- ubuntu
|
||||||
- os: macos
|
- macos
|
||||||
runner-image: macos-latest-xlarge
|
|
||||||
env:
|
env:
|
||||||
CODEQL_ACTION_RESOLVE_SUPPORTED_LANGUAGES_USING_CLI: true
|
CODEQL_ACTION_RESOLVE_SUPPORTED_LANGUAGES_USING_CLI: true
|
||||||
installGo: true
|
installGo: true
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ versions:
|
|||||||
- default
|
- default
|
||||||
steps:
|
steps:
|
||||||
- name: Set up Ruby
|
- name: Set up Ruby
|
||||||
uses: ruby/setup-ruby@c4e5b1316158f92e3d49443a9d58b31d25ac0f8f # v1.306.0
|
uses: ruby/setup-ruby@0cb964fd540e0a24c900370abf38a33466142735 # v1.305.0
|
||||||
with:
|
with:
|
||||||
ruby-version: 2.6
|
ruby-version: 2.6
|
||||||
- name: Install Code Scanning integration
|
- name: Install Code Scanning integration
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ name: "Rust analysis"
|
|||||||
description: "Tests creation of a Rust database"
|
description: "Tests creation of a Rust database"
|
||||||
versions:
|
versions:
|
||||||
# experimental rust support introduced, requires action to set `CODEQL_ENABLE_EXPERIMENTAL_FEATURES`
|
# experimental rust support introduced, requires action to set `CODEQL_ENABLE_EXPERIMENTAL_FEATURES`
|
||||||
- stable-v2.19.4
|
- stable-v2.19.3
|
||||||
# first public preview version
|
# first public preview version
|
||||||
- stable-v2.22.1
|
- stable-v2.22.1
|
||||||
- linked
|
- linked
|
||||||
|
|||||||
@@ -3,8 +3,7 @@ description: "Tests creation of a Swift database using autobuild"
|
|||||||
versions:
|
versions:
|
||||||
- nightly-latest
|
- nightly-latest
|
||||||
operatingSystems:
|
operatingSystems:
|
||||||
- os: macos
|
- macos
|
||||||
runner-image: macos-latest-xlarge
|
|
||||||
steps:
|
steps:
|
||||||
- uses: ./../action/init
|
- uses: ./../action/init
|
||||||
id: init
|
id: init
|
||||||
|
|||||||
+2
-5
@@ -6,17 +6,14 @@ export const OLDEST_SUPPORTED_MAJOR_VERSION = 3;
|
|||||||
/** The `pr-checks` directory. */
|
/** The `pr-checks` directory. */
|
||||||
export const PR_CHECKS_DIR = __dirname;
|
export const PR_CHECKS_DIR = __dirname;
|
||||||
|
|
||||||
/** The repository root. */
|
|
||||||
export const REPO_ROOT = path.join(PR_CHECKS_DIR, "..");
|
|
||||||
|
|
||||||
/** The path of the file configuring which checks shouldn't be required. */
|
/** The path of the file configuring which checks shouldn't be required. */
|
||||||
export const PR_CHECK_EXCLUDED_FILE = path.join(PR_CHECKS_DIR, "excluded.yml");
|
export const PR_CHECK_EXCLUDED_FILE = path.join(PR_CHECKS_DIR, "excluded.yml");
|
||||||
|
|
||||||
/** The path to the esbuild metadata file. */
|
/** The path to the esbuild metadata file. */
|
||||||
export const BUNDLE_METADATA_FILE = path.join(REPO_ROOT, "meta.json");
|
export const BUNDLE_METADATA_FILE = path.join(PR_CHECKS_DIR, "..", "meta.json");
|
||||||
|
|
||||||
/** The `src` directory. */
|
/** The `src` directory. */
|
||||||
const SOURCE_ROOT = path.join(REPO_ROOT, "src");
|
const SOURCE_ROOT = path.join(PR_CHECKS_DIR, "..", "src");
|
||||||
|
|
||||||
/** The path to the built-in languages file. */
|
/** The path to the built-in languages file. */
|
||||||
export const BUILTIN_LANGUAGES_FILE = path.join(
|
export const BUILTIN_LANGUAGES_FILE = path.join(
|
||||||
|
|||||||
@@ -1,17 +1,16 @@
|
|||||||
# PR checks to exclude from required checks
|
# PR checks to exclude from required checks
|
||||||
contains:
|
contains:
|
||||||
- "ESLint"
|
|
||||||
- "https://"
|
- "https://"
|
||||||
- "test-setup-python-scripts"
|
|
||||||
- "update"
|
|
||||||
- "Update"
|
- "Update"
|
||||||
|
- "ESLint"
|
||||||
|
- "update"
|
||||||
|
- "test-setup-python-scripts"
|
||||||
is:
|
is:
|
||||||
- "Agent"
|
|
||||||
- "check-expected-release-files"
|
|
||||||
- "Cleanup artifacts"
|
|
||||||
- "CodeQL"
|
- "CodeQL"
|
||||||
- "Dependabot"
|
- "Dependabot"
|
||||||
- "Label PR with size"
|
- "check-expected-release-files"
|
||||||
- "Post repo size comment"
|
- "Agent"
|
||||||
|
- "Cleanup artifacts"
|
||||||
- "Prepare"
|
- "Prepare"
|
||||||
- "Upload results"
|
- "Upload results"
|
||||||
|
- "Label PR with size"
|
||||||
|
|||||||
@@ -7,10 +7,10 @@
|
|||||||
"@octokit/core": "^7.0.6",
|
"@octokit/core": "^7.0.6",
|
||||||
"@octokit/plugin-paginate-rest": ">=9.2.2",
|
"@octokit/plugin-paginate-rest": ">=9.2.2",
|
||||||
"@octokit/plugin-rest-endpoint-methods": "^17.0.0",
|
"@octokit/plugin-rest-endpoint-methods": "^17.0.0",
|
||||||
"yaml": "^2.8.4"
|
"yaml": "^2.8.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^20.19.39",
|
"@types/node": "^20.19.9",
|
||||||
"tsx": "^4.21.0"
|
"tsx": "^4.21.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,13 +7,7 @@ Tests for the sync-checks.ts script
|
|||||||
import * as assert from "node:assert/strict";
|
import * as assert from "node:assert/strict";
|
||||||
import { describe, it } from "node:test";
|
import { describe, it } from "node:test";
|
||||||
|
|
||||||
import {
|
import { CheckInfo, Exclusions, Options, removeExcluded } from "./sync-checks";
|
||||||
CheckInfo,
|
|
||||||
Exclusions,
|
|
||||||
Options,
|
|
||||||
removeExcluded,
|
|
||||||
resolveToken,
|
|
||||||
} from "./sync-checks";
|
|
||||||
|
|
||||||
const defaultOptions: Options = {
|
const defaultOptions: Options = {
|
||||||
apply: false,
|
apply: false,
|
||||||
@@ -64,46 +58,3 @@ describe("removeExcluded", async () => {
|
|||||||
assert.deepEqual(retained, expectedExactMatches);
|
assert.deepEqual(retained, expectedExactMatches);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("resolveToken", async () => {
|
|
||||||
await it("reads the token from standard input", async () => {
|
|
||||||
const token = await resolveToken(
|
|
||||||
{ tokenStdin: true },
|
|
||||||
{ env: {}, readStdin: async () => " stdin-token\n" },
|
|
||||||
);
|
|
||||||
assert.equal(token, "stdin-token");
|
|
||||||
});
|
|
||||||
|
|
||||||
await it("reads the token from the GH_TOKEN environment variable", async () => {
|
|
||||||
const token = await resolveToken(
|
|
||||||
{},
|
|
||||||
{ env: { GH_TOKEN: "env-token" }, readStdin: async () => "" },
|
|
||||||
);
|
|
||||||
assert.equal(token, "env-token");
|
|
||||||
});
|
|
||||||
|
|
||||||
await it("reads the token from the GITHUB_TOKEN environment variable", async () => {
|
|
||||||
const token = await resolveToken(
|
|
||||||
{},
|
|
||||||
{ env: { GITHUB_TOKEN: "env-token" }, readStdin: async () => "" },
|
|
||||||
);
|
|
||||||
assert.equal(token, "env-token");
|
|
||||||
});
|
|
||||||
|
|
||||||
await it("rejects an empty standard input token", async () => {
|
|
||||||
await assert.rejects(
|
|
||||||
resolveToken(
|
|
||||||
{ tokenStdin: true },
|
|
||||||
{ env: {}, readStdin: async () => "\n" },
|
|
||||||
),
|
|
||||||
/No token received on standard input/,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
await it("rejects missing token sources", async () => {
|
|
||||||
await assert.rejects(
|
|
||||||
resolveToken({}, { env: {}, readStdin: async () => "" }),
|
|
||||||
/Missing authentication token/,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|||||||
@@ -15,8 +15,8 @@ import {
|
|||||||
|
|
||||||
/** Represents the command-line options. */
|
/** Represents the command-line options. */
|
||||||
export interface Options {
|
export interface Options {
|
||||||
/** Whether to read the GitHub API token from standard input. */
|
/** The token to use to authenticate to the GitHub API. */
|
||||||
tokenStdin?: boolean;
|
token?: string;
|
||||||
/** The git ref to use the checks for. */
|
/** The git ref to use the checks for. */
|
||||||
ref?: string;
|
ref?: string;
|
||||||
/** Whether to actually apply the changes or not. */
|
/** Whether to actually apply the changes or not. */
|
||||||
@@ -31,65 +31,6 @@ const codeqlActionRepo = {
|
|||||||
repo: "codeql-action",
|
repo: "codeql-action",
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Environment variables to check for a GitHub API token. */
|
|
||||||
const TOKEN_ENVIRONMENT_VARIABLES = ["GH_TOKEN", "GITHUB_TOKEN"];
|
|
||||||
|
|
||||||
/** Represents the sources from which we can retrieve the GitHub API token. */
|
|
||||||
interface TokenSource {
|
|
||||||
/** Environment variables to inspect. */
|
|
||||||
env: NodeJS.ProcessEnv;
|
|
||||||
/** Reads a token from standard input. */
|
|
||||||
readStdin: () => Promise<string>;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Reads the GitHub API token from standard input. */
|
|
||||||
async function readTokenFromStdin(): Promise<string> {
|
|
||||||
let token = "";
|
|
||||||
process.stdin.setEncoding("utf8");
|
|
||||||
for await (const chunk of process.stdin) {
|
|
||||||
token += chunk;
|
|
||||||
}
|
|
||||||
return token.trim();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Gets a GitHub API token from one of the supported environment variables. */
|
|
||||||
function getTokenFromEnvironment(env: NodeJS.ProcessEnv): string | undefined {
|
|
||||||
for (const variableName of TOKEN_ENVIRONMENT_VARIABLES) {
|
|
||||||
const token = env[variableName]?.trim();
|
|
||||||
if (token) {
|
|
||||||
return token;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Gets the token to use to authenticate to the GitHub API. */
|
|
||||||
export async function resolveToken(
|
|
||||||
options: Pick<Options, "tokenStdin">,
|
|
||||||
tokenSource: TokenSource = {
|
|
||||||
env: process.env,
|
|
||||||
readStdin: readTokenFromStdin,
|
|
||||||
},
|
|
||||||
): Promise<string> {
|
|
||||||
if (options.tokenStdin) {
|
|
||||||
const token = (await tokenSource.readStdin()).trim();
|
|
||||||
if (token.length === 0) {
|
|
||||||
throw new Error("No token received on standard input.");
|
|
||||||
}
|
|
||||||
return token;
|
|
||||||
}
|
|
||||||
|
|
||||||
const environmentToken = getTokenFromEnvironment(tokenSource.env);
|
|
||||||
if (environmentToken !== undefined) {
|
|
||||||
return environmentToken;
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new Error(
|
|
||||||
"Missing authentication token. Set GH_TOKEN/GITHUB_TOKEN or pipe a token " +
|
|
||||||
"to --token-stdin.",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Represents a configuration of which checks should not be set up as required checks. */
|
/** Represents a configuration of which checks should not be set up as required checks. */
|
||||||
export interface Exclusions {
|
export interface Exclusions {
|
||||||
/** A list of strings that, if contained in a check name, are excluded. */
|
/** A list of strings that, if contained in a check name, are excluded. */
|
||||||
@@ -264,10 +205,9 @@ async function updateBranch(
|
|||||||
async function main(): Promise<void> {
|
async function main(): Promise<void> {
|
||||||
const { values: options } = parseArgs({
|
const { values: options } = parseArgs({
|
||||||
options: {
|
options: {
|
||||||
// Read the token to use to authenticate to the API from standard input.
|
// The token to use to authenticate to the API.
|
||||||
"token-stdin": {
|
token: {
|
||||||
type: "boolean",
|
type: "string",
|
||||||
default: false,
|
|
||||||
},
|
},
|
||||||
// The git ref for which to retrieve the check runs.
|
// The git ref for which to retrieve the check runs.
|
||||||
ref: {
|
ref: {
|
||||||
@@ -288,16 +228,16 @@ async function main(): Promise<void> {
|
|||||||
strict: true,
|
strict: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
const token = await resolveToken({
|
if (options.token === undefined) {
|
||||||
tokenStdin: options["token-stdin"],
|
throw new Error("Missing --token");
|
||||||
});
|
}
|
||||||
|
|
||||||
console.info(
|
console.info(
|
||||||
`Oldest supported major version is: ${OLDEST_SUPPORTED_MAJOR_VERSION}`,
|
`Oldest supported major version is: ${OLDEST_SUPPORTED_MAJOR_VERSION}`,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Initialise the API client.
|
// Initialise the API client.
|
||||||
const client = getApiClient(token);
|
const client = getApiClient(options.token);
|
||||||
|
|
||||||
// Find the check runs for the specified `ref` that we will later set as the required checks
|
// Find the check runs for the specified `ref` that we will later set as the required checks
|
||||||
// for the main and release branches.
|
// for the main and release branches.
|
||||||
|
|||||||
+11
-42
@@ -28,24 +28,6 @@ interface WorkflowInput {
|
|||||||
/** A partial mapping from known input names to input definitions. */
|
/** A partial mapping from known input names to input definitions. */
|
||||||
type WorkflowInputs = Partial<Record<KnownInputName, WorkflowInput>>;
|
type WorkflowInputs = Partial<Record<KnownInputName, WorkflowInput>>;
|
||||||
|
|
||||||
/** An operating system identifier. */
|
|
||||||
type OperatingSystemIdentifier = "ubuntu" | "macos" | "windows";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents an operating system matrix entry for a generated PR check workflow.
|
|
||||||
*
|
|
||||||
* Either a string containing the OS identifier or an object containing the OS identifier and an
|
|
||||||
* optional runner image label.
|
|
||||||
*/
|
|
||||||
type OperatingSystem =
|
|
||||||
| OperatingSystemIdentifier
|
|
||||||
| {
|
|
||||||
/** OS identifier. */
|
|
||||||
os: OperatingSystemIdentifier;
|
|
||||||
/** Optional runner image label. */
|
|
||||||
"runner-image"?: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents PR check specifications.
|
* Represents PR check specifications.
|
||||||
*/
|
*/
|
||||||
@@ -54,8 +36,8 @@ interface Specification extends JobSpecification {
|
|||||||
inputs?: Record<string, WorkflowInput>;
|
inputs?: Record<string, WorkflowInput>;
|
||||||
/** CodeQL bundle versions to test against. Defaults to `DEFAULT_TEST_VERSIONS`. */
|
/** CodeQL bundle versions to test against. Defaults to `DEFAULT_TEST_VERSIONS`. */
|
||||||
versions?: string[];
|
versions?: string[];
|
||||||
/** Operating system prefixes, either as strings or with explicit runner image labels. */
|
/** Operating system prefixes used to select runner images (e.g. `["ubuntu", "macos"]`). */
|
||||||
operatingSystems?: OperatingSystem[];
|
operatingSystems?: string[];
|
||||||
/** Per-OS version overrides. If specified for an OS, only those versions are tested on that OS. */
|
/** Per-OS version overrides. If specified for an OS, only those versions are tested on that OS. */
|
||||||
osCodeQlVersions?: Record<string, string[]>;
|
osCodeQlVersions?: Record<string, string[]>;
|
||||||
/** Whether to use the all-platform CodeQL bundle. */
|
/** Whether to use the all-platform CodeQL bundle. */
|
||||||
@@ -115,6 +97,10 @@ type LanguageSetups = Partial<Record<BuiltInLanguage, LanguageSetup>>;
|
|||||||
// The default set of CodeQL Bundle versions to use for the PR checks.
|
// The default set of CodeQL Bundle versions to use for the PR checks.
|
||||||
const defaultTestVersions = [
|
const defaultTestVersions = [
|
||||||
// The oldest supported CodeQL version. If bumping, update `CODEQL_MINIMUM_VERSION` in `codeql.ts`
|
// The oldest supported CodeQL version. If bumping, update `CODEQL_MINIMUM_VERSION` in `codeql.ts`
|
||||||
|
"stable-v2.17.6",
|
||||||
|
// The last CodeQL release in the 2.18 series.
|
||||||
|
"stable-v2.18.4",
|
||||||
|
// The last CodeQL release in the 2.19 series.
|
||||||
"stable-v2.19.4",
|
"stable-v2.19.4",
|
||||||
// The last CodeQL release in the 2.20 series.
|
// The last CodeQL release in the 2.20 series.
|
||||||
"stable-v2.20.7",
|
"stable-v2.20.7",
|
||||||
@@ -122,10 +108,6 @@ const defaultTestVersions = [
|
|||||||
"stable-v2.21.4",
|
"stable-v2.21.4",
|
||||||
// The last CodeQL release in the 2.22 series.
|
// The last CodeQL release in the 2.22 series.
|
||||||
"stable-v2.22.4",
|
"stable-v2.22.4",
|
||||||
// The last CodeQL release in the 2.23 series.
|
|
||||||
"stable-v2.23.9",
|
|
||||||
// The last CodeQL release in the 2.24 series.
|
|
||||||
"stable-v2.24.3",
|
|
||||||
// The default version of CodeQL for Dotcom, as determined by feature flags.
|
// The default version of CodeQL for Dotcom, as determined by feature flags.
|
||||||
"default",
|
"default",
|
||||||
// The version of CodeQL shipped with the Action in `defaults.json`. During the release process
|
// The version of CodeQL shipped with the Action in `defaults.json`. During the release process
|
||||||
@@ -329,19 +311,10 @@ function generateJobMatrix(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const defaultRunnerImages = [
|
const runnerImages = ["ubuntu-latest", "macos-latest", "windows-latest"];
|
||||||
"ubuntu-latest",
|
|
||||||
"macos-latest",
|
|
||||||
"windows-latest",
|
|
||||||
];
|
|
||||||
const operatingSystems = checkSpecification.operatingSystems ?? ["ubuntu"];
|
const operatingSystems = checkSpecification.operatingSystems ?? ["ubuntu"];
|
||||||
|
|
||||||
for (const operatingSystemConfig of operatingSystems) {
|
for (const operatingSystem of operatingSystems) {
|
||||||
const operatingSystem =
|
|
||||||
typeof operatingSystemConfig === "string"
|
|
||||||
? operatingSystemConfig
|
|
||||||
: operatingSystemConfig.os;
|
|
||||||
|
|
||||||
// If osCodeQlVersions is set for this OS, only include the specified CodeQL versions.
|
// If osCodeQlVersions is set for this OS, only include the specified CodeQL versions.
|
||||||
const allowedVersions =
|
const allowedVersions =
|
||||||
checkSpecification.osCodeQlVersions?.[operatingSystem];
|
checkSpecification.osCodeQlVersions?.[operatingSystem];
|
||||||
@@ -349,13 +322,9 @@ function generateJobMatrix(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const runnerImagesForOs =
|
const runnerImagesForOs = runnerImages.filter((image) =>
|
||||||
typeof operatingSystemConfig === "string" ||
|
image.startsWith(operatingSystem),
|
||||||
operatingSystemConfig["runner-image"] === undefined
|
);
|
||||||
? defaultRunnerImages.filter((image) =>
|
|
||||||
image.startsWith(operatingSystem),
|
|
||||||
)
|
|
||||||
: [operatingSystemConfig["runner-image"]];
|
|
||||||
|
|
||||||
for (const runnerImage of runnerImagesForOs) {
|
for (const runnerImage of runnerImagesForOs) {
|
||||||
matrix.push({
|
matrix.push({
|
||||||
|
|||||||
@@ -23,8 +23,7 @@ predicate isSafeForDefaultSetup(string envVar) {
|
|||||||
"GITHUB_BASE_REF", "GITHUB_EVENT_NAME", "GITHUB_JOB", "GITHUB_RUN_ATTEMPT", "GITHUB_RUN_ID",
|
"GITHUB_BASE_REF", "GITHUB_EVENT_NAME", "GITHUB_JOB", "GITHUB_RUN_ATTEMPT", "GITHUB_RUN_ID",
|
||||||
"GITHUB_SHA", "GITHUB_REPOSITORY", "GITHUB_SERVER_URL", "GITHUB_TOKEN", "GITHUB_WORKFLOW",
|
"GITHUB_SHA", "GITHUB_REPOSITORY", "GITHUB_SERVER_URL", "GITHUB_TOKEN", "GITHUB_WORKFLOW",
|
||||||
"GITHUB_WORKSPACE", "GOFLAGS", "ImageVersion", "JAVA_TOOL_OPTIONS", "RUNNER_ARCH",
|
"GITHUB_WORKSPACE", "GOFLAGS", "ImageVersion", "JAVA_TOOL_OPTIONS", "RUNNER_ARCH",
|
||||||
"RUNNER_ENVIRONMENT", "RUNNER_NAME", "RUNNER_OS", "RUNNER_TEMP", "RUNNER_TOOL_CACHE",
|
"RUNNER_ENVIRONMENT", "RUNNER_NAME", "RUNNER_OS", "RUNNER_TEMP", "RUNNER_TOOL_CACHE"
|
||||||
"NODE_ENV"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,7 +43,6 @@ predicate envVarRead(DataFlow::Node node, string envVar) {
|
|||||||
from DataFlow::Node read, string envVar
|
from DataFlow::Node read, string envVar
|
||||||
where
|
where
|
||||||
envVarRead(read, envVar) and
|
envVarRead(read, envVar) and
|
||||||
read.getFile().getRelativePath().matches("src/%") and
|
|
||||||
not read.getFile().getBaseName().matches("%.test.ts") and
|
not read.getFile().getBaseName().matches("%.test.ts") and
|
||||||
not isSafeForDefaultSetup(envVar)
|
not isSafeForDefaultSetup(envVar)
|
||||||
select read,
|
select read,
|
||||||
|
|||||||
@@ -22,4 +22,4 @@ outputs:
|
|||||||
description: The inferred build environment configuration.
|
description: The inferred build environment configuration.
|
||||||
runs:
|
runs:
|
||||||
using: node24
|
using: node24
|
||||||
main: '../lib/resolve-environment-entry.js'
|
main: '../lib/resolve-environment-action.js'
|
||||||
|
|||||||
+1
-20
@@ -19,25 +19,6 @@ inputs:
|
|||||||
If not specified, the Action will check in several places until it finds
|
If not specified, the Action will check in several places until it finds
|
||||||
the CodeQL tools.
|
the CodeQL tools.
|
||||||
required: false
|
required: false
|
||||||
languages:
|
|
||||||
description: >-
|
|
||||||
A comma-separated list of CodeQL languages that will be analyzed in subsequent
|
|
||||||
`github/codeql-action/init` and `github/codeql-action/analyze` invocations. If specified, the
|
|
||||||
Action may use this list to select a CodeQL CLI version that is best suited to analyzing those
|
|
||||||
languages, for example by preferring a version that has a cached overlay-base database for the
|
|
||||||
specified languages. This input is not remembered and must also be passed to
|
|
||||||
`github/codeql-action/init`.
|
|
||||||
required: false
|
|
||||||
analysis-kinds:
|
|
||||||
description: >-
|
|
||||||
[Internal] A comma-separated list of analysis kinds that subsequent
|
|
||||||
`github/codeql-action/init` invocations will enable. If specified, the Action may use this
|
|
||||||
list to select a CodeQL CLI version that is best suited to those analysis kinds. This input is
|
|
||||||
not remembered and must also be passed to `github/codeql-action/init`.
|
|
||||||
|
|
||||||
Available options are the same as for the `analysis-kinds` input on the `init` Action.
|
|
||||||
default: 'code-scanning'
|
|
||||||
required: true
|
|
||||||
token:
|
token:
|
||||||
description: GitHub token to use for authenticating with this instance of GitHub.
|
description: GitHub token to use for authenticating with this instance of GitHub.
|
||||||
default: ${{ github.token }}
|
default: ${{ github.token }}
|
||||||
@@ -55,4 +36,4 @@ outputs:
|
|||||||
description: The version of the CodeQL binary that was installed.
|
description: The version of the CodeQL binary that was installed.
|
||||||
runs:
|
runs:
|
||||||
using: node24
|
using: node24
|
||||||
main: '../lib/setup-codeql-entry.js'
|
main: '../lib/setup-codeql-action.js'
|
||||||
|
|||||||
@@ -1,4 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
|
|
||||||
const import_entry_points = require("./entry-points");
|
|
||||||
void (0, import_entry_points.run__ACTION__)();
|
|
||||||
+9
-96
@@ -16,12 +16,7 @@ import {
|
|||||||
} from "./analyses";
|
} from "./analyses";
|
||||||
import { EnvVar } from "./environment";
|
import { EnvVar } from "./environment";
|
||||||
import { getRunnerLogger } from "./logging";
|
import { getRunnerLogger } from "./logging";
|
||||||
import {
|
import { setupTests } from "./testing-utils";
|
||||||
createFeatures,
|
|
||||||
RecordingLogger,
|
|
||||||
setupBaseActionsVars,
|
|
||||||
setupTests,
|
|
||||||
} from "./testing-utils";
|
|
||||||
import { AssessmentPayload } from "./upload-lib/types";
|
import { AssessmentPayload } from "./upload-lib/types";
|
||||||
import { ConfigurationError } from "./util";
|
import { ConfigurationError } from "./util";
|
||||||
|
|
||||||
@@ -58,91 +53,24 @@ test("Parsing analysis kinds requires at least one analysis kind", async (t) =>
|
|||||||
test.serial(
|
test.serial(
|
||||||
"getAnalysisKinds - returns expected analysis kinds for `analysis-kinds` input",
|
"getAnalysisKinds - returns expected analysis kinds for `analysis-kinds` input",
|
||||||
async (t) => {
|
async (t) => {
|
||||||
process.env[EnvVar.TEST_MODE] = "true";
|
|
||||||
const features = createFeatures([]);
|
|
||||||
const requiredInputStub = sinon.stub(actionsUtil, "getRequiredInput");
|
const requiredInputStub = sinon.stub(actionsUtil, "getRequiredInput");
|
||||||
requiredInputStub
|
requiredInputStub
|
||||||
.withArgs("analysis-kinds")
|
.withArgs("analysis-kinds")
|
||||||
.returns("code-scanning,code-quality");
|
.returns("code-scanning,code-quality");
|
||||||
const result = await getAnalysisKinds(
|
const result = await getAnalysisKinds(getRunnerLogger(true), true);
|
||||||
getRunnerLogger(true),
|
|
||||||
features,
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
t.assert(result.includes(AnalysisKind.CodeScanning));
|
t.assert(result.includes(AnalysisKind.CodeScanning));
|
||||||
t.assert(result.includes(AnalysisKind.CodeQuality));
|
t.assert(result.includes(AnalysisKind.CodeQuality));
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
test.serial(
|
|
||||||
"getAnalysisKinds - only use `code-scanning` for multiple analysis kinds outside of test mode",
|
|
||||||
async (t) => {
|
|
||||||
setupBaseActionsVars();
|
|
||||||
process.env[EnvVar.TEST_MODE] = "false";
|
|
||||||
const features = createFeatures([]);
|
|
||||||
const logger = new RecordingLogger();
|
|
||||||
const requiredInputStub = sinon.stub(actionsUtil, "getRequiredInput");
|
|
||||||
requiredInputStub
|
|
||||||
.withArgs("analysis-kinds")
|
|
||||||
.returns("code-scanning,code-quality");
|
|
||||||
const result = await getAnalysisKinds(logger, features, true);
|
|
||||||
t.deepEqual(result, [AnalysisKind.CodeScanning]);
|
|
||||||
t.assert(
|
|
||||||
logger.hasMessage(
|
|
||||||
"Continuing with only `analysis-kinds: code-scanning`.",
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
test.serial(
|
|
||||||
"getAnalysisKinds - logs error for non-default `analysis-kinds` in custom workflow",
|
|
||||||
async (t) => {
|
|
||||||
setupBaseActionsVars({ GITHUB_EVENT_NAME: "push" });
|
|
||||||
process.env[EnvVar.TEST_MODE] = "false";
|
|
||||||
const features = createFeatures([]);
|
|
||||||
const logger = new RecordingLogger();
|
|
||||||
const requiredInputStub = sinon.stub(actionsUtil, "getRequiredInput");
|
|
||||||
requiredInputStub.withArgs("analysis-kinds").returns("code-quality");
|
|
||||||
const result = await getAnalysisKinds(logger, features, true);
|
|
||||||
t.deepEqual(result, [AnalysisKind.CodeQuality]);
|
|
||||||
t.assert(
|
|
||||||
logger.hasMessage(
|
|
||||||
"An analysis kind other than `code-scanning` was specified in a custom workflow.",
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
test.serial(
|
|
||||||
"getAnalysisKinds - no error for non-default `analysis-kinds` in managed workflow",
|
|
||||||
async (t) => {
|
|
||||||
setupBaseActionsVars({ GITHUB_EVENT_NAME: "dynamic" });
|
|
||||||
process.env[EnvVar.TEST_MODE] = "false";
|
|
||||||
const features = createFeatures([]);
|
|
||||||
const logger = new RecordingLogger();
|
|
||||||
const requiredInputStub = sinon.stub(actionsUtil, "getRequiredInput");
|
|
||||||
requiredInputStub.withArgs("analysis-kinds").returns("code-quality");
|
|
||||||
const result = await getAnalysisKinds(logger, features, true);
|
|
||||||
t.deepEqual(result, [AnalysisKind.CodeQuality]);
|
|
||||||
t.deepEqual(logger.messages, []);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
test.serial(
|
test.serial(
|
||||||
"getAnalysisKinds - includes `code-quality` when deprecated `quality-queries` input is used",
|
"getAnalysisKinds - includes `code-quality` when deprecated `quality-queries` input is used",
|
||||||
async (t) => {
|
async (t) => {
|
||||||
process.env[EnvVar.TEST_MODE] = "true";
|
|
||||||
const features = createFeatures([]);
|
|
||||||
const requiredInputStub = sinon.stub(actionsUtil, "getRequiredInput");
|
const requiredInputStub = sinon.stub(actionsUtil, "getRequiredInput");
|
||||||
requiredInputStub.withArgs("analysis-kinds").returns("code-scanning");
|
requiredInputStub.withArgs("analysis-kinds").returns("code-scanning");
|
||||||
const optionalInputStub = sinon.stub(actionsUtil, "getOptionalInput");
|
const optionalInputStub = sinon.stub(actionsUtil, "getOptionalInput");
|
||||||
optionalInputStub.withArgs("quality-queries").returns("code-quality");
|
optionalInputStub.withArgs("quality-queries").returns("code-quality");
|
||||||
const result = await getAnalysisKinds(
|
const result = await getAnalysisKinds(getRunnerLogger(true), true);
|
||||||
getRunnerLogger(true),
|
|
||||||
features,
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
t.assert(result.includes(AnalysisKind.CodeScanning));
|
t.assert(result.includes(AnalysisKind.CodeScanning));
|
||||||
t.assert(result.includes(AnalysisKind.CodeQuality));
|
t.assert(result.includes(AnalysisKind.CodeQuality));
|
||||||
},
|
},
|
||||||
@@ -151,12 +79,9 @@ test.serial(
|
|||||||
test.serial(
|
test.serial(
|
||||||
"getAnalysisKinds - throws if `analysis-kinds` input is invalid",
|
"getAnalysisKinds - throws if `analysis-kinds` input is invalid",
|
||||||
async (t) => {
|
async (t) => {
|
||||||
const features = createFeatures([]);
|
|
||||||
const requiredInputStub = sinon.stub(actionsUtil, "getRequiredInput");
|
const requiredInputStub = sinon.stub(actionsUtil, "getRequiredInput");
|
||||||
requiredInputStub.withArgs("analysis-kinds").returns("no-such-thing");
|
requiredInputStub.withArgs("analysis-kinds").returns("no-such-thing");
|
||||||
await t.throwsAsync(
|
await t.throwsAsync(getAnalysisKinds(getRunnerLogger(true), true));
|
||||||
getAnalysisKinds(getRunnerLogger(true), features, true),
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -173,18 +98,11 @@ for (let i = 0; i < analysisKinds.length; i++) {
|
|||||||
test.serial(
|
test.serial(
|
||||||
`getAnalysisKinds - allows ${analysisKind} with ${otherAnalysis}`,
|
`getAnalysisKinds - allows ${analysisKind} with ${otherAnalysis}`,
|
||||||
async (t) => {
|
async (t) => {
|
||||||
setupBaseActionsVars();
|
|
||||||
process.env[EnvVar.TEST_MODE] = "true";
|
|
||||||
const features = createFeatures([]);
|
|
||||||
const requiredInputStub = sinon.stub(actionsUtil, "getRequiredInput");
|
const requiredInputStub = sinon.stub(actionsUtil, "getRequiredInput");
|
||||||
requiredInputStub
|
requiredInputStub
|
||||||
.withArgs("analysis-kinds")
|
.withArgs("analysis-kinds")
|
||||||
.returns([analysisKind, otherAnalysis].join(","));
|
.returns([analysisKind, otherAnalysis].join(","));
|
||||||
const result = await getAnalysisKinds(
|
const result = await getAnalysisKinds(getRunnerLogger(true), true);
|
||||||
getRunnerLogger(true),
|
|
||||||
features,
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
t.is(result.length, 2);
|
t.is(result.length, 2);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@@ -192,19 +110,14 @@ for (let i = 0; i < analysisKinds.length; i++) {
|
|||||||
test.serial(
|
test.serial(
|
||||||
`getAnalysisKinds - throws if ${analysisKind} is enabled with ${otherAnalysis}`,
|
`getAnalysisKinds - throws if ${analysisKind} is enabled with ${otherAnalysis}`,
|
||||||
async (t) => {
|
async (t) => {
|
||||||
setupBaseActionsVars();
|
|
||||||
const features = createFeatures([]);
|
|
||||||
const requiredInputStub = sinon.stub(actionsUtil, "getRequiredInput");
|
const requiredInputStub = sinon.stub(actionsUtil, "getRequiredInput");
|
||||||
requiredInputStub
|
requiredInputStub
|
||||||
.withArgs("analysis-kinds")
|
.withArgs("analysis-kinds")
|
||||||
.returns([analysisKind, otherAnalysis].join(","));
|
.returns([analysisKind, otherAnalysis].join(","));
|
||||||
await t.throwsAsync(
|
await t.throwsAsync(getAnalysisKinds(getRunnerLogger(true), true), {
|
||||||
getAnalysisKinds(getRunnerLogger(true), features, true),
|
instanceOf: ConfigurationError,
|
||||||
{
|
message: `${analysisKind} and ${otherAnalysis} cannot be enabled at the same time`,
|
||||||
instanceOf: ConfigurationError,
|
});
|
||||||
message: `${analysisKind} and ${otherAnalysis} cannot be enabled at the same time`,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-58
@@ -2,17 +2,15 @@ import {
|
|||||||
fixCodeQualityCategory,
|
fixCodeQualityCategory,
|
||||||
getOptionalInput,
|
getOptionalInput,
|
||||||
getRequiredInput,
|
getRequiredInput,
|
||||||
isDynamicWorkflow,
|
|
||||||
} from "./actions-util";
|
} from "./actions-util";
|
||||||
import { EnvVar } from "./environment";
|
import { EnvVar } from "./environment";
|
||||||
import { Feature, FeatureEnablement } from "./feature-flags";
|
|
||||||
import { Logger } from "./logging";
|
import { Logger } from "./logging";
|
||||||
import {
|
import {
|
||||||
AssessmentPayload,
|
AssessmentPayload,
|
||||||
BasePayload,
|
BasePayload,
|
||||||
UploadPayload,
|
UploadPayload,
|
||||||
} from "./upload-lib/types";
|
} from "./upload-lib/types";
|
||||||
import { ConfigurationError, getRequiredEnvParam, isInTestMode } from "./util";
|
import { ConfigurationError, getRequiredEnvParam } from "./util";
|
||||||
|
|
||||||
export enum AnalysisKind {
|
export enum AnalysisKind {
|
||||||
CodeScanning = "code-scanning",
|
CodeScanning = "code-scanning",
|
||||||
@@ -66,21 +64,6 @@ export async function parseAnalysisKinds(
|
|||||||
// Used to avoid re-parsing the input after we have done it once.
|
// Used to avoid re-parsing the input after we have done it once.
|
||||||
let cachedAnalysisKinds: AnalysisKind[] | undefined;
|
let cachedAnalysisKinds: AnalysisKind[] | undefined;
|
||||||
|
|
||||||
/** Determines whether `code-scanning` is the only enabled analysis kind in `analysisKinds`. */
|
|
||||||
function isOnlyCodeScanningEnabled(analysisKinds: AnalysisKind[]) {
|
|
||||||
return (
|
|
||||||
analysisKinds.length === 1 && analysisKinds[0] === AnalysisKind.CodeScanning
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Prepends a generic message about the intended usage for `analysis-kinds` to `message`. */
|
|
||||||
function makeAnalysisKindUsageError(message: string) {
|
|
||||||
return (
|
|
||||||
"The `analysis-kinds` input is experimental and for GitHub-internal use only. " +
|
|
||||||
`Its behaviour may change at any time or be removed entirely. ${message}`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialises the analysis kinds for the analysis based on the `analysis-kinds` input.
|
* Initialises the analysis kinds for the analysis based on the `analysis-kinds` input.
|
||||||
* This function will also use the deprecated `quality-queries` input as an indicator to enable `code-quality`.
|
* This function will also use the deprecated `quality-queries` input as an indicator to enable `code-quality`.
|
||||||
@@ -94,7 +77,6 @@ function makeAnalysisKindUsageError(message: string) {
|
|||||||
*/
|
*/
|
||||||
export async function getAnalysisKinds(
|
export async function getAnalysisKinds(
|
||||||
logger: Logger,
|
logger: Logger,
|
||||||
features: FeatureEnablement,
|
|
||||||
skipCache: boolean = false,
|
skipCache: boolean = false,
|
||||||
): Promise<AnalysisKind[]> {
|
): Promise<AnalysisKind[]> {
|
||||||
if (!skipCache && cachedAnalysisKinds !== undefined) {
|
if (!skipCache && cachedAnalysisKinds !== undefined) {
|
||||||
@@ -105,26 +87,6 @@ export async function getAnalysisKinds(
|
|||||||
getRequiredInput("analysis-kinds"),
|
getRequiredInput("analysis-kinds"),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Log an error if we are outside of a GitHub-managed workflow and an analysis kind
|
|
||||||
// other than `code-scanning` is enabled.
|
|
||||||
if (
|
|
||||||
!isInTestMode() &&
|
|
||||||
!isDynamicWorkflow() &&
|
|
||||||
!isOnlyCodeScanningEnabled(analysisKinds)
|
|
||||||
) {
|
|
||||||
const codeQualityHint = analysisKinds.includes(AnalysisKind.CodeQuality)
|
|
||||||
? " If your intention is to use quality queries outside of Code Quality, " +
|
|
||||||
"use the `queries` input with `code-quality` instead."
|
|
||||||
: "";
|
|
||||||
|
|
||||||
logger.error(
|
|
||||||
makeAnalysisKindUsageError(
|
|
||||||
"An analysis kind other than `code-scanning` was specified in a custom workflow. " +
|
|
||||||
`This is not supported and will become a fatal error in a future version of the CodeQL Action.${codeQualityHint}`,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Warn that `quality-queries` is deprecated if there is an argument for it.
|
// Warn that `quality-queries` is deprecated if there is an argument for it.
|
||||||
const qualityQueriesInput = getOptionalInput("quality-queries");
|
const qualityQueriesInput = getOptionalInput("quality-queries");
|
||||||
|
|
||||||
@@ -158,25 +120,6 @@ export async function getAnalysisKinds(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Log an error if we have multiple inputs for `analysis-kinds` outside of test mode,
|
|
||||||
// and enable only `code-scanning`.
|
|
||||||
if (
|
|
||||||
!isInTestMode() &&
|
|
||||||
analysisKinds.length > 1 &&
|
|
||||||
!(await features.getValue(Feature.AllowMultipleAnalysisKinds))
|
|
||||||
) {
|
|
||||||
logger.error(
|
|
||||||
makeAnalysisKindUsageError(
|
|
||||||
"Specifying multiple values as input is no longer supported. " +
|
|
||||||
"Continuing with only `analysis-kinds: code-scanning`.",
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
// Only enable Code Scanning.
|
|
||||||
cachedAnalysisKinds = [AnalysisKind.CodeScanning];
|
|
||||||
return cachedAnalysisKinds;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cache the analysis kinds and return them.
|
// Cache the analysis kinds and return them.
|
||||||
cachedAnalysisKinds = analysisKinds;
|
cachedAnalysisKinds = analysisKinds;
|
||||||
return cachedAnalysisKinds;
|
return cachedAnalysisKinds;
|
||||||
|
|||||||
@@ -0,0 +1,90 @@
|
|||||||
|
import test from "ava";
|
||||||
|
import * as sinon from "sinon";
|
||||||
|
|
||||||
|
import * as actionsUtil from "./actions-util";
|
||||||
|
import * as analyze from "./analyze";
|
||||||
|
import * as api from "./api-client";
|
||||||
|
import * as configUtils from "./config-utils";
|
||||||
|
import * as gitUtils from "./git-utils";
|
||||||
|
import * as statusReport from "./status-report";
|
||||||
|
import {
|
||||||
|
setupTests,
|
||||||
|
setupActionsVars,
|
||||||
|
mockFeatureFlagApiEndpoint,
|
||||||
|
} from "./testing-utils";
|
||||||
|
import * as util from "./util";
|
||||||
|
|
||||||
|
setupTests(test);
|
||||||
|
|
||||||
|
// This test needs to be in its own file so that ava would run it in its own
|
||||||
|
// nodejs process. The code being tested is in analyze-action.ts, which runs
|
||||||
|
// immediately on load. So the file needs to be loaded during part of the test,
|
||||||
|
// and that can happen only once per nodejs process. If multiple such tests are
|
||||||
|
// in the same test file, ava would run them in the same nodejs process, and all
|
||||||
|
// but the first test would fail.
|
||||||
|
|
||||||
|
test("analyze action with RAM & threads from environment variables", async (t) => {
|
||||||
|
// This test frequently times out on Windows with the default timeout, so we bump
|
||||||
|
// it a bit to 20s.
|
||||||
|
t.timeout(1000 * 20);
|
||||||
|
await util.withTmpDir(async (tmpDir) => {
|
||||||
|
setupActionsVars(tmpDir, tmpDir);
|
||||||
|
sinon
|
||||||
|
.stub(statusReport, "createStatusReportBase")
|
||||||
|
.resolves({} as statusReport.StatusReportBase);
|
||||||
|
sinon.stub(statusReport, "sendStatusReport").resolves();
|
||||||
|
sinon.stub(gitUtils, "isAnalyzingDefaultBranch").resolves(true);
|
||||||
|
|
||||||
|
const gitHubVersion: util.GitHubVersion = {
|
||||||
|
type: util.GitHubVariant.DOTCOM,
|
||||||
|
};
|
||||||
|
sinon.stub(configUtils, "getConfig").resolves({
|
||||||
|
gitHubVersion,
|
||||||
|
augmentationProperties: {},
|
||||||
|
languages: [],
|
||||||
|
packs: [],
|
||||||
|
trapCaches: {},
|
||||||
|
} as unknown as configUtils.Config);
|
||||||
|
const requiredInputStub = sinon.stub(actionsUtil, "getRequiredInput");
|
||||||
|
requiredInputStub.withArgs("token").returns("fake-token");
|
||||||
|
requiredInputStub.withArgs("upload-database").returns("false");
|
||||||
|
requiredInputStub.withArgs("output").returns("out");
|
||||||
|
const optionalInputStub = sinon.stub(actionsUtil, "getOptionalInput");
|
||||||
|
optionalInputStub.withArgs("expect-error").returns("false");
|
||||||
|
sinon.stub(api, "getGitHubVersion").resolves(gitHubVersion);
|
||||||
|
mockFeatureFlagApiEndpoint(200, {});
|
||||||
|
|
||||||
|
// When there are no action inputs for RAM and threads, the action uses
|
||||||
|
// environment variables (passed down from the init action) to set RAM and
|
||||||
|
// threads usage.
|
||||||
|
process.env["CODEQL_THREADS"] = "-1";
|
||||||
|
process.env["CODEQL_RAM"] = "4992";
|
||||||
|
|
||||||
|
const runFinalizeStub = sinon.stub(analyze, "runFinalize");
|
||||||
|
const runQueriesStub = sinon.stub(analyze, "runQueries");
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
||||||
|
const analyzeAction = require("./analyze-action");
|
||||||
|
|
||||||
|
// When analyze-action.ts loads, it runs an async function from the top
|
||||||
|
// level but does not wait for it to finish. To ensure that calls to
|
||||||
|
// runFinalize and runQueries are correctly captured by spies, we explicitly
|
||||||
|
// wait for the action promise to complete before starting verification.
|
||||||
|
await analyzeAction.runPromise;
|
||||||
|
|
||||||
|
t.assert(
|
||||||
|
runFinalizeStub.calledOnceWith(
|
||||||
|
sinon.match.any,
|
||||||
|
sinon.match.any,
|
||||||
|
"--threads=-1",
|
||||||
|
"--ram=4992",
|
||||||
|
),
|
||||||
|
);
|
||||||
|
t.assert(
|
||||||
|
runQueriesStub.calledOnceWith(
|
||||||
|
sinon.match.any,
|
||||||
|
"--ram=4992",
|
||||||
|
"--threads=-1",
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
import test from "ava";
|
||||||
|
import * as sinon from "sinon";
|
||||||
|
|
||||||
|
import * as actionsUtil from "./actions-util";
|
||||||
|
import * as analyze from "./analyze";
|
||||||
|
import * as api from "./api-client";
|
||||||
|
import * as configUtils from "./config-utils";
|
||||||
|
import * as gitUtils from "./git-utils";
|
||||||
|
import * as statusReport from "./status-report";
|
||||||
|
import {
|
||||||
|
setupTests,
|
||||||
|
setupActionsVars,
|
||||||
|
mockFeatureFlagApiEndpoint,
|
||||||
|
} from "./testing-utils";
|
||||||
|
import * as util from "./util";
|
||||||
|
|
||||||
|
setupTests(test);
|
||||||
|
|
||||||
|
// This test needs to be in its own file so that ava would run it in its own
|
||||||
|
// nodejs process. The code being tested is in analyze-action.ts, which runs
|
||||||
|
// immediately on load. So the file needs to be loaded during part of the test,
|
||||||
|
// and that can happen only once per nodejs process. If multiple such tests are
|
||||||
|
// in the same test file, ava would run them in the same nodejs process, and all
|
||||||
|
// but the first test would fail.
|
||||||
|
|
||||||
|
test("analyze action with RAM & threads from action inputs", async (t) => {
|
||||||
|
t.timeout(1000 * 20);
|
||||||
|
await util.withTmpDir(async (tmpDir) => {
|
||||||
|
setupActionsVars(tmpDir, tmpDir);
|
||||||
|
sinon
|
||||||
|
.stub(statusReport, "createStatusReportBase")
|
||||||
|
.resolves({} as statusReport.StatusReportBase);
|
||||||
|
sinon.stub(statusReport, "sendStatusReport").resolves();
|
||||||
|
const gitHubVersion: util.GitHubVersion = {
|
||||||
|
type: util.GitHubVariant.DOTCOM,
|
||||||
|
};
|
||||||
|
sinon.stub(configUtils, "getConfig").resolves({
|
||||||
|
gitHubVersion,
|
||||||
|
augmentationProperties: {},
|
||||||
|
languages: [],
|
||||||
|
packs: [],
|
||||||
|
trapCaches: {},
|
||||||
|
} as unknown as configUtils.Config);
|
||||||
|
const requiredInputStub = sinon.stub(actionsUtil, "getRequiredInput");
|
||||||
|
requiredInputStub.withArgs("token").returns("fake-token");
|
||||||
|
requiredInputStub.withArgs("upload-database").returns("false");
|
||||||
|
requiredInputStub.withArgs("output").returns("out");
|
||||||
|
const optionalInputStub = sinon.stub(actionsUtil, "getOptionalInput");
|
||||||
|
optionalInputStub.withArgs("expect-error").returns("false");
|
||||||
|
sinon.stub(api, "getGitHubVersion").resolves(gitHubVersion);
|
||||||
|
sinon.stub(gitUtils, "isAnalyzingDefaultBranch").resolves(true);
|
||||||
|
mockFeatureFlagApiEndpoint(200, {});
|
||||||
|
|
||||||
|
process.env["CODEQL_THREADS"] = "1";
|
||||||
|
process.env["CODEQL_RAM"] = "4992";
|
||||||
|
|
||||||
|
// Action inputs have precedence over environment variables.
|
||||||
|
optionalInputStub.withArgs("threads").returns("-1");
|
||||||
|
optionalInputStub.withArgs("ram").returns("3012");
|
||||||
|
|
||||||
|
const runFinalizeStub = sinon.stub(analyze, "runFinalize");
|
||||||
|
const runQueriesStub = sinon.stub(analyze, "runQueries");
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
||||||
|
const analyzeAction = require("./analyze-action");
|
||||||
|
|
||||||
|
// When analyze-action.ts loads, it runs an async function from the top
|
||||||
|
// level but does not wait for it to finish. To ensure that calls to
|
||||||
|
// runFinalize and runQueries are correctly captured by spies, we explicitly
|
||||||
|
// wait for the action promise to complete before starting verification.
|
||||||
|
await analyzeAction.runPromise;
|
||||||
|
|
||||||
|
t.assert(
|
||||||
|
runFinalizeStub.calledOnceWith(
|
||||||
|
sinon.match.any,
|
||||||
|
sinon.match.any,
|
||||||
|
"--threads=-1",
|
||||||
|
"--ram=3012",
|
||||||
|
),
|
||||||
|
);
|
||||||
|
t.assert(
|
||||||
|
runQueriesStub.calledOnceWith(
|
||||||
|
sinon.match.any,
|
||||||
|
"--ram=3012",
|
||||||
|
"--threads=-1",
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -20,7 +20,7 @@ import { EnvVar } from "./environment";
|
|||||||
import { getActionsLogger } from "./logging";
|
import { getActionsLogger } from "./logging";
|
||||||
import { checkGitHubVersionInRange, getErrorMessage } from "./util";
|
import { checkGitHubVersionInRange, getErrorMessage } from "./util";
|
||||||
|
|
||||||
export async function runWrapper() {
|
async function runWrapper() {
|
||||||
// To capture errors appropriately, keep as much code within the try-catch as
|
// To capture errors appropriately, keep as much code within the try-catch as
|
||||||
// possible, and only use safe functions outside.
|
// possible, and only use safe functions outside.
|
||||||
|
|
||||||
@@ -72,3 +72,5 @@ export async function runWrapper() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void runWrapper();
|
||||||
|
|||||||
@@ -1,142 +0,0 @@
|
|||||||
import test from "ava";
|
|
||||||
import * as sinon from "sinon";
|
|
||||||
|
|
||||||
import * as actionsUtil from "./actions-util";
|
|
||||||
import * as analyze from "./analyze";
|
|
||||||
import { runWrapper } from "./analyze-action";
|
|
||||||
import * as api from "./api-client";
|
|
||||||
import * as configUtils from "./config-utils";
|
|
||||||
import * as gitUtils from "./git-utils";
|
|
||||||
import * as statusReport from "./status-report";
|
|
||||||
import {
|
|
||||||
setupTests,
|
|
||||||
setupActionsVars,
|
|
||||||
mockFeatureFlagApiEndpoint,
|
|
||||||
} from "./testing-utils";
|
|
||||||
import * as util from "./util";
|
|
||||||
|
|
||||||
setupTests(test);
|
|
||||||
|
|
||||||
test.serial(
|
|
||||||
"analyze action with RAM & threads from environment variables",
|
|
||||||
async (t) => {
|
|
||||||
// This test frequently times out on Windows with the default timeout, so we bump
|
|
||||||
// it a bit to 20s.
|
|
||||||
t.timeout(1000 * 20);
|
|
||||||
await util.withTmpDir(async (tmpDir) => {
|
|
||||||
setupActionsVars(tmpDir, tmpDir);
|
|
||||||
sinon
|
|
||||||
.stub(statusReport, "createStatusReportBase")
|
|
||||||
.resolves({} as statusReport.StatusReportBase);
|
|
||||||
sinon.stub(statusReport, "sendStatusReport").resolves();
|
|
||||||
sinon.stub(gitUtils, "isAnalyzingDefaultBranch").resolves(true);
|
|
||||||
|
|
||||||
const gitHubVersion: util.GitHubVersion = {
|
|
||||||
type: util.GitHubVariant.DOTCOM,
|
|
||||||
};
|
|
||||||
sinon.stub(configUtils, "getConfig").resolves({
|
|
||||||
gitHubVersion,
|
|
||||||
augmentationProperties: {},
|
|
||||||
languages: [],
|
|
||||||
packs: [],
|
|
||||||
trapCaches: {},
|
|
||||||
} as unknown as configUtils.Config);
|
|
||||||
const requiredInputStub = sinon.stub(actionsUtil, "getRequiredInput");
|
|
||||||
requiredInputStub.withArgs("token").returns("fake-token");
|
|
||||||
requiredInputStub.withArgs("upload-database").returns("false");
|
|
||||||
requiredInputStub.withArgs("output").returns("out");
|
|
||||||
const optionalInputStub = sinon.stub(actionsUtil, "getOptionalInput");
|
|
||||||
optionalInputStub.withArgs("expect-error").returns("false");
|
|
||||||
sinon.stub(api, "getGitHubVersion").resolves(gitHubVersion);
|
|
||||||
mockFeatureFlagApiEndpoint(200, {});
|
|
||||||
|
|
||||||
// When there are no action inputs for RAM and threads, the action uses
|
|
||||||
// environment variables (passed down from the init action) to set RAM and
|
|
||||||
// threads usage.
|
|
||||||
process.env["CODEQL_THREADS"] = "-1";
|
|
||||||
process.env["CODEQL_RAM"] = "4992";
|
|
||||||
|
|
||||||
const runFinalizeStub = sinon.stub(analyze, "runFinalize");
|
|
||||||
const runQueriesStub = sinon.stub(analyze, "runQueries");
|
|
||||||
|
|
||||||
await runWrapper();
|
|
||||||
|
|
||||||
t.assert(
|
|
||||||
runFinalizeStub.calledOnceWith(
|
|
||||||
sinon.match.any,
|
|
||||||
sinon.match.any,
|
|
||||||
"--threads=-1",
|
|
||||||
"--ram=4992",
|
|
||||||
),
|
|
||||||
);
|
|
||||||
t.assert(
|
|
||||||
runQueriesStub.calledOnceWith(
|
|
||||||
sinon.match.any,
|
|
||||||
"--ram=4992",
|
|
||||||
"--threads=-1",
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
test.serial(
|
|
||||||
"analyze action with RAM & threads from action inputs",
|
|
||||||
async (t) => {
|
|
||||||
t.timeout(1000 * 20);
|
|
||||||
await util.withTmpDir(async (tmpDir) => {
|
|
||||||
setupActionsVars(tmpDir, tmpDir);
|
|
||||||
sinon
|
|
||||||
.stub(statusReport, "createStatusReportBase")
|
|
||||||
.resolves({} as statusReport.StatusReportBase);
|
|
||||||
sinon.stub(statusReport, "sendStatusReport").resolves();
|
|
||||||
const gitHubVersion: util.GitHubVersion = {
|
|
||||||
type: util.GitHubVariant.DOTCOM,
|
|
||||||
};
|
|
||||||
sinon.stub(configUtils, "getConfig").resolves({
|
|
||||||
gitHubVersion,
|
|
||||||
augmentationProperties: {},
|
|
||||||
languages: [],
|
|
||||||
packs: [],
|
|
||||||
trapCaches: {},
|
|
||||||
} as unknown as configUtils.Config);
|
|
||||||
const requiredInputStub = sinon.stub(actionsUtil, "getRequiredInput");
|
|
||||||
requiredInputStub.withArgs("token").returns("fake-token");
|
|
||||||
requiredInputStub.withArgs("upload-database").returns("false");
|
|
||||||
requiredInputStub.withArgs("output").returns("out");
|
|
||||||
const optionalInputStub = sinon.stub(actionsUtil, "getOptionalInput");
|
|
||||||
optionalInputStub.withArgs("expect-error").returns("false");
|
|
||||||
sinon.stub(api, "getGitHubVersion").resolves(gitHubVersion);
|
|
||||||
sinon.stub(gitUtils, "isAnalyzingDefaultBranch").resolves(true);
|
|
||||||
mockFeatureFlagApiEndpoint(200, {});
|
|
||||||
|
|
||||||
process.env["CODEQL_THREADS"] = "1";
|
|
||||||
process.env["CODEQL_RAM"] = "4992";
|
|
||||||
|
|
||||||
// Action inputs have precedence over environment variables.
|
|
||||||
optionalInputStub.withArgs("threads").returns("-1");
|
|
||||||
optionalInputStub.withArgs("ram").returns("3012");
|
|
||||||
|
|
||||||
const runFinalizeStub = sinon.stub(analyze, "runFinalize");
|
|
||||||
const runQueriesStub = sinon.stub(analyze, "runQueries");
|
|
||||||
|
|
||||||
await runWrapper();
|
|
||||||
|
|
||||||
t.assert(
|
|
||||||
runFinalizeStub.calledOnceWith(
|
|
||||||
sinon.match.any,
|
|
||||||
sinon.match.any,
|
|
||||||
"--threads=-1",
|
|
||||||
"--ram=3012",
|
|
||||||
),
|
|
||||||
);
|
|
||||||
t.assert(
|
|
||||||
runQueriesStub.calledOnceWith(
|
|
||||||
sinon.match.any,
|
|
||||||
"--ram=3012",
|
|
||||||
"--threads=-1",
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
);
|
|
||||||
+11
-6
@@ -28,7 +28,7 @@ import {
|
|||||||
DependencyCacheUploadStatusReport,
|
DependencyCacheUploadStatusReport,
|
||||||
uploadDependencyCaches,
|
uploadDependencyCaches,
|
||||||
} from "./dependency-caching";
|
} from "./dependency-caching";
|
||||||
import { EnvVar, exportVariable } from "./environment";
|
import { EnvVar } from "./environment";
|
||||||
import { initFeatures } from "./feature-flags";
|
import { initFeatures } from "./feature-flags";
|
||||||
import { BuiltInLanguage } from "./languages";
|
import { BuiltInLanguage } from "./languages";
|
||||||
import { getActionsLogger, Logger } from "./logging";
|
import { getActionsLogger, Logger } from "./logging";
|
||||||
@@ -284,7 +284,7 @@ async function run(startedAt: Date) {
|
|||||||
|
|
||||||
const apiDetails = getApiDetails();
|
const apiDetails = getApiDetails();
|
||||||
const outputDir = actionsUtil.getRequiredInput("output");
|
const outputDir = actionsUtil.getRequiredInput("output");
|
||||||
exportVariable(EnvVar.SARIF_RESULTS_OUTPUT_DIR, outputDir);
|
core.exportVariable(EnvVar.SARIF_RESULTS_OUTPUT_DIR, outputDir);
|
||||||
const threads = util.getThreadsFlag(
|
const threads = util.getThreadsFlag(
|
||||||
actionsUtil.getOptionalInput("threads") || process.env["CODEQL_THREADS"],
|
actionsUtil.getOptionalInput("threads") || process.env["CODEQL_THREADS"],
|
||||||
logger,
|
logger,
|
||||||
@@ -444,7 +444,7 @@ async function run(startedAt: Date) {
|
|||||||
`expect-error input was set to true but no error was thrown.`,
|
`expect-error input was set to true but no error was thrown.`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
exportVariable(EnvVar.ANALYZE_DID_COMPLETE_SUCCESSFULLY, "true");
|
core.exportVariable(EnvVar.ANALYZE_DID_COMPLETE_SUCCESSFULLY, "true");
|
||||||
} catch (unwrappedError) {
|
} catch (unwrappedError) {
|
||||||
const error = util.wrapError(unwrappedError);
|
const error = util.wrapError(unwrappedError);
|
||||||
if (
|
if (
|
||||||
@@ -523,11 +523,14 @@ async function run(startedAt: Date) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function runWrapper() {
|
// Module-level startedAt so it can be accessed by runWrapper for error reporting
|
||||||
const startedAt = new Date();
|
const startedAt = new Date();
|
||||||
|
export const runPromise = run(startedAt);
|
||||||
|
|
||||||
|
async function runWrapper() {
|
||||||
const logger = getActionsLogger();
|
const logger = getActionsLogger();
|
||||||
try {
|
try {
|
||||||
await run(startedAt);
|
await runPromise;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
core.setFailed(`analyze action failed: ${util.getErrorMessage(error)}`);
|
core.setFailed(`analyze action failed: ${util.getErrorMessage(error)}`);
|
||||||
await sendUnhandledErrorStatusReport(
|
await sendUnhandledErrorStatusReport(
|
||||||
@@ -539,3 +542,5 @@ export async function runWrapper() {
|
|||||||
}
|
}
|
||||||
await util.checkForTimeout();
|
await util.checkForTimeout();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void runWrapper();
|
||||||
|
|||||||
+7
-24
@@ -3,7 +3,7 @@ import * as githubUtils from "@actions/github/lib/utils";
|
|||||||
import * as retry from "@octokit/plugin-retry";
|
import * as retry from "@octokit/plugin-retry";
|
||||||
|
|
||||||
import { getActionVersion, getRequiredInput } from "./actions-util";
|
import { getActionVersion, getRequiredInput } from "./actions-util";
|
||||||
import { EnvVar, exportVariable } from "./environment";
|
import { EnvVar } from "./environment";
|
||||||
import { Logger } from "./logging";
|
import { Logger } from "./logging";
|
||||||
import { getRepositoryNwo, RepositoryNwo } from "./repository";
|
import { getRepositoryNwo, RepositoryNwo } from "./repository";
|
||||||
import {
|
import {
|
||||||
@@ -128,8 +128,6 @@ export async function getGitHubVersionFromApi(
|
|||||||
|
|
||||||
// Doesn't strictly have to be the meta endpoint as we're only
|
// Doesn't strictly have to be the meta endpoint as we're only
|
||||||
// using the response headers which are available on every request.
|
// using the response headers which are available on every request.
|
||||||
//
|
|
||||||
// See https://docs.github.com/en/rest/meta/meta#get-github-meta-information.
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
|
||||||
const response = await apiClient.rest.meta.get();
|
const response = await apiClient.rest.meta.get();
|
||||||
|
|
||||||
@@ -166,9 +164,6 @@ export async function getGitHubVersion(): Promise<GitHubVersion> {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the path of the currently executing workflow relative to the repository root.
|
* Get the path of the currently executing workflow relative to the repository root.
|
||||||
*
|
|
||||||
* See https://docs.github.com/en/rest/actions/workflow-runs#get-a-workflow-run
|
|
||||||
* and https://docs.github.com/en/rest/actions/workflows#get-a-workflow.
|
|
||||||
*/
|
*/
|
||||||
export async function getWorkflowRelativePath(): Promise<string> {
|
export async function getWorkflowRelativePath(): Promise<string> {
|
||||||
const repo_nwo = getRepositoryNwo();
|
const repo_nwo = getRepositoryNwo();
|
||||||
@@ -216,7 +211,7 @@ export async function getAnalysisKey(): Promise<string> {
|
|||||||
const jobName = getRequiredEnvParam("GITHUB_JOB");
|
const jobName = getRequiredEnvParam("GITHUB_JOB");
|
||||||
|
|
||||||
analysisKey = `${workflowPath}:${jobName}`;
|
analysisKey = `${workflowPath}:${jobName}`;
|
||||||
exportVariable(EnvVar.ANALYSIS_KEY, analysisKey);
|
core.exportVariable(EnvVar.ANALYSIS_KEY, analysisKey);
|
||||||
return analysisKey;
|
return analysisKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -257,13 +252,9 @@ export interface ActionsCacheItem {
|
|||||||
size_in_bytes?: number;
|
size_in_bytes?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** List all Actions cache entries matching the provided key and ref. */
|
||||||
* List all Actions cache entries starting with the provided key prefix and matching the provided ref.
|
|
||||||
*
|
|
||||||
* See https://docs.github.com/en/rest/actions/cache#list-github-actions-caches-for-a-repository.
|
|
||||||
*/
|
|
||||||
export async function listActionsCaches(
|
export async function listActionsCaches(
|
||||||
keyPrefix: string,
|
key: string,
|
||||||
ref?: string,
|
ref?: string,
|
||||||
): Promise<ActionsCacheItem[]> {
|
): Promise<ActionsCacheItem[]> {
|
||||||
const repositoryNwo = getRepositoryNwo();
|
const repositoryNwo = getRepositoryNwo();
|
||||||
@@ -273,17 +264,13 @@ export async function listActionsCaches(
|
|||||||
{
|
{
|
||||||
owner: repositoryNwo.owner,
|
owner: repositoryNwo.owner,
|
||||||
repo: repositoryNwo.repo,
|
repo: repositoryNwo.repo,
|
||||||
key: keyPrefix,
|
key,
|
||||||
ref,
|
ref,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** Delete an Actions cache item by its ID. */
|
||||||
* Delete an Actions cache item by its ID.
|
|
||||||
*
|
|
||||||
* See https://docs.github.com/en/rest/actions/cache#delete-a-github-actions-cache-for-a-repository-using-a-cache-id.
|
|
||||||
*/
|
|
||||||
export async function deleteActionsCache(id: number) {
|
export async function deleteActionsCache(id: number) {
|
||||||
const repositoryNwo = getRepositoryNwo();
|
const repositoryNwo = getRepositoryNwo();
|
||||||
|
|
||||||
@@ -294,11 +281,7 @@ export async function deleteActionsCache(id: number) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** Retrieve all custom repository properties. */
|
||||||
* Retrieve all custom repository properties.
|
|
||||||
*
|
|
||||||
* See https://docs.github.com/en/rest/repos/custom-properties#get-all-custom-property-values-for-a-repository.
|
|
||||||
*/
|
|
||||||
export async function getRepositoryProperties(repositoryNwo: RepositoryNwo) {
|
export async function getRepositoryProperties(repositoryNwo: RepositoryNwo) {
|
||||||
return getApiClient().request("GET /repos/:owner/:repo/properties/values", {
|
return getApiClient().request("GET /repos/:owner/:repo/properties/values", {
|
||||||
owner: repositoryNwo.owner,
|
owner: repositoryNwo.owner,
|
||||||
|
|||||||
@@ -141,9 +141,9 @@ test("scanArtifactsForTokens handles files without tokens", async (t) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// `scanArchiveFile` does not support Windows, so we skip this test there.
|
|
||||||
if (os.platform() !== "win32") {
|
if (os.platform() !== "win32") {
|
||||||
test("scanArtifactsForTokens finds token in debug artifacts", async (t) => {
|
test("scanArtifactsForTokens finds token in debug artifacts", async (t) => {
|
||||||
|
t.timeout(15000); // 15 seconds
|
||||||
const messages: LoggedMessage[] = [];
|
const messages: LoggedMessage[] = [];
|
||||||
const logger = getRecordingLogger(messages, { logToConsole: false });
|
const logger = getRecordingLogger(messages, { logToConsole: false });
|
||||||
// The zip here is a regression test based on
|
// The zip here is a regression test based on
|
||||||
|
|||||||
@@ -156,10 +156,6 @@ async function scanArchiveFile(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (process.platform === "win32") {
|
|
||||||
throw new Error("Scanning archives is not supported on Windows.");
|
|
||||||
}
|
|
||||||
|
|
||||||
const result: ScanResult = {
|
const result: ScanResult = {
|
||||||
scannedFiles: 0,
|
scannedFiles: 0,
|
||||||
findings: [],
|
findings: [],
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import { getGitHubVersion } from "./api-client";
|
|||||||
import { determineAutobuildLanguages, runAutobuild } from "./autobuild";
|
import { determineAutobuildLanguages, runAutobuild } from "./autobuild";
|
||||||
import { getCodeQL } from "./codeql";
|
import { getCodeQL } from "./codeql";
|
||||||
import { Config, getConfig } from "./config-utils";
|
import { Config, getConfig } from "./config-utils";
|
||||||
import { EnvVar, exportVariable } from "./environment";
|
import { EnvVar } from "./environment";
|
||||||
import { Language } from "./languages";
|
import { Language } from "./languages";
|
||||||
import { Logger, getActionsLogger } from "./logging";
|
import { Logger, getActionsLogger } from "./logging";
|
||||||
import {
|
import {
|
||||||
@@ -137,12 +137,12 @@ async function run(startedAt: Date) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
exportVariable(EnvVar.AUTOBUILD_DID_COMPLETE_SUCCESSFULLY, "true");
|
core.exportVariable(EnvVar.AUTOBUILD_DID_COMPLETE_SUCCESSFULLY, "true");
|
||||||
|
|
||||||
await sendCompletedStatusReport(config, logger, startedAt, languages ?? []);
|
await sendCompletedStatusReport(config, logger, startedAt, languages ?? []);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function runWrapper() {
|
async function runWrapper() {
|
||||||
const startedAt = new Date();
|
const startedAt = new Date();
|
||||||
const logger = getActionsLogger();
|
const logger = getActionsLogger();
|
||||||
try {
|
try {
|
||||||
@@ -157,3 +157,5 @@ export async function runWrapper() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void runWrapper();
|
||||||
|
|||||||
+7
-5
@@ -1,9 +1,11 @@
|
|||||||
|
import * as core from "@actions/core";
|
||||||
|
|
||||||
import { getTemporaryDirectory, getWorkflowEventName } from "./actions-util";
|
import { getTemporaryDirectory, getWorkflowEventName } from "./actions-util";
|
||||||
import { getGitHubVersion } from "./api-client";
|
import { getGitHubVersion } from "./api-client";
|
||||||
import { CodeQL, getCodeQL } from "./codeql";
|
import { CodeQL, getCodeQL } from "./codeql";
|
||||||
import * as configUtils from "./config-utils";
|
import * as configUtils from "./config-utils";
|
||||||
import { DocUrl } from "./doc-url";
|
import { DocUrl } from "./doc-url";
|
||||||
import { EnvVar, exportVariable } from "./environment";
|
import { EnvVar } from "./environment";
|
||||||
import { Feature, featureConfig, initFeatures } from "./feature-flags";
|
import { Feature, featureConfig, initFeatures } from "./feature-flags";
|
||||||
import { BuiltInLanguage, Language } from "./languages";
|
import { BuiltInLanguage, Language } from "./languages";
|
||||||
import { Logger } from "./logging";
|
import { Logger } from "./logging";
|
||||||
@@ -134,16 +136,16 @@ export async function setupCppAutobuild(codeql: CodeQL, logger: Logger) {
|
|||||||
: ""
|
: ""
|
||||||
}`,
|
}`,
|
||||||
);
|
);
|
||||||
exportVariable(envVar, "false");
|
core.exportVariable(envVar, "false");
|
||||||
} else {
|
} else {
|
||||||
logger.info(
|
logger.info(
|
||||||
`Enabling ${featureName}. This can be disabled by setting the ${envVar} environment variable to 'false'. See ${DocUrl.DEFINE_ENV_VARIABLES} for more information.`,
|
`Enabling ${featureName}. This can be disabled by setting the ${envVar} environment variable to 'false'. See ${DocUrl.DEFINE_ENV_VARIABLES} for more information.`,
|
||||||
);
|
);
|
||||||
exportVariable(envVar, "true");
|
core.exportVariable(envVar, "true");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
logger.info(`Disabling ${featureName}.`);
|
logger.info(`Disabling ${featureName}.`);
|
||||||
exportVariable(envVar, "false");
|
core.exportVariable(envVar, "false");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -163,7 +165,7 @@ export async function runAutobuild(
|
|||||||
await codeQL.runAutobuild(config, language);
|
await codeQL.runAutobuild(config, language);
|
||||||
}
|
}
|
||||||
if (language === BuiltInLanguage.go) {
|
if (language === BuiltInLanguage.go) {
|
||||||
exportVariable(EnvVar.DID_AUTOBUILD_GOLANG, "true");
|
core.exportVariable(EnvVar.DID_AUTOBUILD_GOLANG, "true");
|
||||||
}
|
}
|
||||||
logger.endGroup();
|
logger.endGroup();
|
||||||
}
|
}
|
||||||
|
|||||||
+38
-58
@@ -33,7 +33,6 @@ import {
|
|||||||
mockBundleDownloadApi,
|
mockBundleDownloadApi,
|
||||||
makeVersionInfo,
|
makeVersionInfo,
|
||||||
createTestConfig,
|
createTestConfig,
|
||||||
makeMacro,
|
|
||||||
} from "./testing-utils";
|
} from "./testing-utils";
|
||||||
import { ToolsDownloadStatusReport } from "./tools-download";
|
import { ToolsDownloadStatusReport } from "./tools-download";
|
||||||
import * as util from "./util";
|
import * as util from "./util";
|
||||||
@@ -71,10 +70,8 @@ async function installIntoToolcache({
|
|||||||
tmpDir,
|
tmpDir,
|
||||||
util.GitHubVariant.GHES,
|
util.GitHubVariant.GHES,
|
||||||
cliVersion !== undefined
|
cliVersion !== undefined
|
||||||
? { enabledVersions: [{ cliVersion, tagName }] }
|
? { cliVersion, tagName }
|
||||||
: SAMPLE_DEFAULT_CLI_VERSION,
|
: SAMPLE_DEFAULT_CLI_VERSION,
|
||||||
undefined, // rawLanguages
|
|
||||||
false, // useOverlayAwareDefaultCliVersion
|
|
||||||
createFeatures([]),
|
createFeatures([]),
|
||||||
getRunnerLogger(true),
|
getRunnerLogger(true),
|
||||||
false,
|
false,
|
||||||
@@ -146,8 +143,6 @@ test.serial(
|
|||||||
tmpDir,
|
tmpDir,
|
||||||
util.GitHubVariant.DOTCOM,
|
util.GitHubVariant.DOTCOM,
|
||||||
SAMPLE_DEFAULT_CLI_VERSION,
|
SAMPLE_DEFAULT_CLI_VERSION,
|
||||||
undefined, // rawLanguages
|
|
||||||
false, // useOverlayAwareDefaultCliVersion
|
|
||||||
features,
|
features,
|
||||||
getRunnerLogger(true),
|
getRunnerLogger(true),
|
||||||
false,
|
false,
|
||||||
@@ -180,8 +175,6 @@ test.serial(
|
|||||||
tmpDir,
|
tmpDir,
|
||||||
util.GitHubVariant.DOTCOM,
|
util.GitHubVariant.DOTCOM,
|
||||||
SAMPLE_DEFAULT_CLI_VERSION,
|
SAMPLE_DEFAULT_CLI_VERSION,
|
||||||
undefined, // rawLanguages
|
|
||||||
false, // useOverlayAwareDefaultCliVersion
|
|
||||||
features,
|
features,
|
||||||
getRunnerLogger(true),
|
getRunnerLogger(true),
|
||||||
false,
|
false,
|
||||||
@@ -221,8 +214,6 @@ test.serial(
|
|||||||
tmpDir,
|
tmpDir,
|
||||||
util.GitHubVariant.DOTCOM,
|
util.GitHubVariant.DOTCOM,
|
||||||
SAMPLE_DEFAULT_CLI_VERSION,
|
SAMPLE_DEFAULT_CLI_VERSION,
|
||||||
undefined, // rawLanguages
|
|
||||||
false, // useOverlayAwareDefaultCliVersion
|
|
||||||
features,
|
features,
|
||||||
getRunnerLogger(true),
|
getRunnerLogger(true),
|
||||||
false,
|
false,
|
||||||
@@ -273,8 +264,6 @@ for (const {
|
|||||||
tmpDir,
|
tmpDir,
|
||||||
util.GitHubVariant.DOTCOM,
|
util.GitHubVariant.DOTCOM,
|
||||||
SAMPLE_DEFAULT_CLI_VERSION,
|
SAMPLE_DEFAULT_CLI_VERSION,
|
||||||
undefined, // rawLanguages
|
|
||||||
false, // useOverlayAwareDefaultCliVersion
|
|
||||||
features,
|
features,
|
||||||
getRunnerLogger(true),
|
getRunnerLogger(true),
|
||||||
false,
|
false,
|
||||||
@@ -295,11 +284,11 @@ for (const {
|
|||||||
for (const toolcacheVersion of [
|
for (const toolcacheVersion of [
|
||||||
// Test that we use the tools from the toolcache when `SAMPLE_DEFAULT_CLI_VERSION` is requested
|
// Test that we use the tools from the toolcache when `SAMPLE_DEFAULT_CLI_VERSION` is requested
|
||||||
// and `SAMPLE_DEFAULT_CLI_VERSION-` is in the toolcache.
|
// and `SAMPLE_DEFAULT_CLI_VERSION-` is in the toolcache.
|
||||||
SAMPLE_DEFAULT_CLI_VERSION.enabledVersions[0].cliVersion,
|
SAMPLE_DEFAULT_CLI_VERSION.cliVersion,
|
||||||
`${SAMPLE_DEFAULT_CLI_VERSION.enabledVersions[0].cliVersion}-20230101`,
|
`${SAMPLE_DEFAULT_CLI_VERSION.cliVersion}-20230101`,
|
||||||
]) {
|
]) {
|
||||||
test.serial(
|
test.serial(
|
||||||
`uses tools from toolcache when ${SAMPLE_DEFAULT_CLI_VERSION.enabledVersions[0].cliVersion} is requested and ` +
|
`uses tools from toolcache when ${SAMPLE_DEFAULT_CLI_VERSION.cliVersion} is requested and ` +
|
||||||
`${toolcacheVersion} is installed`,
|
`${toolcacheVersion} is installed`,
|
||||||
async (t) => {
|
async (t) => {
|
||||||
const features = createFeatures([]);
|
const features = createFeatures([]);
|
||||||
@@ -319,16 +308,11 @@ for (const toolcacheVersion of [
|
|||||||
tmpDir,
|
tmpDir,
|
||||||
util.GitHubVariant.DOTCOM,
|
util.GitHubVariant.DOTCOM,
|
||||||
SAMPLE_DEFAULT_CLI_VERSION,
|
SAMPLE_DEFAULT_CLI_VERSION,
|
||||||
undefined, // rawLanguages
|
|
||||||
false, // useOverlayAwareDefaultCliVersion
|
|
||||||
features,
|
features,
|
||||||
getRunnerLogger(true),
|
getRunnerLogger(true),
|
||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
t.is(
|
t.is(result.toolsVersion, SAMPLE_DEFAULT_CLI_VERSION.cliVersion);
|
||||||
result.toolsVersion,
|
|
||||||
SAMPLE_DEFAULT_CLI_VERSION.enabledVersions[0].cliVersion,
|
|
||||||
);
|
|
||||||
t.is(result.toolsSource, ToolsSource.Toolcache);
|
t.is(result.toolsSource, ToolsSource.Toolcache);
|
||||||
t.is(result.toolsDownloadStatusReport?.combinedDurationMs, undefined);
|
t.is(result.toolsDownloadStatusReport?.combinedDurationMs, undefined);
|
||||||
t.is(result.toolsDownloadStatusReport?.downloadDurationMs, undefined);
|
t.is(result.toolsDownloadStatusReport?.downloadDurationMs, undefined);
|
||||||
@@ -358,15 +342,9 @@ test.serial(
|
|||||||
tmpDir,
|
tmpDir,
|
||||||
util.GitHubVariant.GHES,
|
util.GitHubVariant.GHES,
|
||||||
{
|
{
|
||||||
enabledVersions: [
|
cliVersion: defaults.cliVersion,
|
||||||
{
|
tagName: defaults.bundleVersion,
|
||||||
cliVersion: defaults.cliVersion,
|
|
||||||
tagName: defaults.bundleVersion,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
undefined, // rawLanguages
|
|
||||||
false, // useOverlayAwareDefaultCliVersion
|
|
||||||
features,
|
features,
|
||||||
getRunnerLogger(true),
|
getRunnerLogger(true),
|
||||||
false,
|
false,
|
||||||
@@ -406,15 +384,9 @@ test.serial(
|
|||||||
tmpDir,
|
tmpDir,
|
||||||
util.GitHubVariant.GHES,
|
util.GitHubVariant.GHES,
|
||||||
{
|
{
|
||||||
enabledVersions: [
|
cliVersion: defaults.cliVersion,
|
||||||
{
|
tagName: defaults.bundleVersion,
|
||||||
cliVersion: defaults.cliVersion,
|
|
||||||
tagName: defaults.bundleVersion,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
undefined, // rawLanguages
|
|
||||||
false, // useOverlayAwareDefaultCliVersion
|
|
||||||
features,
|
features,
|
||||||
getRunnerLogger(true),
|
getRunnerLogger(true),
|
||||||
false,
|
false,
|
||||||
@@ -454,8 +426,6 @@ test.serial(
|
|||||||
tmpDir,
|
tmpDir,
|
||||||
util.GitHubVariant.DOTCOM,
|
util.GitHubVariant.DOTCOM,
|
||||||
SAMPLE_DEFAULT_CLI_VERSION,
|
SAMPLE_DEFAULT_CLI_VERSION,
|
||||||
undefined, // rawLanguages
|
|
||||||
false, // useOverlayAwareDefaultCliVersion
|
|
||||||
features,
|
features,
|
||||||
getRunnerLogger(true),
|
getRunnerLogger(true),
|
||||||
false,
|
false,
|
||||||
@@ -497,8 +467,6 @@ test.serial(
|
|||||||
tmpDir,
|
tmpDir,
|
||||||
util.GitHubVariant.DOTCOM,
|
util.GitHubVariant.DOTCOM,
|
||||||
SAMPLE_DEFAULT_CLI_VERSION,
|
SAMPLE_DEFAULT_CLI_VERSION,
|
||||||
undefined, // rawLanguages
|
|
||||||
false, // useOverlayAwareDefaultCliVersion
|
|
||||||
features,
|
features,
|
||||||
getRunnerLogger(true),
|
getRunnerLogger(true),
|
||||||
false,
|
false,
|
||||||
@@ -572,7 +540,7 @@ test.serial("getExtraOptions throws for bad content", (t) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Test macro for ensuring different variants of injected augmented configurations
|
// Test macro for ensuring different variants of injected augmented configurations
|
||||||
const injectedConfigMacro = makeMacro({
|
const injectedConfigMacro = test.macro({
|
||||||
exec: async (
|
exec: async (
|
||||||
t: ExecutionContext<unknown>,
|
t: ExecutionContext<unknown>,
|
||||||
augmentationProperties: AugmentationProperties,
|
augmentationProperties: AugmentationProperties,
|
||||||
@@ -622,8 +590,9 @@ const injectedConfigMacro = makeMacro({
|
|||||||
`databaseInitCluster() injected config: ${providedTitle}`,
|
`databaseInitCluster() injected config: ${providedTitle}`,
|
||||||
});
|
});
|
||||||
|
|
||||||
injectedConfigMacro.serial(
|
test.serial(
|
||||||
"basic",
|
"basic",
|
||||||
|
injectedConfigMacro,
|
||||||
{
|
{
|
||||||
...defaultAugmentationProperties,
|
...defaultAugmentationProperties,
|
||||||
},
|
},
|
||||||
@@ -631,8 +600,9 @@ injectedConfigMacro.serial(
|
|||||||
{},
|
{},
|
||||||
);
|
);
|
||||||
|
|
||||||
injectedConfigMacro.serial(
|
test.serial(
|
||||||
"injected packs from input",
|
"injected packs from input",
|
||||||
|
injectedConfigMacro,
|
||||||
{
|
{
|
||||||
...defaultAugmentationProperties,
|
...defaultAugmentationProperties,
|
||||||
packsInput: ["xxx", "yyy"],
|
packsInput: ["xxx", "yyy"],
|
||||||
@@ -643,8 +613,9 @@ injectedConfigMacro.serial(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
injectedConfigMacro.serial(
|
test.serial(
|
||||||
"injected packs from input with existing packs combines",
|
"injected packs from input with existing packs combines",
|
||||||
|
injectedConfigMacro,
|
||||||
{
|
{
|
||||||
...defaultAugmentationProperties,
|
...defaultAugmentationProperties,
|
||||||
packsInputCombines: true,
|
packsInputCombines: true,
|
||||||
@@ -664,8 +635,9 @@ injectedConfigMacro.serial(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
injectedConfigMacro.serial(
|
test.serial(
|
||||||
"injected packs from input with existing packs overrides",
|
"injected packs from input with existing packs overrides",
|
||||||
|
injectedConfigMacro,
|
||||||
{
|
{
|
||||||
...defaultAugmentationProperties,
|
...defaultAugmentationProperties,
|
||||||
packsInput: ["xxx", "yyy"],
|
packsInput: ["xxx", "yyy"],
|
||||||
@@ -683,8 +655,9 @@ injectedConfigMacro.serial(
|
|||||||
);
|
);
|
||||||
|
|
||||||
// similar, but with queries
|
// similar, but with queries
|
||||||
injectedConfigMacro.serial(
|
test.serial(
|
||||||
"injected queries from input",
|
"injected queries from input",
|
||||||
|
injectedConfigMacro,
|
||||||
{
|
{
|
||||||
...defaultAugmentationProperties,
|
...defaultAugmentationProperties,
|
||||||
queriesInput: [{ uses: "xxx" }, { uses: "yyy" }],
|
queriesInput: [{ uses: "xxx" }, { uses: "yyy" }],
|
||||||
@@ -702,8 +675,9 @@ injectedConfigMacro.serial(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
injectedConfigMacro.serial(
|
test.serial(
|
||||||
"injected queries from input overrides",
|
"injected queries from input overrides",
|
||||||
|
injectedConfigMacro,
|
||||||
{
|
{
|
||||||
...defaultAugmentationProperties,
|
...defaultAugmentationProperties,
|
||||||
queriesInput: [{ uses: "xxx" }, { uses: "yyy" }],
|
queriesInput: [{ uses: "xxx" }, { uses: "yyy" }],
|
||||||
@@ -725,8 +699,9 @@ injectedConfigMacro.serial(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
injectedConfigMacro.serial(
|
test.serial(
|
||||||
"injected queries from input combines",
|
"injected queries from input combines",
|
||||||
|
injectedConfigMacro,
|
||||||
{
|
{
|
||||||
...defaultAugmentationProperties,
|
...defaultAugmentationProperties,
|
||||||
queriesInputCombines: true,
|
queriesInputCombines: true,
|
||||||
@@ -752,8 +727,9 @@ injectedConfigMacro.serial(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
injectedConfigMacro.serial(
|
test.serial(
|
||||||
"injected queries from input combines 2",
|
"injected queries from input combines 2",
|
||||||
|
injectedConfigMacro,
|
||||||
{
|
{
|
||||||
...defaultAugmentationProperties,
|
...defaultAugmentationProperties,
|
||||||
queriesInputCombines: true,
|
queriesInputCombines: true,
|
||||||
@@ -773,8 +749,9 @@ injectedConfigMacro.serial(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
injectedConfigMacro.serial(
|
test.serial(
|
||||||
"injected queries and packs, but empty",
|
"injected queries and packs, but empty",
|
||||||
|
injectedConfigMacro,
|
||||||
{
|
{
|
||||||
...defaultAugmentationProperties,
|
...defaultAugmentationProperties,
|
||||||
queriesInputCombines: true,
|
queriesInputCombines: true,
|
||||||
@@ -791,8 +768,9 @@ injectedConfigMacro.serial(
|
|||||||
{},
|
{},
|
||||||
);
|
);
|
||||||
|
|
||||||
injectedConfigMacro.serial(
|
test.serial(
|
||||||
"repo property queries have the highest precedence",
|
"repo property queries have the highest precedence",
|
||||||
|
injectedConfigMacro,
|
||||||
{
|
{
|
||||||
...defaultAugmentationProperties,
|
...defaultAugmentationProperties,
|
||||||
queriesInputCombines: true,
|
queriesInputCombines: true,
|
||||||
@@ -812,8 +790,9 @@ injectedConfigMacro.serial(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
injectedConfigMacro.serial(
|
test.serial(
|
||||||
"repo property queries combines with queries input",
|
"repo property queries combines with queries input",
|
||||||
|
injectedConfigMacro,
|
||||||
{
|
{
|
||||||
...defaultAugmentationProperties,
|
...defaultAugmentationProperties,
|
||||||
queriesInputCombines: false,
|
queriesInputCombines: false,
|
||||||
@@ -838,8 +817,9 @@ injectedConfigMacro.serial(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
injectedConfigMacro.serial(
|
test.serial(
|
||||||
"repo property queries combines everything else",
|
"repo property queries combines everything else",
|
||||||
|
injectedConfigMacro,
|
||||||
{
|
{
|
||||||
...defaultAugmentationProperties,
|
...defaultAugmentationProperties,
|
||||||
queriesInputCombines: true,
|
queriesInputCombines: true,
|
||||||
@@ -1072,7 +1052,7 @@ test.serial(
|
|||||||
);
|
);
|
||||||
|
|
||||||
test.serial(
|
test.serial(
|
||||||
"Avoids duplicating --force-overwrite flag if specified in CODEQL_ACTION_EXTRA_OPTIONS",
|
"Avoids duplicating --overwrite flag if specified in CODEQL_ACTION_EXTRA_OPTIONS",
|
||||||
async (t) => {
|
async (t) => {
|
||||||
const runnerConstructorStub = stubToolRunnerConstructor();
|
const runnerConstructorStub = stubToolRunnerConstructor();
|
||||||
const codeqlObject = await stubCodeql();
|
const codeqlObject = await stubCodeql();
|
||||||
@@ -1080,7 +1060,7 @@ test.serial(
|
|||||||
sinon.stub(io, "which").resolves("");
|
sinon.stub(io, "which").resolves("");
|
||||||
|
|
||||||
process.env["CODEQL_ACTION_EXTRA_OPTIONS"] =
|
process.env["CODEQL_ACTION_EXTRA_OPTIONS"] =
|
||||||
'{ "database": { "init": ["--force-overwrite"] } }';
|
'{ "database": { "init": ["--overwrite"] } }';
|
||||||
|
|
||||||
await codeqlObject.databaseInitCluster(
|
await codeqlObject.databaseInitCluster(
|
||||||
stubConfig,
|
stubConfig,
|
||||||
@@ -1093,9 +1073,9 @@ test.serial(
|
|||||||
t.true(runnerConstructorStub.calledOnce);
|
t.true(runnerConstructorStub.calledOnce);
|
||||||
const args = runnerConstructorStub.firstCall.args[1] as string[];
|
const args = runnerConstructorStub.firstCall.args[1] as string[];
|
||||||
t.is(
|
t.is(
|
||||||
args.filter((option: string) => option === "--force-overwrite").length,
|
args.filter((option: string) => option === "--overwrite").length,
|
||||||
1,
|
1,
|
||||||
"--force-overwrite should only be passed once",
|
"--overwrite should only be passed once",
|
||||||
);
|
);
|
||||||
|
|
||||||
// Clean up
|
// Clean up
|
||||||
|
|||||||
+20
-21
@@ -15,7 +15,7 @@ import * as api from "./api-client";
|
|||||||
import { CliError, wrapCliConfigurationError } from "./cli-errors";
|
import { CliError, wrapCliConfigurationError } from "./cli-errors";
|
||||||
import { appendExtraQueryExclusions, type Config } from "./config-utils";
|
import { appendExtraQueryExclusions, type Config } from "./config-utils";
|
||||||
import { DocUrl } from "./doc-url";
|
import { DocUrl } from "./doc-url";
|
||||||
import { EnvVar, exportVariable } from "./environment";
|
import { EnvVar } from "./environment";
|
||||||
import {
|
import {
|
||||||
CodeQLDefaultVersionInfo,
|
CodeQLDefaultVersionInfo,
|
||||||
Feature,
|
Feature,
|
||||||
@@ -277,7 +277,7 @@ let cachedCodeQL: CodeQL | undefined = undefined;
|
|||||||
* The version flags below can be used to conditionally enable certain features
|
* The version flags below can be used to conditionally enable certain features
|
||||||
* on versions newer than this.
|
* on versions newer than this.
|
||||||
*/
|
*/
|
||||||
const CODEQL_MINIMUM_VERSION = "2.19.4";
|
const CODEQL_MINIMUM_VERSION = "2.17.6";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This version will shortly become the oldest version of CodeQL that the Action will run with.
|
* This version will shortly become the oldest version of CodeQL that the Action will run with.
|
||||||
@@ -305,8 +305,6 @@ const EXTRACTION_DEBUG_MODE_VERBOSITY = "progress++";
|
|||||||
* @param tempDir
|
* @param tempDir
|
||||||
* @param variant
|
* @param variant
|
||||||
* @param defaultCliVersion
|
* @param defaultCliVersion
|
||||||
* @param rawLanguages Raw set of languages.
|
|
||||||
* @param useOverlayAwareDefaultCliVersion Whether to select an overlay-aware default CLI version.
|
|
||||||
* @param features Information about the features that are enabled.
|
* @param features Information about the features that are enabled.
|
||||||
* @param logger
|
* @param logger
|
||||||
* @param checkVersion Whether to check that CodeQL CLI meets the minimum
|
* @param checkVersion Whether to check that CodeQL CLI meets the minimum
|
||||||
@@ -319,8 +317,6 @@ export async function setupCodeQL(
|
|||||||
tempDir: string,
|
tempDir: string,
|
||||||
variant: util.GitHubVariant,
|
variant: util.GitHubVariant,
|
||||||
defaultCliVersion: CodeQLDefaultVersionInfo,
|
defaultCliVersion: CodeQLDefaultVersionInfo,
|
||||||
rawLanguages: string[] | undefined,
|
|
||||||
useOverlayAwareDefaultCliVersion: boolean,
|
|
||||||
features: FeatureEnablement,
|
features: FeatureEnablement,
|
||||||
logger: Logger,
|
logger: Logger,
|
||||||
checkVersion: boolean,
|
checkVersion: boolean,
|
||||||
@@ -344,8 +340,6 @@ export async function setupCodeQL(
|
|||||||
tempDir,
|
tempDir,
|
||||||
variant,
|
variant,
|
||||||
defaultCliVersion,
|
defaultCliVersion,
|
||||||
rawLanguages,
|
|
||||||
useOverlayAwareDefaultCliVersion,
|
|
||||||
features,
|
features,
|
||||||
logger,
|
logger,
|
||||||
);
|
);
|
||||||
@@ -592,6 +586,13 @@ async function getCodeQLForCmd(
|
|||||||
extraArgs.push(`--qlconfig-file=${qlconfigFile}`);
|
extraArgs.push(`--qlconfig-file=${qlconfigFile}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const overwriteFlag = isSupportedToolsFeature(
|
||||||
|
await this.getVersion(),
|
||||||
|
ToolsFeature.ForceOverwrite,
|
||||||
|
)
|
||||||
|
? "--force-overwrite"
|
||||||
|
: "--overwrite";
|
||||||
|
|
||||||
const overlayDatabaseMode = config.overlayDatabaseMode;
|
const overlayDatabaseMode = config.overlayDatabaseMode;
|
||||||
if (overlayDatabaseMode === OverlayDatabaseMode.Overlay) {
|
if (overlayDatabaseMode === OverlayDatabaseMode.Overlay) {
|
||||||
const overlayChangesFile = await writeOverlayChangesFile(
|
const overlayChangesFile = await writeOverlayChangesFile(
|
||||||
@@ -618,7 +619,7 @@ async function getCodeQLForCmd(
|
|||||||
"init",
|
"init",
|
||||||
...(overlayDatabaseMode === OverlayDatabaseMode.Overlay
|
...(overlayDatabaseMode === OverlayDatabaseMode.Overlay
|
||||||
? []
|
? []
|
||||||
: ["--force-overwrite"]),
|
: [overwriteFlag]),
|
||||||
"--db-cluster",
|
"--db-cluster",
|
||||||
config.dbLocation,
|
config.dbLocation,
|
||||||
`--source-root=${sourceRoot}`,
|
`--source-root=${sourceRoot}`,
|
||||||
@@ -629,14 +630,7 @@ async function getCodeQLForCmd(
|
|||||||
// Some user configs specify `--no-calculate-baseline` as an additional
|
// Some user configs specify `--no-calculate-baseline` as an additional
|
||||||
// argument to `codeql database init`. Therefore ignore the baseline file
|
// argument to `codeql database init`. Therefore ignore the baseline file
|
||||||
// options here to avoid specifying the same argument twice and erroring.
|
// options here to avoid specifying the same argument twice and erroring.
|
||||||
//
|
ignoringOptions: ["--overwrite", ...baselineFilesOptions],
|
||||||
// Ignore `--overwrite` to avoid passing both `--force-overwrite` and `--overwrite` if
|
|
||||||
// the user has configured `--overwrite`.
|
|
||||||
ignoringOptions: [
|
|
||||||
"--force-overwrite",
|
|
||||||
"--overwrite",
|
|
||||||
...baselineFilesOptions,
|
|
||||||
],
|
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
{ stdin: externalRepositoryToken },
|
{ stdin: externalRepositoryToken },
|
||||||
@@ -853,7 +847,7 @@ async function getCodeQLForCmd(
|
|||||||
"--sarif-group-rules-by-pack",
|
"--sarif-group-rules-by-pack",
|
||||||
"--sarif-include-query-help=always",
|
"--sarif-include-query-help=always",
|
||||||
"--sublanguage-file-coverage",
|
"--sublanguage-file-coverage",
|
||||||
...(await getJobRunUuidSarifOptions()),
|
...(await getJobRunUuidSarifOptions(this)),
|
||||||
...getExtraOptionsFromEnv(["database", "interpret-results"]),
|
...getExtraOptionsFromEnv(["database", "interpret-results"]),
|
||||||
];
|
];
|
||||||
if (sarifRunPropertyFlag !== undefined) {
|
if (sarifRunPropertyFlag !== undefined) {
|
||||||
@@ -1096,7 +1090,7 @@ async function getCodeQLForCmd(
|
|||||||
}' by 'github/codeql-action/*@v${getActionVersion()}' in your code scanning workflow to ` +
|
}' by 'github/codeql-action/*@v${getActionVersion()}' in your code scanning workflow to ` +
|
||||||
"continue using this version of the CodeQL Action.",
|
"continue using this version of the CodeQL Action.",
|
||||||
);
|
);
|
||||||
exportVariable(EnvVar.SUPPRESS_DEPRECATED_SOON_WARNING, "true");
|
core.exportVariable(EnvVar.SUPPRESS_DEPRECATED_SOON_WARNING, "true");
|
||||||
}
|
}
|
||||||
return codeql;
|
return codeql;
|
||||||
}
|
}
|
||||||
@@ -1283,8 +1277,13 @@ function applyAutobuildAzurePipelinesTimeoutFix() {
|
|||||||
].join(" ");
|
].join(" ");
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getJobRunUuidSarifOptions() {
|
async function getJobRunUuidSarifOptions(codeql: CodeQL) {
|
||||||
const jobRunUuid = process.env[EnvVar.JOB_RUN_UUID];
|
const jobRunUuid = process.env[EnvVar.JOB_RUN_UUID];
|
||||||
|
|
||||||
return jobRunUuid ? [`--sarif-run-property=jobRunUuid=${jobRunUuid}`] : [];
|
return jobRunUuid &&
|
||||||
|
(await codeql.supportsFeature(
|
||||||
|
ToolsFeature.DatabaseInterpretResultsSupportsSarifRunProperty,
|
||||||
|
))
|
||||||
|
? [`--sarif-run-property=jobRunUuid=${jobRunUuid}`]
|
||||||
|
: [];
|
||||||
}
|
}
|
||||||
|
|||||||
+127
-155
@@ -21,7 +21,6 @@ import { GitVersionInfo } from "./git-utils";
|
|||||||
import { BuiltInLanguage, Language } from "./languages";
|
import { BuiltInLanguage, Language } from "./languages";
|
||||||
import { getRunnerLogger } from "./logging";
|
import { getRunnerLogger } from "./logging";
|
||||||
import { CODEQL_OVERLAY_MINIMUM_VERSION } from "./overlay";
|
import { CODEQL_OVERLAY_MINIMUM_VERSION } from "./overlay";
|
||||||
import * as overlayDiagnostics from "./overlay/diagnostics";
|
|
||||||
import { OverlayDisabledReason } from "./overlay/diagnostics";
|
import { OverlayDisabledReason } from "./overlay/diagnostics";
|
||||||
import { OverlayDatabaseMode } from "./overlay/overlay-database-mode";
|
import { OverlayDatabaseMode } from "./overlay/overlay-database-mode";
|
||||||
import * as overlayStatus from "./overlay/status";
|
import * as overlayStatus from "./overlay/status";
|
||||||
@@ -35,7 +34,6 @@ import {
|
|||||||
LoggedMessage,
|
LoggedMessage,
|
||||||
mockCodeQLVersion,
|
mockCodeQLVersion,
|
||||||
createTestConfig,
|
createTestConfig,
|
||||||
makeMacro,
|
|
||||||
} from "./testing-utils";
|
} from "./testing-utils";
|
||||||
import {
|
import {
|
||||||
GitHubVariant,
|
GitHubVariant,
|
||||||
@@ -1036,9 +1034,10 @@ const defaultOverlayDatabaseModeTestSetup: OverlayDatabaseModeTestSetup = {
|
|||||||
repositoryProperties: {},
|
repositoryProperties: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
const checkOverlayEnablementMacro = makeMacro({
|
const checkOverlayEnablementMacro = test.macro({
|
||||||
exec: async (
|
exec: async (
|
||||||
t: ExecutionContext,
|
t: ExecutionContext,
|
||||||
|
_title: string,
|
||||||
setupOverrides: Partial<OverlayDatabaseModeTestSetup>,
|
setupOverrides: Partial<OverlayDatabaseModeTestSetup>,
|
||||||
expected:
|
expected:
|
||||||
| {
|
| {
|
||||||
@@ -1132,10 +1131,11 @@ const checkOverlayEnablementMacro = makeMacro({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
title: (title) => `checkOverlayEnablement: ${title}`,
|
title: (_, title) => `checkOverlayEnablement: ${title}`,
|
||||||
});
|
});
|
||||||
|
|
||||||
checkOverlayEnablementMacro.serial(
|
test.serial(
|
||||||
|
checkOverlayEnablementMacro,
|
||||||
"Environment variable override - Overlay",
|
"Environment variable override - Overlay",
|
||||||
{
|
{
|
||||||
overlayDatabaseEnvVar: "overlay",
|
overlayDatabaseEnvVar: "overlay",
|
||||||
@@ -1146,7 +1146,8 @@ checkOverlayEnablementMacro.serial(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
checkOverlayEnablementMacro.serial(
|
test.serial(
|
||||||
|
checkOverlayEnablementMacro,
|
||||||
"Environment variable override - OverlayBase",
|
"Environment variable override - OverlayBase",
|
||||||
{
|
{
|
||||||
overlayDatabaseEnvVar: "overlay-base",
|
overlayDatabaseEnvVar: "overlay-base",
|
||||||
@@ -1157,7 +1158,8 @@ checkOverlayEnablementMacro.serial(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
checkOverlayEnablementMacro.serial(
|
test.serial(
|
||||||
|
checkOverlayEnablementMacro,
|
||||||
"Environment variable override - None",
|
"Environment variable override - None",
|
||||||
{
|
{
|
||||||
overlayDatabaseEnvVar: "none",
|
overlayDatabaseEnvVar: "none",
|
||||||
@@ -1167,7 +1169,8 @@ checkOverlayEnablementMacro.serial(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
checkOverlayEnablementMacro.serial(
|
test.serial(
|
||||||
|
checkOverlayEnablementMacro,
|
||||||
"Ignore invalid environment variable",
|
"Ignore invalid environment variable",
|
||||||
{
|
{
|
||||||
overlayDatabaseEnvVar: "invalid-mode",
|
overlayDatabaseEnvVar: "invalid-mode",
|
||||||
@@ -1177,7 +1180,8 @@ checkOverlayEnablementMacro.serial(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
checkOverlayEnablementMacro.serial(
|
test.serial(
|
||||||
|
checkOverlayEnablementMacro,
|
||||||
"Ignore feature flag when analyzing non-default branch",
|
"Ignore feature flag when analyzing non-default branch",
|
||||||
{
|
{
|
||||||
languages: [BuiltInLanguage.javascript],
|
languages: [BuiltInLanguage.javascript],
|
||||||
@@ -1188,7 +1192,8 @@ checkOverlayEnablementMacro.serial(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
checkOverlayEnablementMacro.serial(
|
test.serial(
|
||||||
|
checkOverlayEnablementMacro,
|
||||||
"Overlay-base database on default branch when feature enabled",
|
"Overlay-base database on default branch when feature enabled",
|
||||||
{
|
{
|
||||||
languages: [BuiltInLanguage.javascript],
|
languages: [BuiltInLanguage.javascript],
|
||||||
@@ -1201,14 +1206,15 @@ checkOverlayEnablementMacro.serial(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
checkOverlayEnablementMacro.serial(
|
test.serial(
|
||||||
|
checkOverlayEnablementMacro,
|
||||||
"Overlay-base database on default branch when feature enabled with custom analysis",
|
"Overlay-base database on default branch when feature enabled with custom analysis",
|
||||||
{
|
{
|
||||||
languages: [BuiltInLanguage.javascript],
|
languages: [BuiltInLanguage.javascript],
|
||||||
features: [Feature.OverlayAnalysis, Feature.OverlayAnalysisJavascript],
|
features: [Feature.OverlayAnalysis, Feature.OverlayAnalysisJavascript],
|
||||||
codeScanningConfig: {
|
codeScanningConfig: {
|
||||||
packs: ["some-custom-pack@1.0.0"],
|
packs: ["some-custom-pack@1.0.0"],
|
||||||
},
|
} as UserConfig,
|
||||||
isDefaultBranch: true,
|
isDefaultBranch: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -1217,7 +1223,8 @@ checkOverlayEnablementMacro.serial(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
checkOverlayEnablementMacro.serial(
|
test.serial(
|
||||||
|
checkOverlayEnablementMacro,
|
||||||
"Overlay-base database on default branch when code-scanning feature enabled",
|
"Overlay-base database on default branch when code-scanning feature enabled",
|
||||||
{
|
{
|
||||||
languages: [BuiltInLanguage.javascript],
|
languages: [BuiltInLanguage.javascript],
|
||||||
@@ -1233,7 +1240,8 @@ checkOverlayEnablementMacro.serial(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
checkOverlayEnablementMacro.serial(
|
test.serial(
|
||||||
|
checkOverlayEnablementMacro,
|
||||||
"No overlay-base database on default branch if runner disk space is too low",
|
"No overlay-base database on default branch if runner disk space is too low",
|
||||||
{
|
{
|
||||||
languages: [BuiltInLanguage.javascript],
|
languages: [BuiltInLanguage.javascript],
|
||||||
@@ -1252,7 +1260,8 @@ checkOverlayEnablementMacro.serial(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
checkOverlayEnablementMacro.serial(
|
test.serial(
|
||||||
|
checkOverlayEnablementMacro,
|
||||||
"No overlay-base database on default branch if we can't determine runner disk space",
|
"No overlay-base database on default branch if we can't determine runner disk space",
|
||||||
{
|
{
|
||||||
languages: [BuiltInLanguage.javascript],
|
languages: [BuiltInLanguage.javascript],
|
||||||
@@ -1268,7 +1277,8 @@ checkOverlayEnablementMacro.serial(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
checkOverlayEnablementMacro.serial(
|
test.serial(
|
||||||
|
checkOverlayEnablementMacro,
|
||||||
"Overlay-base database on default branch if runner disk space is too low and skip resource checks flag is enabled",
|
"Overlay-base database on default branch if runner disk space is too low and skip resource checks flag is enabled",
|
||||||
{
|
{
|
||||||
languages: [BuiltInLanguage.javascript],
|
languages: [BuiltInLanguage.javascript],
|
||||||
@@ -1289,7 +1299,8 @@ checkOverlayEnablementMacro.serial(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
checkOverlayEnablementMacro.serial(
|
test.serial(
|
||||||
|
checkOverlayEnablementMacro,
|
||||||
"No overlay-base database on default branch if runner disk space is below v2 limit and v2 resource checks enabled",
|
"No overlay-base database on default branch if runner disk space is below v2 limit and v2 resource checks enabled",
|
||||||
{
|
{
|
||||||
languages: [BuiltInLanguage.javascript],
|
languages: [BuiltInLanguage.javascript],
|
||||||
@@ -1309,7 +1320,8 @@ checkOverlayEnablementMacro.serial(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
checkOverlayEnablementMacro.serial(
|
test.serial(
|
||||||
|
checkOverlayEnablementMacro,
|
||||||
"Overlay-base database on default branch if runner disk space is between v2 and v1 limits and v2 resource checks enabled",
|
"Overlay-base database on default branch if runner disk space is between v2 and v1 limits and v2 resource checks enabled",
|
||||||
{
|
{
|
||||||
languages: [BuiltInLanguage.javascript],
|
languages: [BuiltInLanguage.javascript],
|
||||||
@@ -1330,7 +1342,8 @@ checkOverlayEnablementMacro.serial(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
checkOverlayEnablementMacro.serial(
|
test.serial(
|
||||||
|
checkOverlayEnablementMacro,
|
||||||
"No overlay-base database on default branch if runner disk space is between v2 and v1 limits and v2 resource checks not enabled",
|
"No overlay-base database on default branch if runner disk space is between v2 and v1 limits and v2 resource checks not enabled",
|
||||||
{
|
{
|
||||||
languages: [BuiltInLanguage.javascript],
|
languages: [BuiltInLanguage.javascript],
|
||||||
@@ -1349,7 +1362,8 @@ checkOverlayEnablementMacro.serial(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
checkOverlayEnablementMacro.serial(
|
test.serial(
|
||||||
|
checkOverlayEnablementMacro,
|
||||||
"No overlay-base database on default branch if memory flag is too low",
|
"No overlay-base database on default branch if memory flag is too low",
|
||||||
{
|
{
|
||||||
languages: [BuiltInLanguage.javascript],
|
languages: [BuiltInLanguage.javascript],
|
||||||
@@ -1365,7 +1379,8 @@ checkOverlayEnablementMacro.serial(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
checkOverlayEnablementMacro.serial(
|
test.serial(
|
||||||
|
checkOverlayEnablementMacro,
|
||||||
"Overlay-base database on default branch if memory flag is too low but CodeQL >= 2.24.3",
|
"Overlay-base database on default branch if memory flag is too low but CodeQL >= 2.24.3",
|
||||||
{
|
{
|
||||||
languages: [BuiltInLanguage.javascript],
|
languages: [BuiltInLanguage.javascript],
|
||||||
@@ -1383,7 +1398,8 @@ checkOverlayEnablementMacro.serial(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
checkOverlayEnablementMacro.serial(
|
test.serial(
|
||||||
|
checkOverlayEnablementMacro,
|
||||||
"Overlay-base database on default branch if memory flag is too low and skip resource checks flag is enabled",
|
"Overlay-base database on default branch if memory flag is too low and skip resource checks flag is enabled",
|
||||||
{
|
{
|
||||||
languages: [BuiltInLanguage.javascript],
|
languages: [BuiltInLanguage.javascript],
|
||||||
@@ -1401,7 +1417,8 @@ checkOverlayEnablementMacro.serial(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
checkOverlayEnablementMacro.serial(
|
test.serial(
|
||||||
|
checkOverlayEnablementMacro,
|
||||||
"No overlay-base database on default branch when cached status indicates previous failure",
|
"No overlay-base database on default branch when cached status indicates previous failure",
|
||||||
{
|
{
|
||||||
languages: [BuiltInLanguage.javascript],
|
languages: [BuiltInLanguage.javascript],
|
||||||
@@ -1418,7 +1435,8 @@ checkOverlayEnablementMacro.serial(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
checkOverlayEnablementMacro.serial(
|
test.serial(
|
||||||
|
checkOverlayEnablementMacro,
|
||||||
"No overlay analysis on PR when cached status indicates previous failure",
|
"No overlay analysis on PR when cached status indicates previous failure",
|
||||||
{
|
{
|
||||||
languages: [BuiltInLanguage.javascript],
|
languages: [BuiltInLanguage.javascript],
|
||||||
@@ -1435,7 +1453,8 @@ checkOverlayEnablementMacro.serial(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
checkOverlayEnablementMacro.serial(
|
test.serial(
|
||||||
|
checkOverlayEnablementMacro,
|
||||||
"No overlay-base database on default branch when code-scanning feature enabled with disable-default-queries",
|
"No overlay-base database on default branch when code-scanning feature enabled with disable-default-queries",
|
||||||
{
|
{
|
||||||
languages: [BuiltInLanguage.javascript],
|
languages: [BuiltInLanguage.javascript],
|
||||||
@@ -1445,7 +1464,7 @@ checkOverlayEnablementMacro.serial(
|
|||||||
],
|
],
|
||||||
codeScanningConfig: {
|
codeScanningConfig: {
|
||||||
"disable-default-queries": true,
|
"disable-default-queries": true,
|
||||||
},
|
} as UserConfig,
|
||||||
isDefaultBranch: true,
|
isDefaultBranch: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -1453,7 +1472,8 @@ checkOverlayEnablementMacro.serial(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
checkOverlayEnablementMacro.serial(
|
test.serial(
|
||||||
|
checkOverlayEnablementMacro,
|
||||||
"No overlay-base database on default branch when code-scanning feature enabled with packs",
|
"No overlay-base database on default branch when code-scanning feature enabled with packs",
|
||||||
{
|
{
|
||||||
languages: [BuiltInLanguage.javascript],
|
languages: [BuiltInLanguage.javascript],
|
||||||
@@ -1463,7 +1483,7 @@ checkOverlayEnablementMacro.serial(
|
|||||||
],
|
],
|
||||||
codeScanningConfig: {
|
codeScanningConfig: {
|
||||||
packs: ["some-custom-pack@1.0.0"],
|
packs: ["some-custom-pack@1.0.0"],
|
||||||
},
|
} as UserConfig,
|
||||||
isDefaultBranch: true,
|
isDefaultBranch: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -1471,7 +1491,8 @@ checkOverlayEnablementMacro.serial(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
checkOverlayEnablementMacro.serial(
|
test.serial(
|
||||||
|
checkOverlayEnablementMacro,
|
||||||
"No overlay-base database on default branch when code-scanning feature enabled with queries",
|
"No overlay-base database on default branch when code-scanning feature enabled with queries",
|
||||||
{
|
{
|
||||||
languages: [BuiltInLanguage.javascript],
|
languages: [BuiltInLanguage.javascript],
|
||||||
@@ -1481,7 +1502,7 @@ checkOverlayEnablementMacro.serial(
|
|||||||
],
|
],
|
||||||
codeScanningConfig: {
|
codeScanningConfig: {
|
||||||
queries: [{ uses: "some-query.ql" }],
|
queries: [{ uses: "some-query.ql" }],
|
||||||
},
|
} as UserConfig,
|
||||||
isDefaultBranch: true,
|
isDefaultBranch: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -1489,7 +1510,8 @@ checkOverlayEnablementMacro.serial(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
checkOverlayEnablementMacro.serial(
|
test.serial(
|
||||||
|
checkOverlayEnablementMacro,
|
||||||
"No overlay-base database on default branch when code-scanning feature enabled with query-filters",
|
"No overlay-base database on default branch when code-scanning feature enabled with query-filters",
|
||||||
{
|
{
|
||||||
languages: [BuiltInLanguage.javascript],
|
languages: [BuiltInLanguage.javascript],
|
||||||
@@ -1499,7 +1521,7 @@ checkOverlayEnablementMacro.serial(
|
|||||||
],
|
],
|
||||||
codeScanningConfig: {
|
codeScanningConfig: {
|
||||||
"query-filters": [{ include: { "security-severity": "high" } }],
|
"query-filters": [{ include: { "security-severity": "high" } }],
|
||||||
},
|
} as UserConfig,
|
||||||
isDefaultBranch: true,
|
isDefaultBranch: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -1507,7 +1529,8 @@ checkOverlayEnablementMacro.serial(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
checkOverlayEnablementMacro.serial(
|
test.serial(
|
||||||
|
checkOverlayEnablementMacro,
|
||||||
"No overlay-base database on default branch when only language-specific feature enabled",
|
"No overlay-base database on default branch when only language-specific feature enabled",
|
||||||
{
|
{
|
||||||
languages: [BuiltInLanguage.javascript],
|
languages: [BuiltInLanguage.javascript],
|
||||||
@@ -1519,7 +1542,8 @@ checkOverlayEnablementMacro.serial(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
checkOverlayEnablementMacro.serial(
|
test.serial(
|
||||||
|
checkOverlayEnablementMacro,
|
||||||
"No overlay-base database on default branch when only code-scanning feature enabled",
|
"No overlay-base database on default branch when only code-scanning feature enabled",
|
||||||
{
|
{
|
||||||
languages: [BuiltInLanguage.javascript],
|
languages: [BuiltInLanguage.javascript],
|
||||||
@@ -1531,7 +1555,8 @@ checkOverlayEnablementMacro.serial(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
checkOverlayEnablementMacro.serial(
|
test.serial(
|
||||||
|
checkOverlayEnablementMacro,
|
||||||
"No overlay-base database on default branch when language-specific feature disabled",
|
"No overlay-base database on default branch when language-specific feature disabled",
|
||||||
{
|
{
|
||||||
languages: [BuiltInLanguage.javascript],
|
languages: [BuiltInLanguage.javascript],
|
||||||
@@ -1543,7 +1568,8 @@ checkOverlayEnablementMacro.serial(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
checkOverlayEnablementMacro.serial(
|
test.serial(
|
||||||
|
checkOverlayEnablementMacro,
|
||||||
"Overlay analysis on PR when feature enabled",
|
"Overlay analysis on PR when feature enabled",
|
||||||
{
|
{
|
||||||
languages: [BuiltInLanguage.javascript],
|
languages: [BuiltInLanguage.javascript],
|
||||||
@@ -1556,14 +1582,15 @@ checkOverlayEnablementMacro.serial(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
checkOverlayEnablementMacro.serial(
|
test.serial(
|
||||||
|
checkOverlayEnablementMacro,
|
||||||
"Overlay analysis on PR when feature enabled with custom analysis",
|
"Overlay analysis on PR when feature enabled with custom analysis",
|
||||||
{
|
{
|
||||||
languages: [BuiltInLanguage.javascript],
|
languages: [BuiltInLanguage.javascript],
|
||||||
features: [Feature.OverlayAnalysis, Feature.OverlayAnalysisJavascript],
|
features: [Feature.OverlayAnalysis, Feature.OverlayAnalysisJavascript],
|
||||||
codeScanningConfig: {
|
codeScanningConfig: {
|
||||||
packs: ["some-custom-pack@1.0.0"],
|
packs: ["some-custom-pack@1.0.0"],
|
||||||
},
|
} as UserConfig,
|
||||||
isPullRequest: true,
|
isPullRequest: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -1572,7 +1599,8 @@ checkOverlayEnablementMacro.serial(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
checkOverlayEnablementMacro.serial(
|
test.serial(
|
||||||
|
checkOverlayEnablementMacro,
|
||||||
"Overlay analysis on PR when code-scanning feature enabled",
|
"Overlay analysis on PR when code-scanning feature enabled",
|
||||||
{
|
{
|
||||||
languages: [BuiltInLanguage.javascript],
|
languages: [BuiltInLanguage.javascript],
|
||||||
@@ -1588,7 +1616,8 @@ checkOverlayEnablementMacro.serial(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
checkOverlayEnablementMacro.serial(
|
test.serial(
|
||||||
|
checkOverlayEnablementMacro,
|
||||||
"No overlay analysis on PR if runner disk space is too low",
|
"No overlay analysis on PR if runner disk space is too low",
|
||||||
{
|
{
|
||||||
languages: [BuiltInLanguage.javascript],
|
languages: [BuiltInLanguage.javascript],
|
||||||
@@ -1607,7 +1636,8 @@ checkOverlayEnablementMacro.serial(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
checkOverlayEnablementMacro.serial(
|
test.serial(
|
||||||
|
checkOverlayEnablementMacro,
|
||||||
"Overlay analysis on PR if runner disk space is too low and skip resource checks flag is enabled",
|
"Overlay analysis on PR if runner disk space is too low and skip resource checks flag is enabled",
|
||||||
{
|
{
|
||||||
languages: [BuiltInLanguage.javascript],
|
languages: [BuiltInLanguage.javascript],
|
||||||
@@ -1628,7 +1658,8 @@ checkOverlayEnablementMacro.serial(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
checkOverlayEnablementMacro.serial(
|
test.serial(
|
||||||
|
checkOverlayEnablementMacro,
|
||||||
"No overlay analysis on PR if we can't determine runner disk space",
|
"No overlay analysis on PR if we can't determine runner disk space",
|
||||||
{
|
{
|
||||||
languages: [BuiltInLanguage.javascript],
|
languages: [BuiltInLanguage.javascript],
|
||||||
@@ -1644,7 +1675,8 @@ checkOverlayEnablementMacro.serial(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
checkOverlayEnablementMacro.serial(
|
test.serial(
|
||||||
|
checkOverlayEnablementMacro,
|
||||||
"No overlay analysis on PR if memory flag is too low",
|
"No overlay analysis on PR if memory flag is too low",
|
||||||
{
|
{
|
||||||
languages: [BuiltInLanguage.javascript],
|
languages: [BuiltInLanguage.javascript],
|
||||||
@@ -1660,7 +1692,8 @@ checkOverlayEnablementMacro.serial(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
checkOverlayEnablementMacro.serial(
|
test.serial(
|
||||||
|
checkOverlayEnablementMacro,
|
||||||
"Overlay analysis on PR if memory flag is too low but CodeQL >= 2.24.3",
|
"Overlay analysis on PR if memory flag is too low but CodeQL >= 2.24.3",
|
||||||
{
|
{
|
||||||
languages: [BuiltInLanguage.javascript],
|
languages: [BuiltInLanguage.javascript],
|
||||||
@@ -1678,7 +1711,8 @@ checkOverlayEnablementMacro.serial(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
checkOverlayEnablementMacro.serial(
|
test.serial(
|
||||||
|
checkOverlayEnablementMacro,
|
||||||
"Overlay analysis on PR if memory flag is too low and skip resource checks flag is enabled",
|
"Overlay analysis on PR if memory flag is too low and skip resource checks flag is enabled",
|
||||||
{
|
{
|
||||||
languages: [BuiltInLanguage.javascript],
|
languages: [BuiltInLanguage.javascript],
|
||||||
@@ -1696,7 +1730,8 @@ checkOverlayEnablementMacro.serial(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
checkOverlayEnablementMacro.serial(
|
test.serial(
|
||||||
|
checkOverlayEnablementMacro,
|
||||||
"No overlay analysis on PR when code-scanning feature enabled with disable-default-queries",
|
"No overlay analysis on PR when code-scanning feature enabled with disable-default-queries",
|
||||||
{
|
{
|
||||||
languages: [BuiltInLanguage.javascript],
|
languages: [BuiltInLanguage.javascript],
|
||||||
@@ -1706,7 +1741,7 @@ checkOverlayEnablementMacro.serial(
|
|||||||
],
|
],
|
||||||
codeScanningConfig: {
|
codeScanningConfig: {
|
||||||
"disable-default-queries": true,
|
"disable-default-queries": true,
|
||||||
},
|
} as UserConfig,
|
||||||
isPullRequest: true,
|
isPullRequest: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -1714,7 +1749,8 @@ checkOverlayEnablementMacro.serial(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
checkOverlayEnablementMacro.serial(
|
test.serial(
|
||||||
|
checkOverlayEnablementMacro,
|
||||||
"No overlay analysis on PR when code-scanning feature enabled with packs",
|
"No overlay analysis on PR when code-scanning feature enabled with packs",
|
||||||
{
|
{
|
||||||
languages: [BuiltInLanguage.javascript],
|
languages: [BuiltInLanguage.javascript],
|
||||||
@@ -1724,7 +1760,7 @@ checkOverlayEnablementMacro.serial(
|
|||||||
],
|
],
|
||||||
codeScanningConfig: {
|
codeScanningConfig: {
|
||||||
packs: ["some-custom-pack@1.0.0"],
|
packs: ["some-custom-pack@1.0.0"],
|
||||||
},
|
} as UserConfig,
|
||||||
isPullRequest: true,
|
isPullRequest: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -1732,7 +1768,8 @@ checkOverlayEnablementMacro.serial(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
checkOverlayEnablementMacro.serial(
|
test.serial(
|
||||||
|
checkOverlayEnablementMacro,
|
||||||
"No overlay analysis on PR when code-scanning feature enabled with queries",
|
"No overlay analysis on PR when code-scanning feature enabled with queries",
|
||||||
{
|
{
|
||||||
languages: [BuiltInLanguage.javascript],
|
languages: [BuiltInLanguage.javascript],
|
||||||
@@ -1742,7 +1779,7 @@ checkOverlayEnablementMacro.serial(
|
|||||||
],
|
],
|
||||||
codeScanningConfig: {
|
codeScanningConfig: {
|
||||||
queries: [{ uses: "some-query.ql" }],
|
queries: [{ uses: "some-query.ql" }],
|
||||||
},
|
} as UserConfig,
|
||||||
isPullRequest: true,
|
isPullRequest: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -1750,7 +1787,8 @@ checkOverlayEnablementMacro.serial(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
checkOverlayEnablementMacro.serial(
|
test.serial(
|
||||||
|
checkOverlayEnablementMacro,
|
||||||
"No overlay analysis on PR when code-scanning feature enabled with query-filters",
|
"No overlay analysis on PR when code-scanning feature enabled with query-filters",
|
||||||
{
|
{
|
||||||
languages: [BuiltInLanguage.javascript],
|
languages: [BuiltInLanguage.javascript],
|
||||||
@@ -1760,7 +1798,7 @@ checkOverlayEnablementMacro.serial(
|
|||||||
],
|
],
|
||||||
codeScanningConfig: {
|
codeScanningConfig: {
|
||||||
"query-filters": [{ include: { "security-severity": "high" } }],
|
"query-filters": [{ include: { "security-severity": "high" } }],
|
||||||
},
|
} as UserConfig,
|
||||||
isPullRequest: true,
|
isPullRequest: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -1768,7 +1806,8 @@ checkOverlayEnablementMacro.serial(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
checkOverlayEnablementMacro.serial(
|
test.serial(
|
||||||
|
checkOverlayEnablementMacro,
|
||||||
"No overlay analysis on PR when only language-specific feature enabled",
|
"No overlay analysis on PR when only language-specific feature enabled",
|
||||||
{
|
{
|
||||||
languages: [BuiltInLanguage.javascript],
|
languages: [BuiltInLanguage.javascript],
|
||||||
@@ -1780,7 +1819,8 @@ checkOverlayEnablementMacro.serial(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
checkOverlayEnablementMacro.serial(
|
test.serial(
|
||||||
|
checkOverlayEnablementMacro,
|
||||||
"No overlay analysis on PR when only code-scanning feature enabled",
|
"No overlay analysis on PR when only code-scanning feature enabled",
|
||||||
{
|
{
|
||||||
languages: [BuiltInLanguage.javascript],
|
languages: [BuiltInLanguage.javascript],
|
||||||
@@ -1792,7 +1832,8 @@ checkOverlayEnablementMacro.serial(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
checkOverlayEnablementMacro.serial(
|
test.serial(
|
||||||
|
checkOverlayEnablementMacro,
|
||||||
"No overlay analysis on PR when language-specific feature disabled",
|
"No overlay analysis on PR when language-specific feature disabled",
|
||||||
{
|
{
|
||||||
languages: [BuiltInLanguage.javascript],
|
languages: [BuiltInLanguage.javascript],
|
||||||
@@ -1804,7 +1845,8 @@ checkOverlayEnablementMacro.serial(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
checkOverlayEnablementMacro.serial(
|
test.serial(
|
||||||
|
checkOverlayEnablementMacro,
|
||||||
"Overlay PR analysis by env",
|
"Overlay PR analysis by env",
|
||||||
{
|
{
|
||||||
overlayDatabaseEnvVar: "overlay",
|
overlayDatabaseEnvVar: "overlay",
|
||||||
@@ -1815,7 +1857,8 @@ checkOverlayEnablementMacro.serial(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
checkOverlayEnablementMacro.serial(
|
test.serial(
|
||||||
|
checkOverlayEnablementMacro,
|
||||||
"Overlay PR analysis by env on a runner with low disk space",
|
"Overlay PR analysis by env on a runner with low disk space",
|
||||||
{
|
{
|
||||||
overlayDatabaseEnvVar: "overlay",
|
overlayDatabaseEnvVar: "overlay",
|
||||||
@@ -1827,7 +1870,8 @@ checkOverlayEnablementMacro.serial(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
checkOverlayEnablementMacro.serial(
|
test.serial(
|
||||||
|
checkOverlayEnablementMacro,
|
||||||
"Overlay PR analysis by feature flag",
|
"Overlay PR analysis by feature flag",
|
||||||
{
|
{
|
||||||
languages: [BuiltInLanguage.javascript],
|
languages: [BuiltInLanguage.javascript],
|
||||||
@@ -1840,7 +1884,8 @@ checkOverlayEnablementMacro.serial(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
checkOverlayEnablementMacro.serial(
|
test.serial(
|
||||||
|
checkOverlayEnablementMacro,
|
||||||
"Fallback due to autobuild with traced language",
|
"Fallback due to autobuild with traced language",
|
||||||
{
|
{
|
||||||
overlayDatabaseEnvVar: "overlay",
|
overlayDatabaseEnvVar: "overlay",
|
||||||
@@ -1852,7 +1897,8 @@ checkOverlayEnablementMacro.serial(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
checkOverlayEnablementMacro.serial(
|
test.serial(
|
||||||
|
checkOverlayEnablementMacro,
|
||||||
"Fallback due to no build mode with traced language",
|
"Fallback due to no build mode with traced language",
|
||||||
{
|
{
|
||||||
overlayDatabaseEnvVar: "overlay",
|
overlayDatabaseEnvVar: "overlay",
|
||||||
@@ -1864,7 +1910,8 @@ checkOverlayEnablementMacro.serial(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
checkOverlayEnablementMacro.serial(
|
test.serial(
|
||||||
|
checkOverlayEnablementMacro,
|
||||||
"Fallback due to old CodeQL version",
|
"Fallback due to old CodeQL version",
|
||||||
{
|
{
|
||||||
overlayDatabaseEnvVar: "overlay",
|
overlayDatabaseEnvVar: "overlay",
|
||||||
@@ -1875,7 +1922,8 @@ checkOverlayEnablementMacro.serial(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
checkOverlayEnablementMacro.serial(
|
test.serial(
|
||||||
|
checkOverlayEnablementMacro,
|
||||||
"Fallback due to missing git root",
|
"Fallback due to missing git root",
|
||||||
{
|
{
|
||||||
overlayDatabaseEnvVar: "overlay",
|
overlayDatabaseEnvVar: "overlay",
|
||||||
@@ -1886,7 +1934,8 @@ checkOverlayEnablementMacro.serial(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
checkOverlayEnablementMacro.serial(
|
test.serial(
|
||||||
|
checkOverlayEnablementMacro,
|
||||||
"Fallback due to old git version with submodules",
|
"Fallback due to old git version with submodules",
|
||||||
{
|
{
|
||||||
overlayDatabaseEnvVar: "overlay",
|
overlayDatabaseEnvVar: "overlay",
|
||||||
@@ -1898,7 +1947,8 @@ checkOverlayEnablementMacro.serial(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
checkOverlayEnablementMacro.serial(
|
test.serial(
|
||||||
|
checkOverlayEnablementMacro,
|
||||||
"Fallback when git version cannot be determined and repo has submodules",
|
"Fallback when git version cannot be determined and repo has submodules",
|
||||||
{
|
{
|
||||||
overlayDatabaseEnvVar: "overlay",
|
overlayDatabaseEnvVar: "overlay",
|
||||||
@@ -1910,7 +1960,8 @@ checkOverlayEnablementMacro.serial(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
checkOverlayEnablementMacro.serial(
|
test.serial(
|
||||||
|
checkOverlayEnablementMacro,
|
||||||
"Overlay enabled when git version cannot be determined and repo has no submodules",
|
"Overlay enabled when git version cannot be determined and repo has no submodules",
|
||||||
{
|
{
|
||||||
overlayDatabaseEnvVar: "overlay",
|
overlayDatabaseEnvVar: "overlay",
|
||||||
@@ -1923,7 +1974,8 @@ checkOverlayEnablementMacro.serial(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
checkOverlayEnablementMacro.serial(
|
test.serial(
|
||||||
|
checkOverlayEnablementMacro,
|
||||||
"No overlay when disabled via repository property",
|
"No overlay when disabled via repository property",
|
||||||
{
|
{
|
||||||
languages: [BuiltInLanguage.javascript],
|
languages: [BuiltInLanguage.javascript],
|
||||||
@@ -1938,7 +1990,8 @@ checkOverlayEnablementMacro.serial(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
checkOverlayEnablementMacro.serial(
|
test.serial(
|
||||||
|
checkOverlayEnablementMacro,
|
||||||
"Overlay not disabled when repository property is false",
|
"Overlay not disabled when repository property is false",
|
||||||
{
|
{
|
||||||
languages: [BuiltInLanguage.javascript],
|
languages: [BuiltInLanguage.javascript],
|
||||||
@@ -1954,7 +2007,8 @@ checkOverlayEnablementMacro.serial(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
checkOverlayEnablementMacro.serial(
|
test.serial(
|
||||||
|
checkOverlayEnablementMacro,
|
||||||
"Environment variable override takes precedence over repository property",
|
"Environment variable override takes precedence over repository property",
|
||||||
{
|
{
|
||||||
overlayDatabaseEnvVar: "overlay",
|
overlayDatabaseEnvVar: "overlay",
|
||||||
@@ -1970,7 +2024,8 @@ checkOverlayEnablementMacro.serial(
|
|||||||
|
|
||||||
// Exercise language-specific overlay analysis features code paths
|
// Exercise language-specific overlay analysis features code paths
|
||||||
for (const language in BuiltInLanguage) {
|
for (const language in BuiltInLanguage) {
|
||||||
checkOverlayEnablementMacro.serial(
|
test.serial(
|
||||||
|
checkOverlayEnablementMacro,
|
||||||
`Check default overlay analysis feature for ${language}`,
|
`Check default overlay analysis feature for ${language}`,
|
||||||
{
|
{
|
||||||
languages: [language],
|
languages: [language],
|
||||||
@@ -1987,7 +2042,8 @@ for (const language in BuiltInLanguage) {
|
|||||||
// overlay analysis enabled, even when the base overlay feature flag is on.
|
// overlay analysis enabled, even when the base overlay feature flag is on.
|
||||||
// Using swift here as it doesn't currently have overlay support — update this if
|
// Using swift here as it doesn't currently have overlay support — update this if
|
||||||
// swift gains overlay support.
|
// swift gains overlay support.
|
||||||
checkOverlayEnablementMacro.serial(
|
test.serial(
|
||||||
|
checkOverlayEnablementMacro,
|
||||||
"No overlay analysis for language without per-language overlay feature flag",
|
"No overlay analysis for language without per-language overlay feature flag",
|
||||||
{
|
{
|
||||||
languages: [BuiltInLanguage.swift],
|
languages: [BuiltInLanguage.swift],
|
||||||
@@ -2144,87 +2200,3 @@ test.serial(
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
test("applyIncrementalAnalysisSettings: no-op when mode is not Overlay and diff ranges are unavailable", async (t) => {
|
|
||||||
const config = createTestConfig({});
|
|
||||||
config.overlayDatabaseMode = OverlayDatabaseMode.None;
|
|
||||||
const codeql = createStubCodeQL({});
|
|
||||||
const logger = getRunnerLogger(true);
|
|
||||||
|
|
||||||
await configUtils.applyIncrementalAnalysisSettings(
|
|
||||||
config,
|
|
||||||
false,
|
|
||||||
codeql,
|
|
||||||
logger,
|
|
||||||
);
|
|
||||||
|
|
||||||
t.is(config.overlayDatabaseMode, OverlayDatabaseMode.None);
|
|
||||||
t.deepEqual(config.extraQueryExclusions, []);
|
|
||||||
});
|
|
||||||
|
|
||||||
test("applyIncrementalAnalysisSettings: keeps overlay mode and adds exclusions when diff ranges are available", async (t) => {
|
|
||||||
const config = createTestConfig({
|
|
||||||
overlayDatabaseMode: OverlayDatabaseMode.Overlay,
|
|
||||||
});
|
|
||||||
const codeql = createStubCodeQL({});
|
|
||||||
const logger = getRunnerLogger(true);
|
|
||||||
|
|
||||||
await configUtils.applyIncrementalAnalysisSettings(
|
|
||||||
config,
|
|
||||||
true,
|
|
||||||
codeql,
|
|
||||||
logger,
|
|
||||||
);
|
|
||||||
|
|
||||||
t.is(config.overlayDatabaseMode, OverlayDatabaseMode.Overlay);
|
|
||||||
t.deepEqual(config.extraQueryExclusions, [
|
|
||||||
{ exclude: { tags: "exclude-from-incremental" } },
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
|
|
||||||
test("applyIncrementalAnalysisSettings: disables overlay analysis when diff ranges are unavailable", async (t) => {
|
|
||||||
const config = createTestConfig({
|
|
||||||
overlayDatabaseMode: OverlayDatabaseMode.Overlay,
|
|
||||||
});
|
|
||||||
config.useOverlayDatabaseCaching = true;
|
|
||||||
const codeql = createStubCodeQL({});
|
|
||||||
const logger = getRunnerLogger(true);
|
|
||||||
const addDiagnosticsStub = sinon
|
|
||||||
.stub(overlayDiagnostics, "addOverlayDisablementDiagnostics")
|
|
||||||
.resolves();
|
|
||||||
|
|
||||||
await configUtils.applyIncrementalAnalysisSettings(
|
|
||||||
config,
|
|
||||||
false,
|
|
||||||
codeql,
|
|
||||||
logger,
|
|
||||||
);
|
|
||||||
|
|
||||||
t.is(config.overlayDatabaseMode, OverlayDatabaseMode.None);
|
|
||||||
t.is(config.useOverlayDatabaseCaching, false);
|
|
||||||
t.deepEqual(config.extraQueryExclusions, []);
|
|
||||||
t.true(addDiagnosticsStub.calledOnce);
|
|
||||||
t.is(
|
|
||||||
addDiagnosticsStub.firstCall.args[2],
|
|
||||||
OverlayDisabledReason.DiffInformedAnalysisNotEnabled,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
test("applyIncrementalAnalysisSettings: adds exclusions for diff-informed-only runs", async (t) => {
|
|
||||||
const config = createTestConfig({});
|
|
||||||
config.overlayDatabaseMode = OverlayDatabaseMode.None;
|
|
||||||
const codeql = createStubCodeQL({});
|
|
||||||
const logger = getRunnerLogger(true);
|
|
||||||
|
|
||||||
await configUtils.applyIncrementalAnalysisSettings(
|
|
||||||
config,
|
|
||||||
true,
|
|
||||||
codeql,
|
|
||||||
logger,
|
|
||||||
);
|
|
||||||
|
|
||||||
t.is(config.overlayDatabaseMode, OverlayDatabaseMode.None);
|
|
||||||
t.deepEqual(config.extraQueryExclusions, [
|
|
||||||
{ exclude: { tags: "exclude-from-incremental" } },
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
|
|||||||
+17
-59
@@ -2,6 +2,7 @@ import * as fs from "fs";
|
|||||||
import * as path from "path";
|
import * as path from "path";
|
||||||
import { performance } from "perf_hooks";
|
import { performance } from "perf_hooks";
|
||||||
|
|
||||||
|
import * as core from "@actions/core";
|
||||||
import * as yaml from "js-yaml";
|
import * as yaml from "js-yaml";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@@ -30,8 +31,8 @@ import {
|
|||||||
addNoLanguageDiagnostic,
|
addNoLanguageDiagnostic,
|
||||||
makeTelemetryDiagnostic,
|
makeTelemetryDiagnostic,
|
||||||
} from "./diagnostics";
|
} from "./diagnostics";
|
||||||
import { prepareDiffInformedAnalysis } from "./diff-informed-analysis-utils";
|
import { shouldPerformDiffInformedAnalysis } from "./diff-informed-analysis-utils";
|
||||||
import { EnvVar, exportVariable } from "./environment";
|
import { EnvVar } from "./environment";
|
||||||
import * as errorMessages from "./error-messages";
|
import * as errorMessages from "./error-messages";
|
||||||
import { Feature, FeatureEnablement } from "./feature-flags";
|
import { Feature, FeatureEnablement } from "./feature-flags";
|
||||||
import {
|
import {
|
||||||
@@ -406,7 +407,6 @@ export async function getLanguages(
|
|||||||
return languages;
|
return languages;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Splits the `languages` input into a list of raw languages without checking if they are supported by CodeQL. */
|
|
||||||
export function getRawLanguagesNoAutodetect(
|
export function getRawLanguagesNoAutodetect(
|
||||||
languagesInput: string | undefined,
|
languagesInput: string | undefined,
|
||||||
): string[] {
|
): string[] {
|
||||||
@@ -1044,10 +1044,10 @@ async function setCppTrapCachingEnvironmentVariables(
|
|||||||
);
|
);
|
||||||
} else if (config.trapCaches[BuiltInLanguage.cpp]) {
|
} else if (config.trapCaches[BuiltInLanguage.cpp]) {
|
||||||
logger.info("Enabling TRAP caching for C/C++.");
|
logger.info("Enabling TRAP caching for C/C++.");
|
||||||
exportVariable(envVar, "true");
|
core.exportVariable(envVar, "true");
|
||||||
} else {
|
} else {
|
||||||
logger.debug(`Disabling TRAP caching for C/C++.`);
|
logger.debug(`Disabling TRAP caching for C/C++.`);
|
||||||
exportVariable(envVar, "false");
|
core.exportVariable(envVar, "false");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1076,48 +1076,6 @@ function hasQueryCustomisation(userConfig: UserConfig): boolean {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Finalize the incremental-analysis configuration for this run.
|
|
||||||
*
|
|
||||||
* Overlay analysis has only been validated in combination with diff-informed
|
|
||||||
* analysis, so if `Overlay` mode was selected for a pull request but the diff
|
|
||||||
* ranges could not be computed, fall back to a full non-overlay analysis.
|
|
||||||
*
|
|
||||||
* Query exclusions for incremental-only queries are then applied whenever the
|
|
||||||
* diff ranges are available — which, after the fallback above, is exactly the
|
|
||||||
* set of runs where any kind of incremental analysis (overlay or
|
|
||||||
* diff-informed) is in effect.
|
|
||||||
*/
|
|
||||||
export async function applyIncrementalAnalysisSettings(
|
|
||||||
config: Config,
|
|
||||||
hasDiffRanges: boolean,
|
|
||||||
codeql: CodeQL,
|
|
||||||
logger: Logger,
|
|
||||||
): Promise<void> {
|
|
||||||
if (
|
|
||||||
config.overlayDatabaseMode === OverlayDatabaseMode.Overlay &&
|
|
||||||
!hasDiffRanges
|
|
||||||
) {
|
|
||||||
logger.info(
|
|
||||||
`Reverting overlay database mode to ${OverlayDatabaseMode.None} ` +
|
|
||||||
"because the PR diff ranges could not be computed.",
|
|
||||||
);
|
|
||||||
config.overlayDatabaseMode = OverlayDatabaseMode.None;
|
|
||||||
config.useOverlayDatabaseCaching = false;
|
|
||||||
await addOverlayDisablementDiagnostics(
|
|
||||||
config,
|
|
||||||
codeql,
|
|
||||||
OverlayDisabledReason.DiffInformedAnalysisNotEnabled,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hasDiffRanges) {
|
|
||||||
config.extraQueryExclusions.push({
|
|
||||||
exclude: { tags: "exclude-from-incremental" },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load and return the config.
|
* Load and return the config.
|
||||||
*
|
*
|
||||||
@@ -1272,18 +1230,18 @@ export async function initConfig(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const hasDiffRanges = await prepareDiffInformedAnalysis(
|
if (
|
||||||
inputs.codeql,
|
config.overlayDatabaseMode === OverlayDatabaseMode.Overlay ||
|
||||||
inputs.features,
|
(await shouldPerformDiffInformedAnalysis(
|
||||||
logger,
|
inputs.codeql,
|
||||||
);
|
inputs.features,
|
||||||
|
logger,
|
||||||
await applyIncrementalAnalysisSettings(
|
))
|
||||||
config,
|
) {
|
||||||
hasDiffRanges,
|
config.extraQueryExclusions.push({
|
||||||
inputs.codeql,
|
exclude: { tags: "exclude-from-incremental" },
|
||||||
logger,
|
});
|
||||||
);
|
}
|
||||||
|
|
||||||
if (await isTrapCachingEnabled(features, config.overlayDatabaseMode)) {
|
if (await isTrapCachingEnabled(features, config.overlayDatabaseMode)) {
|
||||||
const { trapCaches, trapCacheDownloadTime } = await downloadCacheWithTime(
|
const { trapCaches, trapCacheDownloadTime } = await downloadCacheWithTime(
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import {
|
|||||||
checkExpectedLogMessages,
|
checkExpectedLogMessages,
|
||||||
getRecordingLogger,
|
getRecordingLogger,
|
||||||
LoggedMessage,
|
LoggedMessage,
|
||||||
makeMacro,
|
|
||||||
} from "../testing-utils";
|
} from "../testing-utils";
|
||||||
import { ConfigurationError, prettyPrintPack } from "../util";
|
import { ConfigurationError, prettyPrintPack } from "../util";
|
||||||
|
|
||||||
@@ -16,7 +15,7 @@ import * as dbConfig from "./db-config";
|
|||||||
/**
|
/**
|
||||||
* Test macro for ensuring the packs block is valid
|
* Test macro for ensuring the packs block is valid
|
||||||
*/
|
*/
|
||||||
const parsePacksMacro = makeMacro({
|
const parsePacksMacro = test.macro({
|
||||||
exec: (
|
exec: (
|
||||||
t: ExecutionContext<unknown>,
|
t: ExecutionContext<unknown>,
|
||||||
packsInput: string,
|
packsInput: string,
|
||||||
@@ -34,7 +33,7 @@ const parsePacksMacro = makeMacro({
|
|||||||
/**
|
/**
|
||||||
* Test macro for testing when the packs block is invalid
|
* Test macro for testing when the packs block is invalid
|
||||||
*/
|
*/
|
||||||
const parsePacksErrorMacro = makeMacro({
|
const parsePacksErrorMacro = test.macro({
|
||||||
exec: (
|
exec: (
|
||||||
t: ExecutionContext<unknown>,
|
t: ExecutionContext<unknown>,
|
||||||
packsInput: string,
|
packsInput: string,
|
||||||
@@ -50,32 +49,34 @@ const parsePacksErrorMacro = makeMacro({
|
|||||||
/**
|
/**
|
||||||
* Test macro for testing when the packs block is invalid
|
* Test macro for testing when the packs block is invalid
|
||||||
*/
|
*/
|
||||||
const invalidPackNameMacro = makeMacro({
|
const invalidPackNameMacro = test.macro({
|
||||||
exec: (t: ExecutionContext, arg: string) =>
|
exec: (t: ExecutionContext, name: string) =>
|
||||||
parsePacksErrorMacro.fn(
|
parsePacksErrorMacro.exec(
|
||||||
t,
|
t,
|
||||||
arg,
|
name,
|
||||||
[BuiltInLanguage.cpp],
|
[BuiltInLanguage.cpp],
|
||||||
new RegExp(`^"${arg}" is not a valid pack$`),
|
new RegExp(`^"${name}" is not a valid pack$`),
|
||||||
),
|
),
|
||||||
title: (_providedTitle: string | undefined, arg: string | undefined) =>
|
title: (_providedTitle: string | undefined, arg: string | undefined) =>
|
||||||
`Invalid pack string: ${arg}`,
|
`Invalid pack string: ${arg}`,
|
||||||
});
|
});
|
||||||
|
|
||||||
parsePacksMacro("no packs", "", [], undefined);
|
test("no packs", parsePacksMacro, "", [], undefined);
|
||||||
parsePacksMacro("two packs", "a/b,c/d@1.2.3", [BuiltInLanguage.cpp], {
|
test("two packs", parsePacksMacro, "a/b,c/d@1.2.3", [BuiltInLanguage.cpp], {
|
||||||
[BuiltInLanguage.cpp]: ["a/b", "c/d@1.2.3"],
|
[BuiltInLanguage.cpp]: ["a/b", "c/d@1.2.3"],
|
||||||
});
|
});
|
||||||
parsePacksMacro(
|
test(
|
||||||
"two packs with spaces",
|
"two packs with spaces",
|
||||||
|
parsePacksMacro,
|
||||||
" a/b , c/d@1.2.3 ",
|
" a/b , c/d@1.2.3 ",
|
||||||
[BuiltInLanguage.cpp],
|
[BuiltInLanguage.cpp],
|
||||||
{
|
{
|
||||||
[BuiltInLanguage.cpp]: ["a/b", "c/d@1.2.3"],
|
[BuiltInLanguage.cpp]: ["a/b", "c/d@1.2.3"],
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
parsePacksErrorMacro(
|
test(
|
||||||
"two packs with language",
|
"two packs with language",
|
||||||
|
parsePacksErrorMacro,
|
||||||
"a/b,c/d@1.2.3",
|
"a/b,c/d@1.2.3",
|
||||||
[BuiltInLanguage.cpp, BuiltInLanguage.java],
|
[BuiltInLanguage.cpp, BuiltInLanguage.java],
|
||||||
new RegExp(
|
new RegExp(
|
||||||
@@ -84,8 +85,9 @@ parsePacksErrorMacro(
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
parsePacksMacro(
|
test(
|
||||||
"packs with other valid names",
|
"packs with other valid names",
|
||||||
|
parsePacksMacro,
|
||||||
[
|
[
|
||||||
// ranges are ok
|
// ranges are ok
|
||||||
"c/d@1.0",
|
"c/d@1.0",
|
||||||
@@ -121,23 +123,23 @@ parsePacksMacro(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
invalidPackNameMacro.test("c"); // all packs require at least a scope and a name
|
test(invalidPackNameMacro, "c"); // all packs require at least a scope and a name
|
||||||
invalidPackNameMacro.test("c-/d");
|
test(invalidPackNameMacro, "c-/d");
|
||||||
invalidPackNameMacro.test("-c/d");
|
test(invalidPackNameMacro, "-c/d");
|
||||||
invalidPackNameMacro.test("c/d_d");
|
test(invalidPackNameMacro, "c/d_d");
|
||||||
invalidPackNameMacro.test("c/d@@");
|
test(invalidPackNameMacro, "c/d@@");
|
||||||
invalidPackNameMacro.test("c/d@1.0.0:");
|
test(invalidPackNameMacro, "c/d@1.0.0:");
|
||||||
invalidPackNameMacro.test("c/d:");
|
test(invalidPackNameMacro, "c/d:");
|
||||||
invalidPackNameMacro.test("c/d:/a");
|
test(invalidPackNameMacro, "c/d:/a");
|
||||||
invalidPackNameMacro.test("@1.0.0:a");
|
test(invalidPackNameMacro, "@1.0.0:a");
|
||||||
invalidPackNameMacro.test("c/d@../a");
|
test(invalidPackNameMacro, "c/d@../a");
|
||||||
invalidPackNameMacro.test("c/d@b/../a");
|
test(invalidPackNameMacro, "c/d@b/../a");
|
||||||
invalidPackNameMacro.test("c/d:z@1");
|
test(invalidPackNameMacro, "c/d:z@1");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test macro for pretty printing pack specs
|
* Test macro for pretty printing pack specs
|
||||||
*/
|
*/
|
||||||
const packSpecPrettyPrintingMacro = makeMacro({
|
const packSpecPrettyPrintingMacro = test.macro({
|
||||||
exec: (t: ExecutionContext, packStr: string, packObj: dbConfig.Pack) => {
|
exec: (t: ExecutionContext, packStr: string, packObj: dbConfig.Pack) => {
|
||||||
const parsed = dbConfig.parsePacksSpecification(packStr);
|
const parsed = dbConfig.parsePacksSpecification(packStr);
|
||||||
t.deepEqual(parsed, packObj, "parsed pack spec is correct");
|
t.deepEqual(parsed, packObj, "parsed pack spec is correct");
|
||||||
@@ -161,35 +163,36 @@ const packSpecPrettyPrintingMacro = makeMacro({
|
|||||||
) => `Prettyprint pack spec: '${packStr}'`,
|
) => `Prettyprint pack spec: '${packStr}'`,
|
||||||
});
|
});
|
||||||
|
|
||||||
packSpecPrettyPrintingMacro.test("a/b", {
|
test(packSpecPrettyPrintingMacro, "a/b", {
|
||||||
name: "a/b",
|
name: "a/b",
|
||||||
version: undefined,
|
version: undefined,
|
||||||
path: undefined,
|
path: undefined,
|
||||||
});
|
});
|
||||||
packSpecPrettyPrintingMacro.test("a/b@~1.2.3", {
|
test(packSpecPrettyPrintingMacro, "a/b@~1.2.3", {
|
||||||
name: "a/b",
|
name: "a/b",
|
||||||
version: "~1.2.3",
|
version: "~1.2.3",
|
||||||
path: undefined,
|
path: undefined,
|
||||||
});
|
});
|
||||||
packSpecPrettyPrintingMacro.test("a/b@~1.2.3:abc/def", {
|
test(packSpecPrettyPrintingMacro, "a/b@~1.2.3:abc/def", {
|
||||||
name: "a/b",
|
name: "a/b",
|
||||||
version: "~1.2.3",
|
version: "~1.2.3",
|
||||||
path: "abc/def",
|
path: "abc/def",
|
||||||
});
|
});
|
||||||
packSpecPrettyPrintingMacro.test("a/b:abc/def", {
|
test(packSpecPrettyPrintingMacro, "a/b:abc/def", {
|
||||||
name: "a/b",
|
name: "a/b",
|
||||||
version: undefined,
|
version: undefined,
|
||||||
path: "abc/def",
|
path: "abc/def",
|
||||||
});
|
});
|
||||||
packSpecPrettyPrintingMacro.test(" a/b:abc/def ", {
|
test(packSpecPrettyPrintingMacro, " a/b:abc/def ", {
|
||||||
name: "a/b",
|
name: "a/b",
|
||||||
version: undefined,
|
version: undefined,
|
||||||
path: "abc/def",
|
path: "abc/def",
|
||||||
});
|
});
|
||||||
|
|
||||||
const calculateAugmentationMacro = makeMacro({
|
const calculateAugmentationMacro = test.macro({
|
||||||
exec: async (
|
exec: async (
|
||||||
t: ExecutionContext,
|
t: ExecutionContext,
|
||||||
|
_title: string,
|
||||||
rawPacksInput: string | undefined,
|
rawPacksInput: string | undefined,
|
||||||
rawQueriesInput: string | undefined,
|
rawQueriesInput: string | undefined,
|
||||||
languages: Language[],
|
languages: Language[],
|
||||||
@@ -204,10 +207,11 @@ const calculateAugmentationMacro = makeMacro({
|
|||||||
);
|
);
|
||||||
t.deepEqual(actualAugmentationProperties, expectedAugmentationProperties);
|
t.deepEqual(actualAugmentationProperties, expectedAugmentationProperties);
|
||||||
},
|
},
|
||||||
title: (title) => `Calculate Augmentation: ${title}`,
|
title: (_, title) => `Calculate Augmentation: ${title}`,
|
||||||
});
|
});
|
||||||
|
|
||||||
calculateAugmentationMacro(
|
test(
|
||||||
|
calculateAugmentationMacro,
|
||||||
"All empty",
|
"All empty",
|
||||||
undefined,
|
undefined,
|
||||||
undefined,
|
undefined,
|
||||||
@@ -218,7 +222,8 @@ calculateAugmentationMacro(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
calculateAugmentationMacro(
|
test(
|
||||||
|
calculateAugmentationMacro,
|
||||||
"With queries",
|
"With queries",
|
||||||
undefined,
|
undefined,
|
||||||
" a, b , c, d",
|
" a, b , c, d",
|
||||||
@@ -230,7 +235,8 @@ calculateAugmentationMacro(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
calculateAugmentationMacro(
|
test(
|
||||||
|
calculateAugmentationMacro,
|
||||||
"With queries combining",
|
"With queries combining",
|
||||||
undefined,
|
undefined,
|
||||||
" + a, b , c, d ",
|
" + a, b , c, d ",
|
||||||
@@ -243,7 +249,8 @@ calculateAugmentationMacro(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
calculateAugmentationMacro(
|
test(
|
||||||
|
calculateAugmentationMacro,
|
||||||
"With packs",
|
"With packs",
|
||||||
" codeql/a , codeql/b , codeql/c , codeql/d ",
|
" codeql/a , codeql/b , codeql/c , codeql/d ",
|
||||||
undefined,
|
undefined,
|
||||||
@@ -255,7 +262,8 @@ calculateAugmentationMacro(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
calculateAugmentationMacro(
|
test(
|
||||||
|
calculateAugmentationMacro,
|
||||||
"With packs combining",
|
"With packs combining",
|
||||||
" + codeql/a, codeql/b, codeql/c, codeql/d",
|
" + codeql/a, codeql/b, codeql/c, codeql/d",
|
||||||
undefined,
|
undefined,
|
||||||
@@ -268,7 +276,8 @@ calculateAugmentationMacro(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
calculateAugmentationMacro(
|
test(
|
||||||
|
calculateAugmentationMacro,
|
||||||
"With repo property queries",
|
"With repo property queries",
|
||||||
undefined,
|
undefined,
|
||||||
undefined,
|
undefined,
|
||||||
@@ -285,7 +294,8 @@ calculateAugmentationMacro(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
calculateAugmentationMacro(
|
test(
|
||||||
|
calculateAugmentationMacro,
|
||||||
"With repo property queries combining",
|
"With repo property queries combining",
|
||||||
undefined,
|
undefined,
|
||||||
undefined,
|
undefined,
|
||||||
@@ -302,9 +312,10 @@ calculateAugmentationMacro(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
const calculateAugmentationErrorMacro = makeMacro({
|
const calculateAugmentationErrorMacro = test.macro({
|
||||||
exec: async (
|
exec: async (
|
||||||
t: ExecutionContext,
|
t: ExecutionContext,
|
||||||
|
_title: string,
|
||||||
rawPacksInput: string | undefined,
|
rawPacksInput: string | undefined,
|
||||||
rawQueriesInput: string | undefined,
|
rawQueriesInput: string | undefined,
|
||||||
languages: Language[],
|
languages: Language[],
|
||||||
@@ -322,10 +333,11 @@ const calculateAugmentationErrorMacro = makeMacro({
|
|||||||
{ message: expectedError },
|
{ message: expectedError },
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
title: (title) => `Calculate Augmentation Error: ${title}`,
|
title: (_, title) => `Calculate Augmentation Error: ${title}`,
|
||||||
});
|
});
|
||||||
|
|
||||||
calculateAugmentationErrorMacro(
|
test(
|
||||||
|
calculateAugmentationErrorMacro,
|
||||||
"Plus (+) with nothing else (queries)",
|
"Plus (+) with nothing else (queries)",
|
||||||
undefined,
|
undefined,
|
||||||
" + ",
|
" + ",
|
||||||
@@ -334,7 +346,8 @@ calculateAugmentationErrorMacro(
|
|||||||
/The workflow property "queries" is invalid/,
|
/The workflow property "queries" is invalid/,
|
||||||
);
|
);
|
||||||
|
|
||||||
calculateAugmentationErrorMacro(
|
test(
|
||||||
|
calculateAugmentationErrorMacro,
|
||||||
"Plus (+) with nothing else (packs)",
|
"Plus (+) with nothing else (packs)",
|
||||||
" + ",
|
" + ",
|
||||||
undefined,
|
undefined,
|
||||||
@@ -343,7 +356,8 @@ calculateAugmentationErrorMacro(
|
|||||||
/The workflow property "packs" is invalid/,
|
/The workflow property "packs" is invalid/,
|
||||||
);
|
);
|
||||||
|
|
||||||
calculateAugmentationErrorMacro(
|
test(
|
||||||
|
calculateAugmentationErrorMacro,
|
||||||
"Plus (+) with nothing else (repo property queries)",
|
"Plus (+) with nothing else (repo property queries)",
|
||||||
undefined,
|
undefined,
|
||||||
undefined,
|
undefined,
|
||||||
@@ -354,7 +368,8 @@ calculateAugmentationErrorMacro(
|
|||||||
/The repository property "github-codeql-extra-queries" is invalid/,
|
/The repository property "github-codeql-extra-queries" is invalid/,
|
||||||
);
|
);
|
||||||
|
|
||||||
calculateAugmentationErrorMacro(
|
test(
|
||||||
|
calculateAugmentationErrorMacro,
|
||||||
"Packs input with multiple languages",
|
"Packs input with multiple languages",
|
||||||
" + a/b, c/d ",
|
" + a/b, c/d ",
|
||||||
undefined,
|
undefined,
|
||||||
@@ -363,7 +378,8 @@ calculateAugmentationErrorMacro(
|
|||||||
/Cannot specify a 'packs' input in a multi-language analysis/,
|
/Cannot specify a 'packs' input in a multi-language analysis/,
|
||||||
);
|
);
|
||||||
|
|
||||||
calculateAugmentationErrorMacro(
|
test(
|
||||||
|
calculateAugmentationErrorMacro,
|
||||||
"Packs input with no languages",
|
"Packs input with no languages",
|
||||||
" + a/b, c/d ",
|
" + a/b, c/d ",
|
||||||
undefined,
|
undefined,
|
||||||
@@ -372,7 +388,8 @@ calculateAugmentationErrorMacro(
|
|||||||
/No languages specified/,
|
/No languages specified/,
|
||||||
);
|
);
|
||||||
|
|
||||||
calculateAugmentationErrorMacro(
|
test(
|
||||||
|
calculateAugmentationErrorMacro,
|
||||||
"Invalid packs",
|
"Invalid packs",
|
||||||
" a-pack-without-a-scope ",
|
" a-pack-without-a-scope ",
|
||||||
undefined,
|
undefined,
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import { dbIsFinalized } from "./analyze";
|
|||||||
import { scanArtifactsForTokens } from "./artifact-scanner";
|
import { scanArtifactsForTokens } from "./artifact-scanner";
|
||||||
import { type CodeQL } from "./codeql";
|
import { type CodeQL } from "./codeql";
|
||||||
import { Config } from "./config-utils";
|
import { Config } from "./config-utils";
|
||||||
import { EnvVar, exportVariable } from "./environment";
|
import { EnvVar } from "./environment";
|
||||||
import * as json from "./json";
|
import * as json from "./json";
|
||||||
import { Language } from "./languages";
|
import { Language } from "./languages";
|
||||||
import { Logger, withGroup } from "./logging";
|
import { Logger, withGroup } from "./logging";
|
||||||
@@ -263,7 +263,7 @@ export function getArtifactSuffix(matrix: string | undefined): string {
|
|||||||
try {
|
try {
|
||||||
const matrixObject = JSON.parse(matrix);
|
const matrixObject = JSON.parse(matrix);
|
||||||
if (json.isObject(matrixObject)) {
|
if (json.isObject(matrixObject)) {
|
||||||
for (const matrixKey of Object.keys(matrixObject).sort())
|
for (const matrixKey of Object.keys(matrixObject as object).sort())
|
||||||
suffix += `-${matrixObject[matrixKey]}`;
|
suffix += `-${matrixObject[matrixKey]}`;
|
||||||
} else {
|
} else {
|
||||||
core.warning("User-specified `matrix` input is not an object.");
|
core.warning("User-specified `matrix` input is not an object.");
|
||||||
@@ -330,7 +330,7 @@ export async function uploadArtifacts(
|
|||||||
// some issues early.
|
// some issues early.
|
||||||
if (isInTestMode()) {
|
if (isInTestMode()) {
|
||||||
await scanArtifactsForTokens(toUpload, logger);
|
await scanArtifactsForTokens(toUpload, logger);
|
||||||
exportVariable("CODEQL_ACTION_ARTIFACT_SCAN_FINISHED", "true");
|
core.exportVariable("CODEQL_ACTION_ARTIFACT_SCAN_FINISHED", "true");
|
||||||
}
|
}
|
||||||
|
|
||||||
const suffix = getArtifactSuffix(getOptionalInput("matrix"));
|
const suffix = getArtifactSuffix(getOptionalInput("matrix"));
|
||||||
|
|||||||
+4
-4
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"bundleVersion": "codeql-bundle-v2.25.5",
|
"bundleVersion": "codeql-bundle-v2.25.3",
|
||||||
"cliVersion": "2.25.5",
|
"cliVersion": "2.25.3",
|
||||||
"priorBundleVersion": "codeql-bundle-v2.25.4",
|
"priorBundleVersion": "codeql-bundle-v2.25.2",
|
||||||
"priorCliVersion": "2.25.4"
|
"priorCliVersion": "2.25.2"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,20 +5,17 @@ import * as actionsUtil from "./actions-util";
|
|||||||
import type { PullRequestBranches } from "./actions-util";
|
import type { PullRequestBranches } from "./actions-util";
|
||||||
import * as apiClient from "./api-client";
|
import * as apiClient from "./api-client";
|
||||||
import {
|
import {
|
||||||
getDiffInformedAnalysisBranches,
|
shouldPerformDiffInformedAnalysis,
|
||||||
prepareDiffInformedAnalysis,
|
|
||||||
exportedForTesting,
|
exportedForTesting,
|
||||||
} from "./diff-informed-analysis-utils";
|
} from "./diff-informed-analysis-utils";
|
||||||
import { Feature, FeatureEnablement, initFeatures } from "./feature-flags";
|
import { Feature, initFeatures } from "./feature-flags";
|
||||||
import { getRunnerLogger } from "./logging";
|
import { getRunnerLogger } from "./logging";
|
||||||
import { parseRepositoryNwo } from "./repository";
|
import { parseRepositoryNwo } from "./repository";
|
||||||
import {
|
import {
|
||||||
setupTests,
|
setupTests,
|
||||||
createFeatures,
|
|
||||||
mockCodeQLVersion,
|
mockCodeQLVersion,
|
||||||
mockFeatureFlagApiEndpoint,
|
mockFeatureFlagApiEndpoint,
|
||||||
setupActionsVars,
|
setupActionsVars,
|
||||||
makeMacro,
|
|
||||||
} from "./testing-utils";
|
} from "./testing-utils";
|
||||||
import { GitHubVariant, withTmpDir } from "./util";
|
import { GitHubVariant, withTmpDir } from "./util";
|
||||||
import type { GitHubVersion } from "./util";
|
import type { GitHubVersion } from "./util";
|
||||||
@@ -45,9 +42,10 @@ const defaultTestCase: DiffInformedAnalysisTestCase = {
|
|||||||
codeQLVersion: "2.21.0",
|
codeQLVersion: "2.21.0",
|
||||||
};
|
};
|
||||||
|
|
||||||
const testShouldPerformDiffInformedAnalysis = makeMacro({
|
const testShouldPerformDiffInformedAnalysis = test.macro({
|
||||||
exec: async (
|
exec: async (
|
||||||
t: ExecutionContext,
|
t: ExecutionContext,
|
||||||
|
_title: string,
|
||||||
partialTestCase: Partial<DiffInformedAnalysisTestCase>,
|
partialTestCase: Partial<DiffInformedAnalysisTestCase>,
|
||||||
expectedResult: boolean,
|
expectedResult: boolean,
|
||||||
) => {
|
) => {
|
||||||
@@ -75,34 +73,39 @@ const testShouldPerformDiffInformedAnalysis = makeMacro({
|
|||||||
[Feature.DiffInformedQueries]: testCase.featureEnabled,
|
[Feature.DiffInformedQueries]: testCase.featureEnabled,
|
||||||
});
|
});
|
||||||
|
|
||||||
sinon
|
const getGitHubVersionStub = sinon
|
||||||
.stub(apiClient, "getGitHubVersion")
|
.stub(apiClient, "getGitHubVersion")
|
||||||
.resolves(testCase.gitHubVersion);
|
.resolves(testCase.gitHubVersion);
|
||||||
sinon
|
const getPullRequestBranchesStub = sinon
|
||||||
.stub(actionsUtil, "getPullRequestBranches")
|
.stub(actionsUtil, "getPullRequestBranches")
|
||||||
.returns(testCase.pullRequestBranches);
|
.returns(testCase.pullRequestBranches);
|
||||||
|
|
||||||
const branches = await getDiffInformedAnalysisBranches(
|
const result = await shouldPerformDiffInformedAnalysis(
|
||||||
codeql,
|
codeql,
|
||||||
features,
|
features,
|
||||||
logger,
|
logger,
|
||||||
);
|
);
|
||||||
|
|
||||||
t.is(branches !== undefined, expectedResult);
|
t.is(result, expectedResult);
|
||||||
|
|
||||||
delete process.env.CODEQL_ACTION_DIFF_INFORMED_QUERIES;
|
delete process.env.CODEQL_ACTION_DIFF_INFORMED_QUERIES;
|
||||||
|
|
||||||
|
getGitHubVersionStub.restore();
|
||||||
|
getPullRequestBranchesStub.restore();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
title: (title) => `getDiffInformedAnalysisBranches: ${title}`,
|
title: (_, title) => `shouldPerformDiffInformedAnalysis: ${title}`,
|
||||||
});
|
});
|
||||||
|
|
||||||
testShouldPerformDiffInformedAnalysis.serial(
|
test.serial(
|
||||||
|
testShouldPerformDiffInformedAnalysis,
|
||||||
"returns true in the default test case",
|
"returns true in the default test case",
|
||||||
{},
|
{},
|
||||||
true,
|
true,
|
||||||
);
|
);
|
||||||
|
|
||||||
testShouldPerformDiffInformedAnalysis.serial(
|
test.serial(
|
||||||
|
testShouldPerformDiffInformedAnalysis,
|
||||||
"returns false when feature flag is disabled from the API",
|
"returns false when feature flag is disabled from the API",
|
||||||
{
|
{
|
||||||
featureEnabled: false,
|
featureEnabled: false,
|
||||||
@@ -110,7 +113,8 @@ testShouldPerformDiffInformedAnalysis.serial(
|
|||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
|
|
||||||
testShouldPerformDiffInformedAnalysis.serial(
|
test.serial(
|
||||||
|
testShouldPerformDiffInformedAnalysis,
|
||||||
"returns false when CODEQL_ACTION_DIFF_INFORMED_QUERIES is set to false",
|
"returns false when CODEQL_ACTION_DIFF_INFORMED_QUERIES is set to false",
|
||||||
{
|
{
|
||||||
featureEnabled: true,
|
featureEnabled: true,
|
||||||
@@ -119,7 +123,8 @@ testShouldPerformDiffInformedAnalysis.serial(
|
|||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
|
|
||||||
testShouldPerformDiffInformedAnalysis.serial(
|
test.serial(
|
||||||
|
testShouldPerformDiffInformedAnalysis,
|
||||||
"returns true when CODEQL_ACTION_DIFF_INFORMED_QUERIES is set to true",
|
"returns true when CODEQL_ACTION_DIFF_INFORMED_QUERIES is set to true",
|
||||||
{
|
{
|
||||||
featureEnabled: false,
|
featureEnabled: false,
|
||||||
@@ -128,7 +133,8 @@ testShouldPerformDiffInformedAnalysis.serial(
|
|||||||
true,
|
true,
|
||||||
);
|
);
|
||||||
|
|
||||||
testShouldPerformDiffInformedAnalysis.serial(
|
test.serial(
|
||||||
|
testShouldPerformDiffInformedAnalysis,
|
||||||
"returns false for CodeQL version 2.20.0",
|
"returns false for CodeQL version 2.20.0",
|
||||||
{
|
{
|
||||||
codeQLVersion: "2.20.0",
|
codeQLVersion: "2.20.0",
|
||||||
@@ -136,7 +142,8 @@ testShouldPerformDiffInformedAnalysis.serial(
|
|||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
|
|
||||||
testShouldPerformDiffInformedAnalysis.serial(
|
test.serial(
|
||||||
|
testShouldPerformDiffInformedAnalysis,
|
||||||
"returns false for invalid GHES version",
|
"returns false for invalid GHES version",
|
||||||
{
|
{
|
||||||
gitHubVersion: {
|
gitHubVersion: {
|
||||||
@@ -147,7 +154,8 @@ testShouldPerformDiffInformedAnalysis.serial(
|
|||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
|
|
||||||
testShouldPerformDiffInformedAnalysis.serial(
|
test.serial(
|
||||||
|
testShouldPerformDiffInformedAnalysis,
|
||||||
"returns false for GHES version 3.18.5",
|
"returns false for GHES version 3.18.5",
|
||||||
{
|
{
|
||||||
gitHubVersion: {
|
gitHubVersion: {
|
||||||
@@ -158,7 +166,8 @@ testShouldPerformDiffInformedAnalysis.serial(
|
|||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
|
|
||||||
testShouldPerformDiffInformedAnalysis.serial(
|
test.serial(
|
||||||
|
testShouldPerformDiffInformedAnalysis,
|
||||||
"returns true for GHES version 3.19.0",
|
"returns true for GHES version 3.19.0",
|
||||||
{
|
{
|
||||||
gitHubVersion: {
|
gitHubVersion: {
|
||||||
@@ -169,7 +178,8 @@ testShouldPerformDiffInformedAnalysis.serial(
|
|||||||
true,
|
true,
|
||||||
);
|
);
|
||||||
|
|
||||||
testShouldPerformDiffInformedAnalysis.serial(
|
test.serial(
|
||||||
|
testShouldPerformDiffInformedAnalysis,
|
||||||
"returns false when not a pull request",
|
"returns false when not a pull request",
|
||||||
{
|
{
|
||||||
pullRequestBranches: undefined,
|
pullRequestBranches: undefined,
|
||||||
@@ -177,135 +187,6 @@ testShouldPerformDiffInformedAnalysis.serial(
|
|||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
|
|
||||||
test.serial(
|
|
||||||
"prepareDiffInformedAnalysis: returns false when not a pull request",
|
|
||||||
async (t) => {
|
|
||||||
await withTmpDir(async (tmpDir) => {
|
|
||||||
setupActionsVars(tmpDir, tmpDir);
|
|
||||||
const logger = getRunnerLogger(true);
|
|
||||||
const codeql = mockCodeQLVersion("2.21.0");
|
|
||||||
const features = createFeatures([Feature.DiffInformedQueries]);
|
|
||||||
|
|
||||||
sinon.stub(actionsUtil, "getPullRequestBranches").returns(undefined);
|
|
||||||
sinon
|
|
||||||
.stub(apiClient, "getGitHubVersion")
|
|
||||||
.resolves({ type: GitHubVariant.DOTCOM });
|
|
||||||
|
|
||||||
const result = await prepareDiffInformedAnalysis(
|
|
||||||
codeql,
|
|
||||||
features,
|
|
||||||
logger,
|
|
||||||
);
|
|
||||||
|
|
||||||
t.false(result);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
test.serial(
|
|
||||||
"prepareDiffInformedAnalysis: returns false when applicability check throws",
|
|
||||||
async (t) => {
|
|
||||||
await withTmpDir(async (tmpDir) => {
|
|
||||||
setupActionsVars(tmpDir, tmpDir);
|
|
||||||
const logger = getRunnerLogger(true);
|
|
||||||
const codeql = mockCodeQLVersion("2.21.0");
|
|
||||||
// A features implementation whose getValue rejects, simulating an
|
|
||||||
// unexpected failure when determining whether diff-informed analysis
|
|
||||||
// should run.
|
|
||||||
const features: FeatureEnablement = {
|
|
||||||
getEnabledDefaultCliVersions: async () => {
|
|
||||||
throw new Error("not implemented");
|
|
||||||
},
|
|
||||||
getValue: async () => {
|
|
||||||
throw new Error("feature flag lookup failed");
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const result = await prepareDiffInformedAnalysis(
|
|
||||||
codeql,
|
|
||||||
features,
|
|
||||||
logger,
|
|
||||||
);
|
|
||||||
|
|
||||||
t.false(result);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
test.serial(
|
|
||||||
"prepareDiffInformedAnalysis: returns true when the diff is fetched successfully",
|
|
||||||
async (t) => {
|
|
||||||
await withTmpDir(async (tmpDir) => {
|
|
||||||
setupActionsVars(tmpDir, tmpDir);
|
|
||||||
const logger = getRunnerLogger(true);
|
|
||||||
const codeql = mockCodeQLVersion("2.21.0");
|
|
||||||
const features = createFeatures([Feature.DiffInformedQueries]);
|
|
||||||
|
|
||||||
sinon
|
|
||||||
.stub(actionsUtil, "getPullRequestBranches")
|
|
||||||
.returns({ base: "main", head: "feature" });
|
|
||||||
sinon
|
|
||||||
.stub(apiClient, "getGitHubVersion")
|
|
||||||
.resolves({ type: GitHubVariant.DOTCOM });
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
||||||
sinon.stub(apiClient, "getApiClient").returns({
|
|
||||||
rest: {
|
|
||||||
repos: {
|
|
||||||
compareCommitsWithBasehead: sinon
|
|
||||||
.stub()
|
|
||||||
.resolves({ data: { files: [] } }),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
} as any);
|
|
||||||
|
|
||||||
const result = await prepareDiffInformedAnalysis(
|
|
||||||
codeql,
|
|
||||||
features,
|
|
||||||
logger,
|
|
||||||
);
|
|
||||||
|
|
||||||
t.true(result);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
test.serial(
|
|
||||||
"prepareDiffInformedAnalysis: returns false when the diff API call fails",
|
|
||||||
async (t) => {
|
|
||||||
await withTmpDir(async (tmpDir) => {
|
|
||||||
setupActionsVars(tmpDir, tmpDir);
|
|
||||||
const logger = getRunnerLogger(true);
|
|
||||||
const codeql = mockCodeQLVersion("2.21.0");
|
|
||||||
const features = createFeatures([Feature.DiffInformedQueries]);
|
|
||||||
|
|
||||||
sinon
|
|
||||||
.stub(actionsUtil, "getPullRequestBranches")
|
|
||||||
.returns({ base: "main", head: "feature" });
|
|
||||||
sinon
|
|
||||||
.stub(apiClient, "getGitHubVersion")
|
|
||||||
.resolves({ type: GitHubVariant.DOTCOM });
|
|
||||||
const notFoundError: any = new Error("Not Found");
|
|
||||||
notFoundError.status = 404;
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
||||||
sinon.stub(apiClient, "getApiClient").returns({
|
|
||||||
rest: {
|
|
||||||
repos: {
|
|
||||||
compareCommitsWithBasehead: sinon.stub().rejects(notFoundError),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
} as any);
|
|
||||||
|
|
||||||
const result = await prepareDiffInformedAnalysis(
|
|
||||||
codeql,
|
|
||||||
features,
|
|
||||||
logger,
|
|
||||||
);
|
|
||||||
|
|
||||||
t.false(result);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
function runGetDiffRanges(changes: number, patch: string[] | undefined): any {
|
function runGetDiffRanges(changes: number, patch: string[] | undefined): any {
|
||||||
return exportedForTesting.getDiffRanges(
|
return exportedForTesting.getDiffRanges(
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -5,9 +5,9 @@ import type { PullRequestBranches } from "./actions-util";
|
|||||||
import { getApiClient, getGitHubVersion } from "./api-client";
|
import { getApiClient, getGitHubVersion } from "./api-client";
|
||||||
import type { CodeQL } from "./codeql";
|
import type { CodeQL } from "./codeql";
|
||||||
import { Feature, FeatureEnablement } from "./feature-flags";
|
import { Feature, FeatureEnablement } from "./feature-flags";
|
||||||
import { Logger, withGroupAsync } from "./logging";
|
import { Logger } from "./logging";
|
||||||
import { getRepositoryNwoFromEnv } from "./repository";
|
import { getRepositoryNwoFromEnv } from "./repository";
|
||||||
import { getErrorMessage, GitHubVariant, satisfiesGHESVersion } from "./util";
|
import { GitHubVariant, satisfiesGHESVersion } from "./util";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This interface is an abbreviated version of the file diff object returned by
|
* This interface is an abbreviated version of the file diff object returned by
|
||||||
@@ -21,6 +21,20 @@ interface FileDiff {
|
|||||||
patch?: string | undefined;
|
patch?: string | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the action should perform diff-informed analysis.
|
||||||
|
*/
|
||||||
|
export async function shouldPerformDiffInformedAnalysis(
|
||||||
|
codeql: CodeQL,
|
||||||
|
features: FeatureEnablement,
|
||||||
|
logger: Logger,
|
||||||
|
): Promise<boolean> {
|
||||||
|
return (
|
||||||
|
(await getDiffInformedAnalysisBranches(codeql, features, logger)) !==
|
||||||
|
undefined
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the branches to use for diff-informed analysis.
|
* Get the branches to use for diff-informed analysis.
|
||||||
*
|
*
|
||||||
@@ -55,46 +69,6 @@ export async function getDiffInformedAnalysisBranches(
|
|||||||
return branches;
|
return branches;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Prepares the diff ranges needed for diff-informed analysis for the current
|
|
||||||
* run.
|
|
||||||
*
|
|
||||||
* @returns `true` if the diff ranges were successfully computed and persisted
|
|
||||||
* and are therefore available for use, `false` otherwise.
|
|
||||||
*/
|
|
||||||
export async function prepareDiffInformedAnalysis(
|
|
||||||
codeql: CodeQL,
|
|
||||||
features: FeatureEnablement,
|
|
||||||
logger: Logger,
|
|
||||||
): Promise<boolean> {
|
|
||||||
let branches: PullRequestBranches | undefined;
|
|
||||||
try {
|
|
||||||
branches = await getDiffInformedAnalysisBranches(codeql, features, logger);
|
|
||||||
} catch (e) {
|
|
||||||
// If we cannot determine whether diff-informed analysis applies (for
|
|
||||||
// example, because a feature-flag lookup failed), treat it as not
|
|
||||||
// applicable rather than triggering the overlay fallback.
|
|
||||||
logger.warning(
|
|
||||||
`Failed to determine branch information for diff-informed analysis: ${getErrorMessage(e)}`,
|
|
||||||
);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!branches) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return await withGroupAsync("Computing PR diff ranges", async () => {
|
|
||||||
try {
|
|
||||||
return await computeAndPersistDiffRanges(branches, logger);
|
|
||||||
} catch (e) {
|
|
||||||
logger.warning(
|
|
||||||
`Failed to compute diff-informed analysis ranges: ${getErrorMessage(e)}`,
|
|
||||||
);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface DiffThunkRange {
|
export interface DiffThunkRange {
|
||||||
/** Relative path from the repository root, using forward slashes as separators. */
|
/** Relative path from the repository root, using forward slashes as separators. */
|
||||||
path: string;
|
path: string;
|
||||||
@@ -177,33 +151,6 @@ export async function getPullRequestEditedDiffRanges(
|
|||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Compute and persist the diff ranges for a pull request. This fetches the
|
|
||||||
* diff from the GitHub API and writes it to the diff ranges JSON file so that
|
|
||||||
* CodeQL can use it for diff-informed analysis.
|
|
||||||
*
|
|
||||||
* @param branches The base and head branches of the pull request, as returned
|
|
||||||
* by `getDiffInformedAnalysisBranches`.
|
|
||||||
* @param logger
|
|
||||||
* @returns `true` if the diff ranges were successfully computed and persisted,
|
|
||||||
* otherwise `false`.
|
|
||||||
*/
|
|
||||||
export async function computeAndPersistDiffRanges(
|
|
||||||
branches: PullRequestBranches,
|
|
||||||
logger: Logger,
|
|
||||||
): Promise<boolean> {
|
|
||||||
const ranges = await getPullRequestEditedDiffRanges(branches, logger);
|
|
||||||
if (ranges === undefined) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
writeDiffRangesJsonFile(logger, ranges);
|
|
||||||
const distinctFiles = new Set(ranges.map((r) => r.path)).size;
|
|
||||||
logger.info(
|
|
||||||
`Persisted ${ranges.length} diff range(s) across ${distinctFiles} file(s).`,
|
|
||||||
);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function getFileDiffsWithBasehead(
|
async function getFileDiffsWithBasehead(
|
||||||
branches: PullRequestBranches,
|
branches: PullRequestBranches,
|
||||||
logger: Logger,
|
logger: Logger,
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
export async function run__ACTION__() {
|
|
||||||
return await __ACTION__.runWrapper();
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,3 @@
|
|||||||
import * as core from "@actions/core";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Environment variables used by the CodeQL Action.
|
* Environment variables used by the CodeQL Action.
|
||||||
*
|
*
|
||||||
@@ -156,29 +154,3 @@ export enum EnvVar {
|
|||||||
/** Used by Code Scanning Risk Assessment to communicate the assessment ID to the CodeQL Action. */
|
/** Used by Code Scanning Risk Assessment to communicate the assessment ID to the CodeQL Action. */
|
||||||
RISK_ASSESSMENT_ID = "CODEQL_ACTION_RISK_ASSESSMENT_ID",
|
RISK_ASSESSMENT_ID = "CODEQL_ACTION_RISK_ASSESSMENT_ID",
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns whether we are in test mode. This is used by CodeQL Action PR checks.
|
|
||||||
*
|
|
||||||
* In test mode, we skip several uploads (SARIF results, status reports, DBs, ...).
|
|
||||||
*/
|
|
||||||
export function isInTestMode(): boolean {
|
|
||||||
return process.env[EnvVar.TEST_MODE] === "true";
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wrapper around `core.exportVariable` which does not call `core.exportVariable`
|
|
||||||
* when running unit tests. This is important, because otherwise `core.exportVariable`
|
|
||||||
* sets environment variables for other steps in a workflow when we run unit tests in CI.
|
|
||||||
*/
|
|
||||||
export function exportVariable(name: string, val: any): void {
|
|
||||||
if (process.env["NODE_ENV"] === "test") {
|
|
||||||
// Setting the environment variable for the current process is OK since we reset
|
|
||||||
// those at the end of each test. This allows tests to pass that rely on that
|
|
||||||
// part of the `core.exportVariable` behaviour.
|
|
||||||
process.env[name] = val;
|
|
||||||
} else {
|
|
||||||
// Call `core.exportVariable` whenever we are not in a test environment.
|
|
||||||
core.exportVariable(name, val);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
+12
-27
@@ -451,16 +451,12 @@ test.serial(`selects CLI from defaults.json on GHES`, async (t) => {
|
|||||||
await withTmpDir(async (tmpDir) => {
|
await withTmpDir(async (tmpDir) => {
|
||||||
const features = setUpFeatureFlagTests(tmpDir);
|
const features = setUpFeatureFlagTests(tmpDir);
|
||||||
|
|
||||||
const defaultCliVersion = await features.getEnabledDefaultCliVersions(
|
const defaultCliVersion = await features.getDefaultCliVersion(
|
||||||
GitHubVariant.GHES,
|
GitHubVariant.GHES,
|
||||||
);
|
);
|
||||||
t.deepEqual(defaultCliVersion, {
|
t.deepEqual(defaultCliVersion, {
|
||||||
enabledVersions: [
|
cliVersion: defaults.cliVersion,
|
||||||
{
|
tagName: defaults.bundleVersion,
|
||||||
cliVersion: defaults.cliVersion,
|
|
||||||
tagName: defaults.bundleVersion,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -486,13 +482,10 @@ for (const variant of [GitHubVariant.DOTCOM, GitHubVariant.GHEC_DR]) {
|
|||||||
false;
|
false;
|
||||||
mockFeatureFlagApiEndpoint(200, expectedFeatureEnablement);
|
mockFeatureFlagApiEndpoint(200, expectedFeatureEnablement);
|
||||||
|
|
||||||
const defaultCliVersion =
|
const defaultCliVersion = await features.getDefaultCliVersion(variant);
|
||||||
await features.getEnabledDefaultCliVersions(variant);
|
|
||||||
t.deepEqual(defaultCliVersion, {
|
t.deepEqual(defaultCliVersion, {
|
||||||
enabledVersions: [
|
cliVersion: "2.20.1",
|
||||||
{ cliVersion: "2.20.1", tagName: "codeql-bundle-v2.20.1" },
|
tagName: "codeql-bundle-v2.20.1",
|
||||||
{ cliVersion: "2.20.0", tagName: "codeql-bundle-v2.20.0" },
|
|
||||||
],
|
|
||||||
toolsFeatureFlagsValid: true,
|
toolsFeatureFlagsValid: true,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -507,15 +500,10 @@ for (const variant of [GitHubVariant.DOTCOM, GitHubVariant.GHEC_DR]) {
|
|||||||
const expectedFeatureEnablement = initializeFeatures(true);
|
const expectedFeatureEnablement = initializeFeatures(true);
|
||||||
mockFeatureFlagApiEndpoint(200, expectedFeatureEnablement);
|
mockFeatureFlagApiEndpoint(200, expectedFeatureEnablement);
|
||||||
|
|
||||||
const defaultCliVersion =
|
const defaultCliVersion = await features.getDefaultCliVersion(variant);
|
||||||
await features.getEnabledDefaultCliVersions(variant);
|
|
||||||
t.deepEqual(defaultCliVersion, {
|
t.deepEqual(defaultCliVersion, {
|
||||||
enabledVersions: [
|
cliVersion: defaults.cliVersion,
|
||||||
{
|
tagName: defaults.bundleVersion,
|
||||||
cliVersion: defaults.cliVersion,
|
|
||||||
tagName: defaults.bundleVersion,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
toolsFeatureFlagsValid: false,
|
toolsFeatureFlagsValid: false,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -541,13 +529,10 @@ for (const variant of [GitHubVariant.DOTCOM, GitHubVariant.GHEC_DR]) {
|
|||||||
] = true;
|
] = true;
|
||||||
mockFeatureFlagApiEndpoint(200, expectedFeatureEnablement);
|
mockFeatureFlagApiEndpoint(200, expectedFeatureEnablement);
|
||||||
|
|
||||||
const defaultCliVersion =
|
const defaultCliVersion = await features.getDefaultCliVersion(variant);
|
||||||
await features.getEnabledDefaultCliVersions(variant);
|
|
||||||
t.deepEqual(defaultCliVersion, {
|
t.deepEqual(defaultCliVersion, {
|
||||||
enabledVersions: [
|
cliVersion: "2.20.1",
|
||||||
{ cliVersion: "2.20.1", tagName: "codeql-bundle-v2.20.1" },
|
tagName: "codeql-bundle-v2.20.1",
|
||||||
{ cliVersion: "2.20.0", tagName: "codeql-bundle-v2.20.0" },
|
|
||||||
],
|
|
||||||
toolsFeatureFlagsValid: true,
|
toolsFeatureFlagsValid: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
+25
-86
@@ -26,38 +26,12 @@ const DEFAULT_VERSION_FEATURE_FLAG_SUFFIX = "_enabled";
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The first version of the CodeQL Bundle that shipped with zstd-compressed bundles.
|
* The first version of the CodeQL Bundle that shipped with zstd-compressed bundles.
|
||||||
*
|
|
||||||
* This is now below the minimum version of CodeQL, but we keep this around because we currently set
|
|
||||||
* up CodeQL before checking that the version is new enough.
|
|
||||||
*/
|
*/
|
||||||
export const CODEQL_VERSION_ZSTD_BUNDLE = "2.19.0";
|
export const CODEQL_VERSION_ZSTD_BUNDLE = "2.19.0";
|
||||||
|
|
||||||
const LINKED_CODEQL_VERSION: CodeQLVersionInfo = {
|
|
||||||
cliVersion: defaults.cliVersion,
|
|
||||||
tagName: defaults.bundleVersion,
|
|
||||||
};
|
|
||||||
|
|
||||||
export interface CodeQLVersionInfo {
|
|
||||||
/** The version number of the CodeQL CLI, e.g. `2.19.0`. */
|
|
||||||
cliVersion: string;
|
|
||||||
/**
|
|
||||||
* The tag name of the CodeQL Bundle associated with this version, e.g. `codeql-bundle-v2.19.0`.
|
|
||||||
*/
|
|
||||||
tagName: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface CodeQLDefaultVersionInfo {
|
export interface CodeQLDefaultVersionInfo {
|
||||||
/**
|
cliVersion: string;
|
||||||
* CodeQL CLI versions that are enabled as defaults, sorted from highest to lowest.
|
tagName: string;
|
||||||
*
|
|
||||||
* Guaranteed to be non-empty. When feature flags are unavailable, this falls back to a single
|
|
||||||
* entry containing the version pinned in `defaults.json`.
|
|
||||||
*/
|
|
||||||
enabledVersions: CodeQLVersionInfo[];
|
|
||||||
/**
|
|
||||||
* If accessed, whether the tools feature flags are valid, i.e. contain at least one enabled
|
|
||||||
* version.
|
|
||||||
*/
|
|
||||||
toolsFeatureFlagsValid?: boolean;
|
toolsFeatureFlagsValid?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,8 +44,6 @@ export interface CodeQLDefaultVersionInfo {
|
|||||||
* Legacy features should end with `_enabled`.
|
* Legacy features should end with `_enabled`.
|
||||||
*/
|
*/
|
||||||
export enum Feature {
|
export enum Feature {
|
||||||
/** Controls whether we allow multiple values for the `analysis-kinds` input. */
|
|
||||||
AllowMultipleAnalysisKinds = "allow_multiple_analysis_kinds",
|
|
||||||
AllowToolcacheInput = "allow_toolcache_input",
|
AllowToolcacheInput = "allow_toolcache_input",
|
||||||
CleanupTrapCaches = "cleanup_trap_caches",
|
CleanupTrapCaches = "cleanup_trap_caches",
|
||||||
CppDependencyInstallation = "cpp_dependency_installation_enabled",
|
CppDependencyInstallation = "cpp_dependency_installation_enabled",
|
||||||
@@ -100,19 +72,6 @@ export enum Feature {
|
|||||||
OverlayAnalysisGo = "overlay_analysis_go",
|
OverlayAnalysisGo = "overlay_analysis_go",
|
||||||
OverlayAnalysisJava = "overlay_analysis_java",
|
OverlayAnalysisJava = "overlay_analysis_java",
|
||||||
OverlayAnalysisJavascript = "overlay_analysis_javascript",
|
OverlayAnalysisJavascript = "overlay_analysis_javascript",
|
||||||
/**
|
|
||||||
* When set, chooses the default CodeQL CLI version as the highest version that is both enabled by
|
|
||||||
* feature flags and present as an overlay-base database in the Actions cache for the configured
|
|
||||||
* languages. Falls back to the highest feature flagged version if no intersecting overlay-base
|
|
||||||
* database exists in the cache.
|
|
||||||
*/
|
|
||||||
OverlayAnalysisMatchCodeqlVersion = "overlay_analysis_match_codeql_version",
|
|
||||||
/**
|
|
||||||
* Like `OverlayAnalysisMatchCodeqlVersion`, but only logs a diagnostic with the version that
|
|
||||||
* would have been chosen instead of actually changing the default CodeQL CLI version.
|
|
||||||
* `OverlayAnalysisMatchCodeqlVersion` overrides this flag.
|
|
||||||
*/
|
|
||||||
OverlayAnalysisMatchCodeqlVersionDryRun = "overlay_analysis_match_codeql_version_dry_run",
|
|
||||||
OverlayAnalysisPython = "overlay_analysis_python",
|
OverlayAnalysisPython = "overlay_analysis_python",
|
||||||
/**
|
/**
|
||||||
* Controls whether lower disk space requirements are used for overlay hardware checks.
|
* Controls whether lower disk space requirements are used for overlay hardware checks.
|
||||||
@@ -165,11 +124,6 @@ export type FeatureConfig = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const featureConfig = {
|
export const featureConfig = {
|
||||||
[Feature.AllowMultipleAnalysisKinds]: {
|
|
||||||
defaultValue: false,
|
|
||||||
envVar: "CODEQL_ACTION_ALLOW_MULTIPLE_ANALYSIS_KINDS",
|
|
||||||
minimumVersion: undefined,
|
|
||||||
},
|
|
||||||
[Feature.AllowToolcacheInput]: {
|
[Feature.AllowToolcacheInput]: {
|
||||||
defaultValue: false,
|
defaultValue: false,
|
||||||
envVar: "CODEQL_ACTION_ALLOW_TOOLCACHE_INPUT",
|
envVar: "CODEQL_ACTION_ALLOW_TOOLCACHE_INPUT",
|
||||||
@@ -323,16 +277,6 @@ export const featureConfig = {
|
|||||||
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_DISABLE_TRAP_CACHING",
|
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_DISABLE_TRAP_CACHING",
|
||||||
minimumVersion: undefined,
|
minimumVersion: undefined,
|
||||||
},
|
},
|
||||||
[Feature.OverlayAnalysisMatchCodeqlVersion]: {
|
|
||||||
defaultValue: false,
|
|
||||||
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_MATCH_CODEQL_VERSION",
|
|
||||||
minimumVersion: undefined,
|
|
||||||
},
|
|
||||||
[Feature.OverlayAnalysisMatchCodeqlVersionDryRun]: {
|
|
||||||
defaultValue: false,
|
|
||||||
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_MATCH_CODEQL_VERSION_DRY_RUN",
|
|
||||||
minimumVersion: undefined,
|
|
||||||
},
|
|
||||||
[Feature.OverlayAnalysisResourceChecksV2]: {
|
[Feature.OverlayAnalysisResourceChecksV2]: {
|
||||||
defaultValue: false,
|
defaultValue: false,
|
||||||
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_RESOURCE_CHECKS_V2",
|
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_RESOURCE_CHECKS_V2",
|
||||||
@@ -402,12 +346,8 @@ export type FeatureWithoutCLI = {
|
|||||||
}[keyof typeof featureConfig];
|
}[keyof typeof featureConfig];
|
||||||
|
|
||||||
export interface FeatureEnablement {
|
export interface FeatureEnablement {
|
||||||
/**
|
/** Gets the default version of the CodeQL tools. */
|
||||||
* Returns the set of default CodeQL CLI versions to consider, sorted from
|
getDefaultCliVersion(
|
||||||
* highest to lowest. The first entry is the version that the CodeQL Action
|
|
||||||
* will use by default. The list is always non-empty.
|
|
||||||
*/
|
|
||||||
getEnabledDefaultCliVersions(
|
|
||||||
variant: util.GitHubVariant,
|
variant: util.GitHubVariant,
|
||||||
): Promise<CodeQLDefaultVersionInfo>;
|
): Promise<CodeQLDefaultVersionInfo>;
|
||||||
getValue(feature: FeatureWithoutCLI): Promise<boolean>;
|
getValue(feature: FeatureWithoutCLI): Promise<boolean>;
|
||||||
@@ -431,11 +371,12 @@ export const FEATURE_FLAGS_FILE_NAME = "cached-feature-flags.json";
|
|||||||
class OfflineFeatures implements FeatureEnablement {
|
class OfflineFeatures implements FeatureEnablement {
|
||||||
constructor(protected readonly logger: Logger) {}
|
constructor(protected readonly logger: Logger) {}
|
||||||
|
|
||||||
async getEnabledDefaultCliVersions(
|
async getDefaultCliVersion(
|
||||||
_variant: util.GitHubVariant,
|
_variant: util.GitHubVariant,
|
||||||
): Promise<CodeQLDefaultVersionInfo> {
|
): Promise<CodeQLDefaultVersionInfo> {
|
||||||
return {
|
return {
|
||||||
enabledVersions: [LINKED_CODEQL_VERSION],
|
cliVersion: defaults.cliVersion,
|
||||||
|
tagName: defaults.bundleVersion,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -445,7 +386,7 @@ class OfflineFeatures implements FeatureEnablement {
|
|||||||
getFeatureConfig(feature: Feature): FeatureConfig {
|
getFeatureConfig(feature: Feature): FeatureConfig {
|
||||||
// Narrow the type to FeatureConfig to avoid type errors. To avoid unsafe use of `as`, we
|
// Narrow the type to FeatureConfig to avoid type errors. To avoid unsafe use of `as`, we
|
||||||
// check that the required properties exist using `satisfies`.
|
// check that the required properties exist using `satisfies`.
|
||||||
return featureConfig[feature] satisfies FeatureConfig;
|
return featureConfig[feature] satisfies FeatureConfig as FeatureConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -577,13 +518,13 @@ class Features extends OfflineFeatures {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getEnabledDefaultCliVersions(
|
async getDefaultCliVersion(
|
||||||
variant: util.GitHubVariant,
|
variant: util.GitHubVariant,
|
||||||
): Promise<CodeQLDefaultVersionInfo> {
|
): Promise<CodeQLDefaultVersionInfo> {
|
||||||
if (supportsFeatureFlags(variant)) {
|
if (supportsFeatureFlags(variant)) {
|
||||||
return await this.gitHubFeatureFlags.getEnabledDefaultCliVersionsFromFlags();
|
return await this.gitHubFeatureFlags.getDefaultCliVersionFromFlags();
|
||||||
}
|
}
|
||||||
return super.getEnabledDefaultCliVersions(variant);
|
return super.getDefaultCliVersion(variant);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -659,22 +600,16 @@ class GitHubFeatureFlags {
|
|||||||
return version;
|
return version;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
async getDefaultCliVersionFromFlags(): Promise<CodeQLDefaultVersionInfo> {
|
||||||
* Returns CLI versions enabled by `default_codeql_version_*_enabled` feature
|
|
||||||
* flags, sorted from highest to lowest. Falls back to the version pinned in
|
|
||||||
* `defaults.json` if no such flags are enabled.
|
|
||||||
*/
|
|
||||||
async getEnabledDefaultCliVersionsFromFlags(): Promise<CodeQLDefaultVersionInfo> {
|
|
||||||
const response = await this.getAllFeatures();
|
const response = await this.getAllFeatures();
|
||||||
|
|
||||||
const sortedCliVersions = Object.entries(response)
|
const enabledFeatureFlagCliVersions = Object.entries(response)
|
||||||
.map(([f, isEnabled]) =>
|
.map(([f, isEnabled]) =>
|
||||||
isEnabled ? this.getCliVersionFromFeatureFlag(f) : undefined,
|
isEnabled ? this.getCliVersionFromFeatureFlag(f) : undefined,
|
||||||
)
|
)
|
||||||
.filter((f): f is string => f !== undefined)
|
.filter((f): f is string => f !== undefined);
|
||||||
.sort(semver.rcompare);
|
|
||||||
|
|
||||||
if (sortedCliVersions.length === 0) {
|
if (enabledFeatureFlagCliVersions.length === 0) {
|
||||||
// We expect at least one default CLI version to be enabled on Dotcom at any time. However if
|
// We expect at least one default CLI version to be enabled on Dotcom at any time. However if
|
||||||
// the feature flags are misconfigured, rather than crashing, we fall back to the CLI version
|
// the feature flags are misconfigured, rather than crashing, we fall back to the CLI version
|
||||||
// shipped with the Action in defaults.json. This has the effect of immediately rolling out
|
// shipped with the Action in defaults.json. This has the effect of immediately rolling out
|
||||||
@@ -690,7 +625,8 @@ class GitHubFeatureFlags {
|
|||||||
`shipped with the Action. This is ${defaults.cliVersion}.`,
|
`shipped with the Action. This is ${defaults.cliVersion}.`,
|
||||||
);
|
);
|
||||||
const result: CodeQLDefaultVersionInfo = {
|
const result: CodeQLDefaultVersionInfo = {
|
||||||
enabledVersions: [LINKED_CODEQL_VERSION],
|
cliVersion: defaults.cliVersion,
|
||||||
|
tagName: defaults.bundleVersion,
|
||||||
};
|
};
|
||||||
if (this.hasAccessedRemoteFeatureFlags) {
|
if (this.hasAccessedRemoteFeatureFlags) {
|
||||||
result.toolsFeatureFlagsValid = false;
|
result.toolsFeatureFlagsValid = false;
|
||||||
@@ -698,14 +634,17 @@ class GitHubFeatureFlags {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const maxCliVersion = enabledFeatureFlagCliVersions.reduce(
|
||||||
|
(maxVersion, currentVersion) =>
|
||||||
|
currentVersion > maxVersion ? currentVersion : maxVersion,
|
||||||
|
enabledFeatureFlagCliVersions[0],
|
||||||
|
);
|
||||||
this.logger.debug(
|
this.logger.debug(
|
||||||
`Derived default CLI version of ${sortedCliVersions[0]} from feature flags.`,
|
`Derived default CLI version of ${maxCliVersion} from feature flags.`,
|
||||||
);
|
);
|
||||||
return {
|
return {
|
||||||
enabledVersions: sortedCliVersions.map((cliVersion) => ({
|
cliVersion: maxCliVersion,
|
||||||
cliVersion,
|
tagName: `codeql-bundle-v${maxCliVersion}`,
|
||||||
tagName: `codeql-bundle-v${cliVersion}`,
|
|
||||||
})),
|
|
||||||
toolsFeatureFlagsValid: true,
|
toolsFeatureFlagsValid: true,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
+158
-59
@@ -33,6 +33,7 @@ test.serial(
|
|||||||
|
|
||||||
const actualRef = await gitUtils.getRef();
|
const actualRef = await gitUtils.getRef();
|
||||||
t.deepEqual(actualRef, expectedRef);
|
t.deepEqual(actualRef, expectedRef);
|
||||||
|
callback.restore();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@@ -53,6 +54,7 @@ test.serial(
|
|||||||
|
|
||||||
const actualRef = await gitUtils.getRef();
|
const actualRef = await gitUtils.getRef();
|
||||||
t.deepEqual(actualRef, expectedRef);
|
t.deepEqual(actualRef, expectedRef);
|
||||||
|
callback.restore();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@@ -71,6 +73,7 @@ test.serial(
|
|||||||
|
|
||||||
const actualRef = await gitUtils.getRef();
|
const actualRef = await gitUtils.getRef();
|
||||||
t.deepEqual(actualRef, "refs/pull/1/head");
|
t.deepEqual(actualRef, "refs/pull/1/head");
|
||||||
|
callback.restore();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@@ -97,6 +100,8 @@ test.serial(
|
|||||||
|
|
||||||
const actualRef = await gitUtils.getRef();
|
const actualRef = await gitUtils.getRef();
|
||||||
t.deepEqual(actualRef, "refs/pull/2/merge");
|
t.deepEqual(actualRef, "refs/pull/2/merge");
|
||||||
|
callback.restore();
|
||||||
|
getAdditionalInputStub.restore();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@@ -156,6 +161,7 @@ test.serial(
|
|||||||
"Both 'ref' and 'sha' are required if one of them is provided.",
|
"Both 'ref' and 'sha' are required if one of them is provided.",
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
getAdditionalInputStub.restore();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@@ -182,6 +188,95 @@ test.serial(
|
|||||||
"Both 'ref' and 'sha' are required if one of them is provided.",
|
"Both 'ref' and 'sha' are required if one of them is provided.",
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
getAdditionalInputStub.restore();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
test.serial(
|
||||||
|
"getRef() returns merge PR ref if GITHUB_SHA still checked out (SHA-256)",
|
||||||
|
async (t) => {
|
||||||
|
await withTmpDir(async (tmpDir: string) => {
|
||||||
|
setupActionsVars(tmpDir, tmpDir);
|
||||||
|
const expectedRef = "refs/pull/1/merge";
|
||||||
|
const currentSha = "a".repeat(64);
|
||||||
|
process.env["GITHUB_REF"] = expectedRef;
|
||||||
|
process.env["GITHUB_SHA"] = currentSha;
|
||||||
|
|
||||||
|
const callback = sinon.stub(gitUtils, "getCommitOid");
|
||||||
|
callback.withArgs("HEAD").resolves(currentSha);
|
||||||
|
|
||||||
|
const actualRef = await gitUtils.getRef();
|
||||||
|
t.deepEqual(actualRef, expectedRef);
|
||||||
|
callback.restore();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
test.serial(
|
||||||
|
"getRef() returns merge PR ref if GITHUB_REF still checked out but sha has changed (actions checkout@v1) (SHA-256)",
|
||||||
|
async (t) => {
|
||||||
|
await withTmpDir(async (tmpDir: string) => {
|
||||||
|
setupActionsVars(tmpDir, tmpDir);
|
||||||
|
const expectedRef = "refs/pull/1/merge";
|
||||||
|
process.env["GITHUB_REF"] = expectedRef;
|
||||||
|
process.env["GITHUB_SHA"] = "b".repeat(64);
|
||||||
|
const sha = "a".repeat(64);
|
||||||
|
|
||||||
|
const callback = sinon.stub(gitUtils, "getCommitOid");
|
||||||
|
callback.withArgs("refs/remotes/pull/1/merge").resolves(sha);
|
||||||
|
callback.withArgs("HEAD").resolves(sha);
|
||||||
|
|
||||||
|
const actualRef = await gitUtils.getRef();
|
||||||
|
t.deepEqual(actualRef, expectedRef);
|
||||||
|
callback.restore();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
test.serial(
|
||||||
|
"getRef() returns head PR ref if GITHUB_REF no longer checked out (SHA-256)",
|
||||||
|
async (t) => {
|
||||||
|
await withTmpDir(async (tmpDir: string) => {
|
||||||
|
setupActionsVars(tmpDir, tmpDir);
|
||||||
|
process.env["GITHUB_REF"] = "refs/pull/1/merge";
|
||||||
|
process.env["GITHUB_SHA"] = "a".repeat(64);
|
||||||
|
|
||||||
|
const callback = sinon.stub(gitUtils, "getCommitOid");
|
||||||
|
callback.withArgs(tmpDir, "refs/pull/1/merge").resolves("a".repeat(64));
|
||||||
|
callback.withArgs(tmpDir, "HEAD").resolves("b".repeat(64));
|
||||||
|
|
||||||
|
const actualRef = await gitUtils.getRef();
|
||||||
|
t.deepEqual(actualRef, "refs/pull/1/head");
|
||||||
|
callback.restore();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
test.serial(
|
||||||
|
"getRef() returns ref provided as an input and ignores current HEAD (SHA-256)",
|
||||||
|
async (t) => {
|
||||||
|
await withTmpDir(async (tmpDir: string) => {
|
||||||
|
setupActionsVars(tmpDir, tmpDir);
|
||||||
|
const getAdditionalInputStub = sinon.stub(
|
||||||
|
actionsUtil,
|
||||||
|
"getOptionalInput",
|
||||||
|
);
|
||||||
|
getAdditionalInputStub.withArgs("ref").resolves("refs/pull/2/merge");
|
||||||
|
getAdditionalInputStub.withArgs("sha").resolves("b".repeat(64));
|
||||||
|
|
||||||
|
// These values are be ignored
|
||||||
|
process.env["GITHUB_REF"] = "refs/pull/1/merge";
|
||||||
|
process.env["GITHUB_SHA"] = "a".repeat(64);
|
||||||
|
|
||||||
|
const callback = sinon.stub(gitUtils, "getCommitOid");
|
||||||
|
callback.withArgs("refs/pull/1/merge").resolves("b".repeat(64));
|
||||||
|
callback.withArgs("HEAD").resolves("b".repeat(64));
|
||||||
|
|
||||||
|
const actualRef = await gitUtils.getRef();
|
||||||
|
t.deepEqual(actualRef, "refs/pull/2/merge");
|
||||||
|
callback.restore();
|
||||||
|
getAdditionalInputStub.restore();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@@ -235,6 +330,7 @@ test.serial("isAnalyzingDefaultBranch()", async (t) => {
|
|||||||
process.env["GITHUB_EVENT_NAME"] = "schedule";
|
process.env["GITHUB_EVENT_NAME"] = "schedule";
|
||||||
process.env["GITHUB_REF"] = "refs/heads/main";
|
process.env["GITHUB_REF"] = "refs/heads/main";
|
||||||
t.deepEqual(await gitUtils.isAnalyzingDefaultBranch(), false);
|
t.deepEqual(await gitUtils.isAnalyzingDefaultBranch(), false);
|
||||||
|
getAdditionalInputStub.restore();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -246,6 +342,8 @@ test.serial("determineBaseBranchHeadCommitOid non-pullrequest", async (t) => {
|
|||||||
const result = await gitUtils.determineBaseBranchHeadCommitOid(__dirname);
|
const result = await gitUtils.determineBaseBranchHeadCommitOid(__dirname);
|
||||||
t.deepEqual(result, undefined);
|
t.deepEqual(result, undefined);
|
||||||
t.deepEqual(0, infoStub.callCount);
|
t.deepEqual(0, infoStub.callCount);
|
||||||
|
|
||||||
|
infoStub.restore();
|
||||||
});
|
});
|
||||||
|
|
||||||
test.serial(
|
test.serial(
|
||||||
@@ -266,6 +364,8 @@ test.serial(
|
|||||||
"git call failed. Will calculate the base branch SHA on the server. Error: " +
|
"git call failed. Will calculate the base branch SHA on the server. Error: " +
|
||||||
"The checkout path provided to the action does not appear to be a git repository.",
|
"The checkout path provided to the action does not appear to be a git repository.",
|
||||||
);
|
);
|
||||||
|
|
||||||
|
infoStub.restore();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -289,10 +389,12 @@ test.serial("determineBaseBranchHeadCommitOid other error", async (t) => {
|
|||||||
"The checkout path provided to the action does not appear to be a git repository.",
|
"The checkout path provided to the action does not appear to be a git repository.",
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
infoStub.restore();
|
||||||
});
|
});
|
||||||
|
|
||||||
test.serial(
|
test.serial(
|
||||||
"determineBaseBranchHeadCommitOid accepts SHA-256 OIDs",
|
"determineBaseBranchHeadCommitOid returns baseOid for SHA-256 merge commit",
|
||||||
async (t) => {
|
async (t) => {
|
||||||
const mergeSha = "a".repeat(64);
|
const mergeSha = "a".repeat(64);
|
||||||
const baseOid = "b".repeat(64);
|
const baseOid = "b".repeat(64);
|
||||||
@@ -441,64 +543,6 @@ test.serial("getFileOidsUnderPath handles quoted paths", async (t) => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test.serial("getFileOidsUnderPath handles SHA-256 OIDs", async (t) => {
|
|
||||||
await withTmpDir(async (tmpDir) => {
|
|
||||||
const sha256OidA =
|
|
||||||
"9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2c0d4b7e8f9a1234567890ab";
|
|
||||||
const sha256OidB =
|
|
||||||
"aabbccddeeff00112233445566778899aabbccddeeff00112233445566778899";
|
|
||||||
|
|
||||||
sinon
|
|
||||||
.stub(gitUtils as any, "runGitCommand")
|
|
||||||
.callsFake(async (_cwd: any, args: any) => {
|
|
||||||
if (args[0] === "rev-parse") {
|
|
||||||
return `${tmpDir}\n`;
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
`100644 ${sha256OidA} 0\tlib/sha256-file-a.js\n` +
|
|
||||||
`100644 ${sha256OidB} 0\tsrc/sha256-file-b.ts`
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
const result = await gitUtils.getFileOidsUnderPath("/fake/path");
|
|
||||||
|
|
||||||
t.deepEqual(result, {
|
|
||||||
"lib/sha256-file-a.js": sha256OidA,
|
|
||||||
"src/sha256-file-b.ts": sha256OidB,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test.serial(
|
|
||||||
"getFileOidsUnderPath rejects OIDs of unsupported length",
|
|
||||||
async (t) => {
|
|
||||||
await withTmpDir(async (tmpDir) => {
|
|
||||||
// 50-char OID: not a valid SHA-1 (40) or SHA-256 (64) length. The regex
|
|
||||||
// must not accept this even though every character is a valid hex digit.
|
|
||||||
const invalidLine =
|
|
||||||
"100644 30d998ded095371488be3a729eb61d86ed721a1830d998ded0 0\tlib/bad.js";
|
|
||||||
sinon
|
|
||||||
.stub(gitUtils as any, "runGitCommand")
|
|
||||||
.callsFake(async (_cwd: any, args: any) => {
|
|
||||||
if (args[0] === "rev-parse") {
|
|
||||||
return `${tmpDir}\n`;
|
|
||||||
}
|
|
||||||
return invalidLine;
|
|
||||||
});
|
|
||||||
|
|
||||||
await t.throwsAsync(
|
|
||||||
async () => {
|
|
||||||
await gitUtils.getFileOidsUnderPath("/fake/path");
|
|
||||||
},
|
|
||||||
{
|
|
||||||
instanceOf: Error,
|
|
||||||
message: `Unexpected "git ls-files" output: ${invalidLine}`,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
test.serial("getFileOidsUnderPath handles empty output", async (t) => {
|
test.serial("getFileOidsUnderPath handles empty output", async (t) => {
|
||||||
await withTmpDir(async (tmpDir) => {
|
await withTmpDir(async (tmpDir) => {
|
||||||
sinon
|
sinon
|
||||||
@@ -545,6 +589,61 @@ test.serial(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
test.serial(
|
||||||
|
"getFileOidsUnderPath handles SHA-256 OIDs (64-char)",
|
||||||
|
async (t) => {
|
||||||
|
await withTmpDir(async (tmpDir) => {
|
||||||
|
sinon
|
||||||
|
.stub(gitUtils as any, "runGitCommand")
|
||||||
|
.callsFake(async (_cwd: any, args: any) => {
|
||||||
|
if (args[0] === "rev-parse") {
|
||||||
|
return `${tmpDir}\n`;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
"100644 9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2c0d4b7e8f9a1234567890ab 0\tlib/git-utils.js\n" +
|
||||||
|
"100644 aabbccddeeff00112233445566778899aabbccddeeff00112233445566778899 0\tsrc/git-utils.ts"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = await gitUtils.getFileOidsUnderPath("/fake/path");
|
||||||
|
|
||||||
|
t.deepEqual(result, {
|
||||||
|
"lib/git-utils.js":
|
||||||
|
"9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2c0d4b7e8f9a1234567890ab",
|
||||||
|
"src/git-utils.ts":
|
||||||
|
"aabbccddeeff00112233445566778899aabbccddeeff00112233445566778899",
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
test.serial(
|
||||||
|
"getFileOidsUnderPath handles mixed SHA-1 and SHA-256 OIDs",
|
||||||
|
async (t) => {
|
||||||
|
await withTmpDir(async (tmpDir) => {
|
||||||
|
sinon
|
||||||
|
.stub(gitUtils as any, "runGitCommand")
|
||||||
|
.callsFake(async (_cwd: any, args: any) => {
|
||||||
|
if (args[0] === "rev-parse") {
|
||||||
|
return `${tmpDir}\n`;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
"100644 30d998ded095371488be3a729eb61d86ed721a18 0\tlib/sha1-file.js\n" +
|
||||||
|
"100644 aabbccddeeff00112233445566778899aabbccddeeff00112233445566778899 0\tsrc/sha256-file.ts"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = await gitUtils.getFileOidsUnderPath("/fake/path");
|
||||||
|
|
||||||
|
t.deepEqual(result, {
|
||||||
|
"lib/sha1-file.js": "30d998ded095371488be3a729eb61d86ed721a18",
|
||||||
|
"src/sha256-file.ts":
|
||||||
|
"aabbccddeeff00112233445566778899aabbccddeeff00112233445566778899",
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
test.serial(
|
test.serial(
|
||||||
"getGitVersionOrThrow returns version for valid git output",
|
"getGitVersionOrThrow returns version for valid git output",
|
||||||
async (t) => {
|
async (t) => {
|
||||||
|
|||||||
+2
-4
@@ -163,8 +163,7 @@ export const determineBaseBranchHeadCommitOid = async function (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Let's confirm our assumptions: We had a merge commit and the parsed parent
|
// Let's confirm our assumptions: We had a merge commit and the parsed parent data looks correct
|
||||||
// data looks correct. OIDs are either 40 (SHA-1) or 64 (SHA-256) hex characters.
|
|
||||||
if (
|
if (
|
||||||
commitOid === mergeSha &&
|
commitOid === mergeSha &&
|
||||||
(headOid.length === 40 || headOid.length === 64) &&
|
(headOid.length === 40 || headOid.length === 64) &&
|
||||||
@@ -297,8 +296,7 @@ export const getFileOidsUnderPath = async function (
|
|||||||
// 100644 4c51bc1d9e86cd86e01b0f340cb8ce095c33b283 0\tsrc/git-utils.test.ts
|
// 100644 4c51bc1d9e86cd86e01b0f340cb8ce095c33b283 0\tsrc/git-utils.test.ts
|
||||||
// 100644 6b792ea543ce75d7a8a03df591e3c85311ecb64f 0\tsrc/git-utils.ts
|
// 100644 6b792ea543ce75d7a8a03df591e3c85311ecb64f 0\tsrc/git-utils.ts
|
||||||
// The fields are: <mode> <oid> <stage>\t<path>
|
// The fields are: <mode> <oid> <stage>\t<path>
|
||||||
// The OID is either 40 (SHA-1) or 64 (SHA-256) hex characters.
|
const regex = /^[0-9]+ ([0-9a-f]{40,64}) [0-9]+\t(.+)$/;
|
||||||
const regex = /^[0-9]+ ([0-9a-f]{40}|[0-9a-f]{64}) [0-9]+\t(.+)$/;
|
|
||||||
for (const line of stdout.split("\n")) {
|
for (const line of stdout.split("\n")) {
|
||||||
if (line) {
|
if (line) {
|
||||||
const match = line.match(regex);
|
const match = line.match(regex);
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user