Skip to content

Commit de553c1

Browse files
authored
Merge pull request #731 from github/lcartey/improve-upgrade-codeql-dependencies
Enable automation of the CodeQL CLI upgrade process
2 parents 3c1615d + 61e7c6d commit de553c1

File tree

4 files changed

+93
-41
lines changed

4 files changed

+93
-41
lines changed

.github/workflows/upgrade_codeql_dependencies.yml

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,20 @@ jobs:
1818
runs-on: ubuntu-22.04
1919
steps:
2020
- name: Checkout
21-
uses: actions/checkout@v2
21+
uses: actions/checkout@v4
22+
23+
- name: Fetch CodeQL
24+
env:
25+
GITHUB_TOKEN: ${{ github.token }}
26+
RUNNER_TEMP: ${{ runner.temp }}
27+
run: |
28+
cd $RUNNER_TEMP
29+
gh release download "v${CODEQL_CLI_VERSION}" --repo https://github.com/github/codeql-cli-binaries --pattern codeql-linux64.zip
30+
unzip -q codeql-linux64.zip
31+
echo "$RUNNER_TEMP/codeql/" >> $GITHUB_PATH
2232
2333
- name: Install Python
24-
uses: actions/setup-python@v4
34+
uses: actions/setup-python@v5
2535
with:
2636
python-version: "3.9"
2737

@@ -35,27 +45,27 @@ jobs:
3545
run: |
3646
python3 scripts/upgrade-codeql-dependencies/upgrade-codeql-dependencies.py --cli-version "$CODEQL_CLI_VERSION"
3747
38-
- name: Fetch CodeQL
39-
env:
40-
GITHUB_TOKEN: ${{ github.token }}
41-
RUNNER_TEMP: ${{ runner.temp }}
42-
run: |
43-
cd $RUNNER_TEMP
44-
gh release download "v${CODEQL_CLI_VERSION}" --repo https://github.com/github/codeql-cli-binaries --pattern codeql-linux64.zip
45-
unzip -q codeql-linux64.zip
46-
4748
- name: Update CodeQL formatting based on new CLI version
4849
env:
4950
RUNNER_TEMP: ${{ runner.temp }}
5051
run: |
51-
find cpp \( -name '*.ql' -or -name '*.qll' \) -print0 | xargs -0 --max-procs "$XARGS_MAX_PROCS" $RUNNER_TEMP/codeql/codeql query format --in-place
52-
find c \( -name '*.ql' -or -name '*.qll' \) -print0 | xargs -0 --max-procs "$XARGS_MAX_PROCS" $RUNNER_TEMP/codeql/codeql query format --in-place
52+
find cpp \( -name '*.ql' -or -name '*.qll' \) -print0 | xargs -0 --max-procs "$XARGS_MAX_PROCS" codeql query format --in-place
53+
find c \( -name '*.ql' -or -name '*.qll' \) -print0 | xargs -0 --max-procs "$XARGS_MAX_PROCS" codeql query format --in-place
5354
5455
- name: Create Pull Request
55-
uses: peter-evans/create-pull-request@v3
56+
uses: peter-evans/create-pull-request@5e914681df9dc83aa4e4905692ca88beb2f9e91f # v7.0.5
5657
with:
57-
title: "Upgrading `github/codeql` dependency to ${{ github.event.inputs.codeql_cli_version }}"
58-
body: "This PR upgrades the CodeQL CLI version to ${{ github.event.inputs.codeql_cli_version }}."
58+
title: "Upgrade `github/codeql` dependency to ${{ github.event.inputs.codeql_cli_version }}"
59+
body: |
60+
This PR upgrades the CodeQL CLI version to ${{ github.event.inputs.codeql_cli_version }}.
61+
62+
## CodeQL dependency upgrade checklist:
63+
64+
- [ ] Confirm the code has been correctly reformatted according to the new CodeQL CLI.
65+
- [ ] Identify any CodeQL compiler warnings and errors, and update queries as required.
66+
- [ ] Validate that the `github/codeql` test cases succeed.
67+
- [ ] Address any CodeQL test failures in the `github/codeql-coding-standards` repository.
68+
- [ ] Validate performance vs pre-upgrade, using /test-performance
5969
commit-message: "Upgrading `github/codeql` dependency to ${{ github.event.inputs.codeql_cli_version }}"
6070
delete-branch: true
6171
branch: "codeql/upgrade-to-${{ github.event.inputs.codeql_cli_version }}"

docs/development_handbook.md

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -496,46 +496,53 @@ There are two external dependencies required for running the coding standards qu
496496

497497
For the purpose of this repository, and any tool qualification, we consider these external dependencies to be "black boxes" which require verification when upgrading.
498498

499-
To (a) clearly specify the supported versions of these external dependencies and to (b) enable automation around them, the repository contains a `supported_codeql_configs.json` which lists the sets of supported configurations. There are four fields:
499+
To (a) clearly specify the supported versions of these external dependencies and to (b) enable automation around them, the repository contains a `supported_codeql_configs.json` which lists the sets of supported configurations under the `supported_environments` property. There are three fields:
500500

501501
- `codeql_cli` - this is the plain version number of the supported CodeQL CLI, e.g. `2.6.3`.
502502
- `codeql_standard_library` - this is the name of a tag on the `github.com/github/codeql` repository. The tag should be compatible with the CodeQL CLI given above. This would typically use the `codeql-cli/v<version-number>` tag for the release, although any tag which is compatible is allowed.
503503
- `codeql_cli_bundle` - (optional) - if present, describes the CodeQL CLI bundle version that is compatible. The bundle should include precisely the CodeQL CLI version and CodeQL Standard Library versions specified in the two mandatory fields.
504-
- `ghes` - (optional) - if present describes the GitHub Enterprise Server release whose integrated copy of the CodeQL Action points to the CodeQL CLI bundle specified in the `codeql_cli_bundle` field.
505504

506505
#### Upgrading external dependencies
507506

508507
To upgrade the CodeQL external dependencies:
509508

510509
1. Determine appropriate versions of the CodeQL CLI and `github/codeql` repository, according to the release schedule and customer demands.
511510
2. Determine if there is a compatible CodeQL CLI bundle version by looking at the releases specified at [CodeQL Action releases](https://github.com/github/codeql-action/releases). The bundle always includes the standard library at the version specified by the `codeql-cli/v<version-number>` tag in the `github/codeql` repository.
512-
3. If you find a compatible CodeQL CLI bundle, determine whether that bundle was released in a GitHub Enterprise server release, by inspecting the `defaults.json` file at https://github.com/github/codeql-action/blob/main/lib/defaults.json#L2 for the CodeQL Action submitted with
513-
4. Populated the `supported_codeql_configs.json` file with the given values, ensuring to delete the optional fields if they are not populated.
514-
5. Submit a Pull Request to the `github/codeql-coding-standards` repository with the title `Upgrade `github/codeql` dependency to <insert codeql_standard_library value>`. Use this template for the description, filling :
515511

516-
```md
517-
This PR updates the `supported_codeql_configs.json` file to target:
512+
If all components are being upgraded to a consistent veresion (e.g. CodeQL CLI v2.15.5, with `github/codeql` tag `codeql-cli/v2.15.5` and bundle `codeql-cli-bundle-v2.15.5`) then the following process can be used:
513+
514+
1. Run the [upgrade_codeql_dependencies.yml](./github/workflows/upgrade_codeql_dependencies.yml) workflow, with the plain version number, e.g. `2.15.5`. This will:
515+
- Download the specified version of the CodeQL CLI
516+
- Run the [upgrade-codeql-dependencies.py](scripts/release/upgrade-codeql-dependencies.py) script, which
517+
- Validates the version selected exists in all relevant places
518+
- Updates the `supported_codeql_configs.json` file.
519+
- Updates each `qlpack.yml` in the repository with an appropriate value for the `codeql/cpp-all` pack, consistent with the selected CodeQL CLI version.
520+
- Updates each `codeql-lock.yml` file to upgrade to the new version.
521+
2. Follow the dependency upgrade checklist, confirming each step. The `.github/workflows/standard_library_upgrade_tests.yml` will trigger automation for running the `github/codeql` unit tests with the appropriate CLI version.
522+
3. Once all the automate tests have passed, and the checklist is complete, the PR can be merged.
523+
4. An internal notification should be shared with the development team.
518524

519-
- CodeQL CLI <codeql_cli>
520-
- CodeQL Standard Library <codeql_standard_library>
521-
- GHES <ghes>
522-
- CodeQL CLI Bundle <date_of_bundle>
525+
If the upgrade is of mismatched versions you will need to manually create the upgrade following this process:
523526

524-
<EITHER:This should match the versions of CodeQL deployed with GitHub Enterprise Server <ghes>>
525-
<OR: This does not match any released version of GitHub Enterprise Server.>
527+
1. Populate the `supported_codeql_configs.json` file with the given values, ensuring to delete the optional fields if they are not populated.
528+
2. Submit a Pull Request to the `github/codeql-coding-standards` repository with the title `Upgrade `github/codeql` dependency to <insert codeql_standard_library value>`. Use this template for the description, filling:
529+
530+
```md
531+
This PR updates the `supported_codeql_configs.json` file to target CodeQL CLI <codeql_cli>.
526532

527533
## CodeQL dependency upgrade checklist:
528534

529-
- [ ] Reformat our CodeQL using the latest version (if required)
535+
- [ ] Confirm the code has been correctly reformatted according to the new CodeQL CLI.
530536
- [ ] Identify any CodeQL compiler warnings and errors, and update queries as required.
531537
- [ ] Validate that the `github/codeql` test cases succeed.
532538
- [ ] Address any CodeQL test failures in the `github/codeql-coding-standards` repository.
533-
- [ ] Validate performance vs pre-upgrade
539+
- [ ] Validate performance vs pre-upgrade, using /test-performance
534540
```
535541

536-
6. Follow the dependency upgrade checklist, confirming each step. The `.github/workflows/standard_library_upgrade_tests.yml` will trigger automation for running the `github/codeql` unit tests with the appropriate CLI version.
537-
7. Once all the automate tests have passed, and the checklist is complete, the PR can be merged.
538-
8. An internal notification should be shared with the development team.
542+
3. Follow the dependency upgrade checklist, confirming each step. The `.github/workflows/standard_library_upgrade_tests.yml` will trigger automation for running the `github/codeql` unit tests with the appropriate CLI version.
543+
4. Once all the automate tests have passed, and the checklist is complete, the PR can be merged.
544+
5. An internal notification should be shared with the development team.
545+
539546

540547
### Release process
541548

scripts/upgrade-codeql-dependencies/requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ idna==3.4
44
requests==2.31.0
55
semantic-version==2.10.0
66
urllib3==1.26.18
7+
pyyaml==6.0.1

scripts/upgrade-codeql-dependencies/upgrade-codeql-dependencies.py

Lines changed: 41 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,23 @@
11
import json
22
import requests
3-
from typing import Optional, Dict, List
3+
from typing import Optional, Dict, List, Tuple
44
from semantic_version import Version
55
from pathlib import Path
6+
import yaml
67

78
SCRIPT_PATH = Path(__file__)
8-
SUPPORTED_VERSIONS_PATH = SCRIPT_PATH.parent.parent.parent / "supported_codeql_configs.json"
9+
CODING_STANDARDS_ROOT = SCRIPT_PATH.parent.parent.parent
10+
SUPPORTED_VERSIONS_PATH = CODING_STANDARDS_ROOT / "supported_codeql_configs.json"
911

10-
def get_compatible_stdlib(version: Version) -> Optional[str]:
12+
def get_compatible_stdlib(version: Version) -> Optional[Tuple[str, str]]:
1113
tag = f"codeql-cli/v{version}"
1214
response = requests.get(f"https://raw.githubusercontent.com/github/codeql/{tag}/cpp/ql/lib/qlpack.yml")
1315

1416
if response.status_code == 200:
15-
return tag
17+
# Parse the qlpack.yml returned in the response as a yaml file to read the version property
18+
qlpack = yaml.safe_load(response.text)
19+
if qlpack is not None and "version" in qlpack:
20+
return (tag, qlpack["version"])
1621
return None
1722

1823
def get_compatible_bundle(version: Version, token: str) -> Optional[str]:
@@ -30,15 +35,17 @@ def get_compatible_bundle(version: Version, token: str) -> Optional[str]:
3035
def main(cli_version : str, github_token: str) -> None:
3136
try:
3237
parsed_cli_version = Version(cli_version)
33-
compatible_stdlib = get_compatible_stdlib(parsed_cli_version)
34-
if compatible_stdlib is None:
38+
compatible_stdlib_return = get_compatible_stdlib(parsed_cli_version)
39+
if compatible_stdlib_return is None:
3540
print(f"Unable to find compatible standard library for: {parsed_cli_version}")
3641
exit(1)
3742
compatible_bundle = get_compatible_bundle(parsed_cli_version, github_token)
3843
if compatible_bundle is None:
3944
print(f"Unable to find compatible bundle for: {parsed_cli_version}")
4045
exit(1)
4146

47+
compatible_stdlib_tag, compatible_stdlib_version = compatible_stdlib_return
48+
4249
with SUPPORTED_VERSIONS_PATH.open("r") as f:
4350
supported_versions = json.load(f)
4451

@@ -49,10 +56,37 @@ def main(cli_version : str, github_token: str) -> None:
4956
supported_env = supported_envs[0]
5057
supported_env["codeql_cli"] = str(parsed_cli_version)
5158
supported_env["codeql_cli_bundle"] = compatible_bundle
52-
supported_env["codeql_standard_library"] = compatible_stdlib
59+
supported_env["codeql_standard_library"] = compatible_stdlib_tag
5360

5461
with SUPPORTED_VERSIONS_PATH.open("w") as f:
5562
json.dump(supported_versions, f, indent=2)
63+
64+
# Find every qlpack.yml file in the repository
65+
qlpack_files = list(CODING_STANDARDS_ROOT.rglob("qlpack.yml"))
66+
# Filter out any files that are in a hidden directory
67+
qlpack_files = [f for f in qlpack_files if not any(part for part in f.parts if part.startswith("."))]
68+
69+
# Update the "codeql/cpp-all" entries in the "dependencies" property in every qlpack.yml file
70+
for qlpack_file in qlpack_files:
71+
with qlpack_file.open("r") as f:
72+
qlpack = yaml.safe_load(f)
73+
print("Updating dependencies in " + str(qlpack_file))
74+
if "codeql/cpp-all" in qlpack["dependencies"]:
75+
qlpack["dependencies"]["codeql/cpp-all"] = compatible_stdlib_version
76+
with qlpack_file.open("w") as f:
77+
yaml.safe_dump(qlpack, f, sort_keys=False)
78+
79+
# Call CodeQL to update the lock files by running codeql pack upgrade
80+
# Note: we need to do this after updating all the qlpack files,
81+
# otherwise we may get dependency resolution errors
82+
# Note: we need to update all qlpack files, because they may
83+
# transitively depend on the packs we changed
84+
for qlpack_file in qlpack_files:
85+
qlpack = qlpack_file.parent
86+
print("Updating lock files for " + str(qlpack))
87+
os.system(f"codeql pack upgrade {qlpack}")
88+
89+
5690
except ValueError as e:
5791
print(e)
5892
exit(1)

0 commit comments

Comments
 (0)