mirror of
https://github.com/github/codeql-action
synced 2026-10-29 15:08:14 +03:00
Compare commits
23
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ad2b30ba0f | ||
|
|
99971dd136 | ||
|
|
202d9f1a6b | ||
|
|
17685f3eba | ||
|
|
87ef6f5834 | ||
|
|
84e80cea7e | ||
|
|
5547a3567f | ||
|
|
eff66e8fb1 | ||
|
|
97b90230e5 | ||
|
|
fe45268b48 | ||
|
|
7e5643a58e | ||
|
|
156dc2ce18 | ||
|
|
86bb85349e | ||
|
|
7121af21e1 | ||
|
|
242ea52c05 | ||
|
|
5f65e35fec | ||
|
|
45b8586e1b | ||
|
|
a9623043dc | ||
|
|
9271dd21d5 | ||
|
|
e0220172c9 | ||
|
|
570e438ccc | ||
|
|
f364105950 | ||
|
|
0d774618aa |
No files matched your search
+135
@@ -0,0 +1,135 @@
|
||||
# Warning: This file is generated automatically, and should not be modified.
|
||||
# Instead, please modify the template in the pr-checks directory and run:
|
||||
# pr-checks/sync.sh
|
||||
# to regenerate this file.
|
||||
|
||||
name: PR Check - Unsupported macOS
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
GO111MODULE: auto
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- releases/v*
|
||||
pull_request: {}
|
||||
merge_group:
|
||||
types:
|
||||
- checks_requested
|
||||
schedule:
|
||||
- cron: '0 5 * * *'
|
||||
workflow_dispatch:
|
||||
inputs: {}
|
||||
workflow_call:
|
||||
inputs: {}
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
concurrency:
|
||||
cancel-in-progress: ${{ github.event_name == 'pull_request' || false }}
|
||||
group: unsupported-macos-${{github.ref}}
|
||||
jobs:
|
||||
unsupported-macos:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- os: xcode-27
|
||||
version: linked
|
||||
- os: xcode-27
|
||||
version: nightly-latest
|
||||
name: Unsupported macOS
|
||||
if: github.triggering_actor != 'dependabot[bot]'
|
||||
permissions:
|
||||
contents: read
|
||||
security-events: read
|
||||
timeout-minutes: 45
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
|
||||
with:
|
||||
node-version: 20.x
|
||||
cache: npm
|
||||
- name: Install newer npm
|
||||
run: npm install -g npm@11.19.1
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
- name: Prepare test
|
||||
id: prepare-test
|
||||
uses: ./.github/actions/prepare-test
|
||||
with:
|
||||
version: ${{ matrix.version }}
|
||||
use-all-platform-bundle: 'false'
|
||||
setup-kotlin: 'true'
|
||||
- name: Check xcode_select_link
|
||||
run: |
|
||||
readlink /private/var/db/xcode_select_link
|
||||
file -h /private/var/db/xcode_select_link
|
||||
|
||||
- uses: ./../action/init
|
||||
id: init
|
||||
continue-on-error: true
|
||||
env:
|
||||
CODEQL_ACTION_CHECK_UNSUPPORTED_TRACED_ANALYSIS: true
|
||||
CODEQL_ACTION_SKIP_UNSUPPORTED_TRACED_ANALYSIS: true
|
||||
with:
|
||||
languages: swift
|
||||
tools: ${{ steps.prepare-test.outputs.tools-url }}
|
||||
|
||||
- name: Analyze
|
||||
# We could run `analyze` here from `./../analyze`, but `getAnalyzeActionName` in `workflow.ts`
|
||||
# can't cope with that unless we introduce a different testing environment. Since this step
|
||||
# would just fail on `xcode-27` anyway, we just skip it instead.
|
||||
if: false
|
||||
uses: ./analyze
|
||||
with:
|
||||
category: '/test-codeql-version:${{ matrix.version }}'
|
||||
env:
|
||||
CODEQL_ACTION_SKIP_GENERATE_FAILED_SARIF: false
|
||||
CODEQL_ACTION_SKIP_SARIF_UPLOAD: true
|
||||
CODEQL_ACTION_TESTING_ENVIRONMENT: codeql-action-pr-checks
|
||||
CODEQL_ACTION_TEST_MODE: true
|
||||
unsupported-macos-sarif-checks:
|
||||
if: github.triggering_actor != 'dependabot[bot]'
|
||||
needs:
|
||||
- unsupported-macos
|
||||
permissions:
|
||||
contents: read
|
||||
security-events: read
|
||||
timeout-minutes: 5
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
|
||||
with:
|
||||
node-version: 20.x
|
||||
cache: npm
|
||||
- name: Install newer npm
|
||||
run: npm install -g npm@11.19.1
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
- name: Download workflow artifact
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
with:
|
||||
pattern: test-mode-sarif-*
|
||||
path: sarif
|
||||
|
||||
- name: List artifact contents
|
||||
run: ls -laR ./sarif
|
||||
|
||||
- name: Check diagnostics appear in SARIF
|
||||
env:
|
||||
SARIF_PATH: "./sarif/"
|
||||
DIAGNOSTIC_ID: "codeql-action/unsupported-traced-analysis-macos"
|
||||
DIAGNOSTIC_NAME: "Traced analysis is not supported on this version of macOS"
|
||||
EXPECTED_LOCATIONS: "0"
|
||||
EXPECTED_MESSAGE: |
|
||||
Traced analysis is not supported on macOS 27 or above.
|
||||
run: npx tsx ./pr-checks/check-diagnostics.ts
|
||||
env:
|
||||
CODEQL_ACTION_TEST_MODE: true
|
||||
Generated
+692
-507
File diff suppressed because it is too large.
Load diff
Generated
+54
-118
@@ -50,14 +50,14 @@
|
||||
"@types/node-forge": "^1.3.14",
|
||||
"@types/sarif": "^2.1.7",
|
||||
"@types/semver": "^7.8.0",
|
||||
"@types/sinon": "^22.0.1",
|
||||
"@types/sinon": "^22.0.0",
|
||||
"ava": "^6.4.1",
|
||||
"esbuild": "^0.28.2",
|
||||
"eslint": "^9.39.5",
|
||||
"eslint-import-resolver-typescript": "^4.4.5",
|
||||
"eslint-plugin-github": "^6.1.2",
|
||||
"eslint-plugin-import-x": "^4.17.1",
|
||||
"eslint-plugin-jsdoc": "^65.4.0",
|
||||
"eslint-plugin-jsdoc": "^65.3.15",
|
||||
"eslint-plugin-no-async-foreach": "^0.1.1",
|
||||
"glob": "^13.0.6",
|
||||
"globals": "^17.13.0",
|
||||
@@ -67,6 +67,14 @@
|
||||
"typescript-eslint": "^8.72.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@aashutoshrathi/word-wrap": {
|
||||
"version": "1.2.6",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/artifact": {
|
||||
"version": "5.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@actions/artifact/-/artifact-5.0.3.tgz",
|
||||
@@ -950,89 +958,18 @@
|
||||
"tslib": "^2.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@es-joy/escodegen": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@es-joy/escodegen/-/escodegen-4.2.0.tgz",
|
||||
"integrity": "sha512-jWqqS3StW6vGwJeT8yu6alS4nipOBi3kD/pR63+9hG2NfGafCJ4viDME15mVf+fyupyptcUJDXfv63gFF5Gzfg==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"dependencies": {
|
||||
"@es-joy/estraverse": "^7.1.1",
|
||||
"@es-joy/jsdoccomment": "^0.62.0",
|
||||
"esprima": "^4.0.1",
|
||||
"esutils": "^2.0.3",
|
||||
"optionator": "^0.9.4"
|
||||
},
|
||||
"bin": {
|
||||
"escodegen": "bin/escodegen.js",
|
||||
"esgenerate": "bin/esgenerate.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"source-map": "~0.7.6"
|
||||
}
|
||||
},
|
||||
"node_modules/@es-joy/escodegen/node_modules/@es-joy/jsdoccomment": {
|
||||
"version": "0.62.0",
|
||||
"resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.62.0.tgz",
|
||||
"integrity": "sha512-yWi6sm7INEwnfS7IJvE0dU+RTrwzLPFcY7e7eGpu/l5Q9lWfQ2ROwZ0qVnc242jw2TUPsfHX3XMIISkGBv57RQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/estree": "^1.0.8",
|
||||
"@typescript-eslint/types": "^8.44.1",
|
||||
"comment-parser": "1.4.1",
|
||||
"esquery": "^1.6.0",
|
||||
"jsdoc-type-pratt-parser": "~5.9.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.11.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@es-joy/escodegen/node_modules/comment-parser": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.1.tgz",
|
||||
"integrity": "sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 12.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@es-joy/escodegen/node_modules/jsdoc-type-pratt-parser": {
|
||||
"version": "5.9.2",
|
||||
"resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-5.9.2.tgz",
|
||||
"integrity": "sha512-TYzkACp/wPvDJLRY7qpHXtrhgwoAaojIOnLaaVNi+AbPU2u1kkjfKd9hXXTq0qSAGsyYXvwUXt99h9I5iCmjjw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@es-joy/estraverse": {
|
||||
"version": "7.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@es-joy/estraverse/-/estraverse-7.1.1.tgz",
|
||||
"integrity": "sha512-h2d737iS0LFAqypZOmXizu54qAbHofI/RpD30Zom03O6BCXKHuFevWKPcGarZbGq82h7qSBb5G6kLdhTMO+caw==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"engines": {
|
||||
"node": ">=4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@es-joy/jsdoccomment": {
|
||||
"version": "0.100.0",
|
||||
"resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.100.0.tgz",
|
||||
"integrity": "sha512-QuIT5kMg3XWN22Wa1rcXmR/GkfSg6Ygs/ikMiHihdSpu+o3O59LygkFV9srKa5xHplBFwNd5ZCo3bywL4k7qMQ==",
|
||||
"version": "0.98.0",
|
||||
"resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.98.0.tgz",
|
||||
"integrity": "sha512-QS+b7I2aaSM+gZfDz1b9E4B367JJ2qTjFXRKF289iKkh9sYdZ21Q5MiF/Duzouy3J0C4VhM3I/8f2F4+zT8gYQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/estree": "^1.0.9",
|
||||
"@typescript-eslint/types": "^8.72.0",
|
||||
"@typescript-eslint/types": "^8.70.0",
|
||||
"comment-parser": "1.4.9",
|
||||
"esquery": "^1.7.0",
|
||||
"jsdoc-type-pratt-parser": "~9.3.0"
|
||||
"jsdoc-type-pratt-parser": "~9.2.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^22.22.2 || >=24.15.0"
|
||||
@@ -2744,15 +2681,20 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/sinon": {
|
||||
"version": "22.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-22.0.1.tgz",
|
||||
"integrity": "sha512-MThluJXPmpBY+Z5S3565F2z+hjkCXnBrr36j2mitVQ7JUtxA+A+YQhs+0Q6J8jxb0SVJvydO+6NWfj9EBzpiBQ==",
|
||||
"version": "22.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-22.0.0.tgz",
|
||||
"integrity": "sha512-TDbVpbccc2HfiqHR09Argj3mHV1KMW7sCCKj52fsl8lbRLkEn7fB1966EWhOKWUBcqfBueZuPoA7/OK1CKiy3g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@sinonjs/fake-timers": "^15.4.0"
|
||||
"@types/sinonjs__fake-timers": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/sinonjs__fake-timers": {
|
||||
"version": "8.1.2",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/unist": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz",
|
||||
@@ -5424,16 +5366,15 @@
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-jsdoc": {
|
||||
"version": "65.4.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-65.4.0.tgz",
|
||||
"integrity": "sha512-bRiU6LfCFmLL7GuePKvA6ZIcXLonhZGCg2TgQLmkcExeVdAirQp2Hsf3xeSUTmlKwAAsREVEOLbZYD8F7oA69g==",
|
||||
"version": "65.3.15",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-65.3.15.tgz",
|
||||
"integrity": "sha512-cpU66X+daaX2X6cndE0grdLAIlodysI3KuUEdrJd6FvQHuuYOOvMRAdy8ToYjyJrsoUv0fXkMclA5RM5kaipMw==",
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"@es-joy/escodegen": "^4.2.0",
|
||||
"@es-joy/jsdoccomment": "~0.100.0",
|
||||
"@es-joy/jsdoccomment": "~0.98.0",
|
||||
"@es-joy/resolve.exports": "1.2.0",
|
||||
"@typescript-eslint/utils": "^8.72.0",
|
||||
"@typescript-eslint/utils": "^8.70.1",
|
||||
"are-docs-informative": "^0.1.1",
|
||||
"comment-parser": "1.4.9",
|
||||
"debug": "^4.4.3",
|
||||
@@ -7229,18 +7170,36 @@
|
||||
}
|
||||
},
|
||||
"node_modules/jsdoc-type-pratt-parser": {
|
||||
"version": "9.3.0",
|
||||
"resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-9.3.0.tgz",
|
||||
"integrity": "sha512-JZ8lKMCZXDlM1jAjAK5tTmtFJtgv6iFQQfjE3Fza6jBRACUueaEXLY17n1u05JO1lcPkNxgP+ddEDtiPsk5ktg==",
|
||||
"version": "9.2.2",
|
||||
"resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-9.2.2.tgz",
|
||||
"integrity": "sha512-eFY7Rlscvv/BpY6UsVsjKwMhu1tJO/F4U/vC9g3yeRy/JqszuO1UP6Vdq+85G+3FP6fEw/sWR8a5ftPFY86csw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/estree": "^1.0.9"
|
||||
"@types/estree": "^1.0.9",
|
||||
"@types/node": "^26.4.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^22.22.2 || >=24.15.0"
|
||||
}
|
||||
},
|
||||
"node_modules/jsdoc-type-pratt-parser/node_modules/@types/node": {
|
||||
"version": "26.6.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-26.6.2.tgz",
|
||||
"integrity": "sha512-X1P21scMv4zGKLYqjdGjaKa7COa0RKVYYZZN/NfvLQ1JegxFhdhpZG/Lyn8AXx6CDUavKAd11v6BvfpkDByK8g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"undici-types": "~8.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/jsdoc-type-pratt-parser/node_modules/undici-types": {
|
||||
"version": "8.9.0",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-8.9.0.tgz",
|
||||
"integrity": "sha512-KTDyRTYX8sWmKXAikPHHSyc63CRPETMctyjKFupcC6OBLXT3xsN0e9aF7m+mIXutFWpUXuedtowG7iLOzp0kQg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/json-buffer": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
|
||||
@@ -8401,18 +8360,16 @@
|
||||
}
|
||||
},
|
||||
"node_modules/optionator": {
|
||||
"version": "0.9.4",
|
||||
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
|
||||
"integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==",
|
||||
"version": "0.9.3",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@aashutoshrathi/word-wrap": "^1.2.3",
|
||||
"deep-is": "^0.1.3",
|
||||
"fast-levenshtein": "^2.0.6",
|
||||
"levn": "^0.4.1",
|
||||
"prelude-ls": "^1.2.1",
|
||||
"type-check": "^0.4.0",
|
||||
"word-wrap": "^1.2.5"
|
||||
"type-check": "^0.4.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.8.0"
|
||||
@@ -9336,17 +9293,6 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/source-map": {
|
||||
"version": "0.7.6",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz",
|
||||
"integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==",
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"optional": true,
|
||||
"engines": {
|
||||
"node": ">= 12"
|
||||
}
|
||||
},
|
||||
"node_modules/spdx-exceptions": {
|
||||
"version": "2.5.0",
|
||||
"resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz",
|
||||
@@ -10380,16 +10326,6 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/word-wrap": {
|
||||
"version": "1.2.5",
|
||||
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
|
||||
"integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/wrap-ansi": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
|
||||
|
||||
+2
-2
@@ -58,14 +58,14 @@
|
||||
"@types/node-forge": "^1.3.14",
|
||||
"@types/sarif": "^2.1.7",
|
||||
"@types/semver": "^7.8.0",
|
||||
"@types/sinon": "^22.0.1",
|
||||
"@types/sinon": "^22.0.0",
|
||||
"ava": "^6.4.1",
|
||||
"esbuild": "^0.28.2",
|
||||
"eslint": "^9.39.5",
|
||||
"eslint-import-resolver-typescript": "^4.4.5",
|
||||
"eslint-plugin-github": "^6.1.2",
|
||||
"eslint-plugin-import-x": "^4.17.1",
|
||||
"eslint-plugin-jsdoc": "^65.4.0",
|
||||
"eslint-plugin-jsdoc": "^65.3.15",
|
||||
"eslint-plugin-no-async-foreach": "^0.1.1",
|
||||
"glob": "^13.0.6",
|
||||
"globals": "^17.13.0",
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
name: "Unsupported macOS"
|
||||
description: "Tests that unsupported macOS versions are detected and result in appropriate diagnostics."
|
||||
versions:
|
||||
- linked
|
||||
- nightly-latest
|
||||
installNode: true
|
||||
|
||||
operatingSystems:
|
||||
- os: macos
|
||||
runner-image: xcode-27
|
||||
|
||||
env:
|
||||
# Allow the failed SARIF file to be generated.
|
||||
CODEQL_ACTION_SKIP_GENERATE_FAILED_SARIF: false
|
||||
# But don't actually upload it.
|
||||
CODEQL_ACTION_SKIP_SARIF_UPLOAD: true
|
||||
# Mark telemetry for this workflow so it can be treated separately.
|
||||
CODEQL_ACTION_TESTING_ENVIRONMENT: codeql-action-pr-checks
|
||||
|
||||
steps:
|
||||
- name: Check xcode_select_link
|
||||
run: |
|
||||
readlink /private/var/db/xcode_select_link
|
||||
file -h /private/var/db/xcode_select_link
|
||||
|
||||
- uses: ./../action/init
|
||||
id: init
|
||||
continue-on-error: true
|
||||
env:
|
||||
CODEQL_ACTION_CHECK_UNSUPPORTED_TRACED_ANALYSIS: true
|
||||
CODEQL_ACTION_SKIP_UNSUPPORTED_TRACED_ANALYSIS: true
|
||||
with:
|
||||
languages: swift
|
||||
tools: ${{ steps.prepare-test.outputs.tools-url }}
|
||||
|
||||
- name: Analyze
|
||||
# We could run `analyze` here from `./../analyze`, but `getAnalyzeActionName` in `workflow.ts`
|
||||
# can't cope with that unless we introduce a different testing environment. Since this step
|
||||
# would just fail on `xcode-27` anyway, we just skip it instead.
|
||||
if: false
|
||||
uses: ./analyze
|
||||
with:
|
||||
category: "/test-codeql-version:${{ matrix.version }}"
|
||||
|
||||
validationJobs:
|
||||
unsupported-macos-sarif-checks:
|
||||
checkout: true
|
||||
installNode: true
|
||||
steps:
|
||||
- name: Download workflow artifact
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
with:
|
||||
pattern: test-mode-sarif-*
|
||||
path: sarif
|
||||
|
||||
- name: List artifact contents
|
||||
run: ls -laR ./sarif
|
||||
|
||||
- name: Check diagnostics appear in SARIF
|
||||
env:
|
||||
SARIF_PATH: "./sarif/"
|
||||
DIAGNOSTIC_ID: "codeql-action/unsupported-traced-analysis-macos"
|
||||
DIAGNOSTIC_NAME: "Traced analysis is not supported on this version of macOS"
|
||||
EXPECTED_LOCATIONS: "0"
|
||||
EXPECTED_MESSAGE: |
|
||||
Traced analysis is not supported on macOS 27 or above.
|
||||
run: npx tsx ./pr-checks/check-diagnostics.ts
|
||||
+8
-1
@@ -124,6 +124,8 @@ interface JobSpecification {
|
||||
|
||||
type ValidationJobSpecification = JobSpecification & {
|
||||
checkout?: boolean;
|
||||
/** Optional condition for the validation job. */
|
||||
if?: string;
|
||||
};
|
||||
|
||||
/** Describes language/framework-specific steps and inputs. */
|
||||
@@ -666,9 +668,14 @@ function generateValidationJob(
|
||||
// Add the generated steps in front of the ones from the specification.
|
||||
specSteps.items.unshift(...checkoutStep, ...steps);
|
||||
|
||||
const baseCondition = "github.triggering_actor != 'dependabot[bot]'";
|
||||
|
||||
const validationJob: Record<string, any> = {
|
||||
name: jobSpecification.name,
|
||||
if: "github.triggering_actor != 'dependabot[bot]'",
|
||||
if:
|
||||
jobSpecification.if !== undefined
|
||||
? `${baseCondition} && ${jobSpecification.if}`
|
||||
: baseCondition,
|
||||
needs: [checkName],
|
||||
permissions: {
|
||||
contents: "read",
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import * as os from "os";
|
||||
|
||||
import * as core from "@actions/core";
|
||||
|
||||
import { ActionsEnv, getActionsEnv } from "./actions-util";
|
||||
@@ -13,6 +15,8 @@ import {
|
||||
} from "./status-report";
|
||||
import { getEnv, getErrorMessage, wrapError } from "./util";
|
||||
|
||||
export type { Logger } from "./logging";
|
||||
|
||||
/** Base state that is available to an Action on startup. */
|
||||
export interface BaseState {
|
||||
/** The name of the Action. */
|
||||
@@ -23,6 +27,8 @@ export interface BaseState {
|
||||
platform: NodeJS.Platform;
|
||||
/** The architecture of the host. */
|
||||
arch: NodeJS.Architecture;
|
||||
/** The version of the operating system. */
|
||||
osRelease: string;
|
||||
}
|
||||
|
||||
/** Describes different state features that an Action may have. */
|
||||
@@ -173,6 +179,7 @@ export async function runInActions(action: Action) {
|
||||
startedAt,
|
||||
platform: process.platform,
|
||||
arch: process.arch,
|
||||
osRelease: os.release(),
|
||||
logger,
|
||||
env,
|
||||
actions: actionsEnv,
|
||||
|
||||
+1
-1
@@ -364,7 +364,7 @@ const MAX_STDERR_BUFFER_SIZE = 20000;
|
||||
* @throws A {@link CommandInvocationError} if the tool exits with a non-zero status code.
|
||||
*/
|
||||
export async function runTool(
|
||||
env: Env,
|
||||
env: ReadOnlyEnv,
|
||||
cmd: string,
|
||||
args: string[] = [],
|
||||
opts: { stdin?: string; noStreamStdout?: boolean } = {},
|
||||
|
||||
+2
-2
@@ -1166,7 +1166,7 @@ export function getExtraOptions(
|
||||
}
|
||||
|
||||
async function runCli(
|
||||
env: Env,
|
||||
env: ReadOnlyEnv,
|
||||
cmd: string,
|
||||
args: string[] = [],
|
||||
opts: { stdin?: string; noStreamStdout?: boolean } = {},
|
||||
@@ -1193,7 +1193,7 @@ async function runCli(
|
||||
* @returns The parsed JSON output from the command.
|
||||
*/
|
||||
async function runCliJson<T>(
|
||||
env: Env,
|
||||
env: ReadOnlyEnv,
|
||||
cmd: string,
|
||||
args: string[] = [],
|
||||
opts: { stdin?: string; noStreamStdout?: boolean } = {},
|
||||
|
||||
@@ -12,4 +12,6 @@ export enum DocUrl {
|
||||
SPECIFY_BUILD_STEPS_MANUALLY = "https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages#about-specifying-build-steps-manually",
|
||||
SYSTEM_REQUIREMENTS = "https://codeql.github.com/docs/codeql-overview/system-requirements/",
|
||||
TRACK_CODE_SCANNING_ALERTS_ACROSS_RUNS = "https://docs.github.com/en/code-security/reference/code-scanning/sarif-support-for-code-scanning#data-for-preventing-duplicated-alerts",
|
||||
/** Blog post about traced analysis being unsupported on macOS 27 and with Xcode 27. */
|
||||
UNSUPPORTED_TRACED_ANALYSIS_MACOS27 = "https://github.blog/changelog/2026-10-19-codeql-changes-for-macos-27-xcode-27-and-swift-6-4/",
|
||||
}
|
||||
@@ -74,6 +74,11 @@ export enum Feature {
|
||||
AllowMergeConfigFiles = "allow_merge_config_files",
|
||||
/** Controls whether we allow multiple values for the `analysis-kinds` input. */
|
||||
AllowMultipleAnalysisKinds = "allow_multiple_analysis_kinds",
|
||||
/**
|
||||
* Whether to check for unsupported traced analysis. Primarily intended as an override to disable
|
||||
* the check if it causes problems somehow.
|
||||
*/
|
||||
CheckUnsupportedTracedAnalysis = "check_unsupported_traced_analysis",
|
||||
/** Whether to allow the `config-file` input to be specified via a repository property. */
|
||||
ConfigFileRepositoryProperty = "config_file_repository_property",
|
||||
CppDependencyInstallation = "cpp_dependency_installation_enabled",
|
||||
@@ -144,6 +149,8 @@ export enum Feature {
|
||||
/** Controls whether overlay build failures on the default branch are stored in the Actions cache. */
|
||||
OverlayAnalysisStatusSave = "overlay_analysis_status_save",
|
||||
QaTelemetryEnabled = "qa_telemetry_enabled",
|
||||
/** Whether we should fail early if we detect that traced analysis is unsupported. */
|
||||
SkipUnsupportedTracedAnalysis = "skip_unsupported_traced_analysis",
|
||||
/** Routes (some) API requests through the registry proxy. */
|
||||
ProxyApiRequests = "proxy_api_requests",
|
||||
/** Note that this currently only disables baseline file coverage information. */
|
||||
@@ -195,6 +202,11 @@ export const featureConfig = {
|
||||
envVar: "CODEQL_ACTION_ALLOW_MULTIPLE_ANALYSIS_KINDS",
|
||||
minimumVersion: undefined,
|
||||
},
|
||||
[Feature.CheckUnsupportedTracedAnalysis]: {
|
||||
defaultValue: false,
|
||||
envVar: "CODEQL_ACTION_CHECK_UNSUPPORTED_TRACED_ANALYSIS",
|
||||
minimumVersion: undefined,
|
||||
},
|
||||
[Feature.ConfigFileRepositoryProperty]: {
|
||||
defaultValue: false,
|
||||
envVar: "CODEQL_ACTION_CONFIG_FILE_REPOSITORY_PROPERTY",
|
||||
@@ -410,6 +422,11 @@ export const featureConfig = {
|
||||
envVar: "CODEQL_ACTION_START_PROXY_USE_FEATURES_RELEASE",
|
||||
minimumVersion: undefined,
|
||||
},
|
||||
[Feature.SkipUnsupportedTracedAnalysis]: {
|
||||
defaultValue: false,
|
||||
envVar: "CODEQL_ACTION_SKIP_UNSUPPORTED_TRACED_ANALYSIS",
|
||||
minimumVersion: undefined,
|
||||
},
|
||||
[Feature.ToolsRepositoryProperty]: {
|
||||
defaultValue: false,
|
||||
envVar: "CODEQL_ACTION_TOOLS_REPOSITORY_PROPERTY",
|
||||
|
||||
+6
-2
@@ -62,7 +62,7 @@ import {
|
||||
runDatabaseInitCluster,
|
||||
} from "./init";
|
||||
import { JavaEnvVars, BuiltInLanguage } from "./languages";
|
||||
import { checkSwiftCompatibility } from "./languages/swift";
|
||||
import { checkRunnerSupportsTracedAnalysis } from "./languages/traced";
|
||||
import { Logger, withGroupAsync } from "./logging";
|
||||
import {
|
||||
downloadOverlayBaseDatabaseFromCache,
|
||||
@@ -419,7 +419,11 @@ async function run(
|
||||
logger,
|
||||
});
|
||||
|
||||
checkSwiftCompatibility(actionState, config);
|
||||
await checkRunnerSupportsTracedAnalysis(
|
||||
actionStateWithFeatures,
|
||||
config,
|
||||
codeql,
|
||||
);
|
||||
|
||||
if (repositoryPropertiesResult.isFailure()) {
|
||||
addNoLanguageDiagnostic(
|
||||
|
||||
+44
-25
@@ -6,31 +6,66 @@ import {
|
||||
createTestConfig,
|
||||
getCodeQLForTesting,
|
||||
getTestEnv,
|
||||
initAllState,
|
||||
makeVersionInfo,
|
||||
RecordingLogger,
|
||||
setupTests,
|
||||
} from "../testing-utils";
|
||||
import { ConfigurationError, withTmpDir } from "../util";
|
||||
import { ToolsFeature } from "../tools-features";
|
||||
import { withTmpDir } from "../util";
|
||||
|
||||
import { checkSwiftCompatibility } from "./swift";
|
||||
|
||||
import { BuiltInLanguage } from ".";
|
||||
|
||||
test("checkSwiftCompatibility doesn't throw for non-Swift languages", (t) => {
|
||||
setupTests(test);
|
||||
|
||||
test("checkSwiftCompatibility doesn't throw for non-Swift languages", async (t) => {
|
||||
for (const language of Object.values(BuiltInLanguage)) {
|
||||
if (language === BuiltInLanguage.swift) {
|
||||
continue;
|
||||
}
|
||||
|
||||
t.notThrows(() =>
|
||||
const codeql = await getCodeQLForTesting();
|
||||
await t.notThrowsAsync(
|
||||
checkSwiftCompatibility(
|
||||
initAllState(),
|
||||
createTestConfig({ languages: [language] }),
|
||||
codeql,
|
||||
// A value of `undefined` should make `isSwiftCompatible` throw for Swift by default
|
||||
// since it means we are on a platform other than macOS
|
||||
undefined,
|
||||
),
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
test("checkSwiftCompatibility doesn't throw for Swift if CLI supports swiftSupportsAllPlatforms", async (t) =>
|
||||
withTmpDir(async (tmpDir) => {
|
||||
const logger = new RecordingLogger();
|
||||
const env = getTestEnv();
|
||||
env.set(ActionsEnvVars.RUNNER_TEMP, tmpDir);
|
||||
|
||||
const codeql = await getCodeQLForTesting("codeql-for-testing", logger, env);
|
||||
const supportsFeature = sinon
|
||||
.stub(codeql, "supportsFeature")
|
||||
.withArgs(ToolsFeature.SwiftSupportsAllPlatforms)
|
||||
.resolves(true);
|
||||
|
||||
await t.notThrowsAsync(
|
||||
checkSwiftCompatibility(
|
||||
createTestConfig({ languages: [BuiltInLanguage.swift] }),
|
||||
codeql,
|
||||
// A value of `undefined` should make `isSwiftCompatible` throw for Swift by default
|
||||
// since it means we are on a platform other than macOS
|
||||
undefined,
|
||||
),
|
||||
);
|
||||
|
||||
t.is(supportsFeature.callCount, 1);
|
||||
t.deepEqual(supportsFeature.args[0], [
|
||||
ToolsFeature.SwiftSupportsAllPlatforms,
|
||||
]);
|
||||
}));
|
||||
|
||||
test("checkSwiftCompatibility doesn't throw for Swift on darwin", async (t) =>
|
||||
withTmpDir(async (tmpDir) => {
|
||||
const logger = new RecordingLogger();
|
||||
@@ -40,31 +75,15 @@ test("checkSwiftCompatibility doesn't throw for Swift on darwin", async (t) =>
|
||||
const codeql = await getCodeQLForTesting("codeql-for-testing", logger, env);
|
||||
sinon.stub(codeql, "getVersion").resolves(makeVersionInfo("2.27.0"));
|
||||
|
||||
t.notThrows(() =>
|
||||
await t.notThrowsAsync(
|
||||
checkSwiftCompatibility(
|
||||
initAllState({ platform: "darwin", env, logger }),
|
||||
createTestConfig({
|
||||
tempDir: tmpDir,
|
||||
languages: [BuiltInLanguage.swift],
|
||||
}),
|
||||
codeql,
|
||||
// A value other than `undefined` means we are on macOS.
|
||||
"some-macos-version",
|
||||
),
|
||||
);
|
||||
}));
|
||||
|
||||
const nonDarwinPlatforms: NodeJS.Platform[] = ["linux", "win32"];
|
||||
for (const nonDarwinPlatform of nonDarwinPlatforms) {
|
||||
test(`checkSwiftCompatibility throws for Swift on ${nonDarwinPlatform}`, (t) => {
|
||||
t.throws(
|
||||
() => {
|
||||
checkSwiftCompatibility(
|
||||
initAllState({ platform: nonDarwinPlatform }),
|
||||
createTestConfig({ languages: [BuiltInLanguage.swift] }),
|
||||
);
|
||||
},
|
||||
{
|
||||
instanceOf: ConfigurationError,
|
||||
message: /^Swift analysis is only supported on macOS runner images/,
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
+25
-10
@@ -1,5 +1,8 @@
|
||||
import { ActionState } from "../action-common";
|
||||
import { Config } from "../config-utils";
|
||||
import type { SemVer } from "semver";
|
||||
|
||||
import { CodeQL } from "../codeql";
|
||||
import type { ActionConfig } from "../config/action-config";
|
||||
import { ToolsFeature } from "../tools-features";
|
||||
import { ConfigurationError } from "../util";
|
||||
|
||||
import { BuiltInLanguage } from ".";
|
||||
@@ -7,19 +10,31 @@ import { BuiltInLanguage } from ".";
|
||||
/**
|
||||
* Determines whether we can run a Swift analysis on the current runner.
|
||||
*
|
||||
* @param action The Action state.
|
||||
* @param config The Action configuration.
|
||||
* @param codeql The {@link CodeQL} CLI instance.
|
||||
* @param darwinVersion The version of the Darwin kernel on macOS, if any.
|
||||
*
|
||||
* @throws {ConfigurationError} If Swift analysis is not possible on the current runner.
|
||||
*/
|
||||
export function checkSwiftCompatibility(
|
||||
action: ActionState<["Base"]>,
|
||||
config: Config,
|
||||
export async function checkSwiftCompatibility(
|
||||
config: ActionConfig<"languages">,
|
||||
codeql: CodeQL,
|
||||
darwinVersion: SemVer | string | undefined,
|
||||
) {
|
||||
if (
|
||||
config.languages.includes(BuiltInLanguage.swift) &&
|
||||
action.platform !== "darwin"
|
||||
) {
|
||||
// The checks are not relevant if we are not trying to analyse Swift.
|
||||
if (!config.languages.includes(BuiltInLanguage.swift)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Skip the checks if the `swiftSupportsAllPlatforms` feature is supported by the CLI.
|
||||
// This is a forward-looking measure that allows a future CLI update to disable these
|
||||
// platform checks in the Action when they shouldn't be enforced anymore.
|
||||
if (await codeql.supportsFeature(ToolsFeature.SwiftSupportsAllPlatforms)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If `darwinVersion` is undefined, then we are not on macOS and Swift analysis is unsupported.
|
||||
if (darwinVersion === undefined) {
|
||||
throw new ConfigurationError(
|
||||
`Swift analysis is only supported on macOS runner images. Please migrate to a macOS runner.`,
|
||||
);
|
||||
|
||||
@@ -0,0 +1,531 @@
|
||||
import fs from "fs";
|
||||
|
||||
import test from "ava";
|
||||
import * as sinon from "sinon";
|
||||
|
||||
import { type CodeQL } from "../codeql";
|
||||
import * as diagnostics from "../diagnostics";
|
||||
import { ActionsEnvVars, type Env } from "../environment";
|
||||
import { Feature } from "../feature-flags";
|
||||
import type { Logger } from "../logging";
|
||||
import { XCODE_SELECT_LINK_PATH } from "../platform";
|
||||
import {
|
||||
checkExpectedLogMessages,
|
||||
checkUnexpectedLogMessages,
|
||||
createFeatures,
|
||||
createTestConfig,
|
||||
getCodeQLForTesting,
|
||||
getTestEnv,
|
||||
initAllState,
|
||||
makeVersionInfo,
|
||||
RecordingLogger,
|
||||
setupTests,
|
||||
} from "../testing-utils";
|
||||
import { BuildMode, ConfigurationError, withTmpDir } from "../util";
|
||||
|
||||
import { checkRunnerSupportsTracedAnalysis } from "./traced";
|
||||
|
||||
import { BuiltInLanguage } from ".";
|
||||
|
||||
setupTests(test);
|
||||
|
||||
const TEST_DEFAULT_TRACED_LANGUAGES = {
|
||||
[BuiltInLanguage.swift]: true,
|
||||
[BuiltInLanguage.go]: true,
|
||||
};
|
||||
|
||||
async function getCodeQLWithTracedStub(
|
||||
cmd: string,
|
||||
logger: Logger,
|
||||
env: Env,
|
||||
tracedLanguages: Partial<
|
||||
Record<BuiltInLanguage, boolean>
|
||||
> = TEST_DEFAULT_TRACED_LANGUAGES,
|
||||
): Promise<CodeQL> {
|
||||
const codeql = await getCodeQLForTesting(cmd, logger, env);
|
||||
sinon.stub(codeql, "isTracedLanguage").callsFake(async (language) => {
|
||||
return tracedLanguages[language] === true;
|
||||
});
|
||||
return codeql;
|
||||
}
|
||||
|
||||
const nonDarwinPlatforms: NodeJS.Platform[] = ["linux", "win32"];
|
||||
for (const nonDarwinPlatform of nonDarwinPlatforms) {
|
||||
test(`checkRunnerSupportsTracedAnalysis throws for Swift on ${nonDarwinPlatform}`, async (t) =>
|
||||
withTmpDir(async (tmpDir) => {
|
||||
const logger = new RecordingLogger();
|
||||
const env = getTestEnv();
|
||||
env.set(ActionsEnvVars.RUNNER_TEMP, tmpDir);
|
||||
|
||||
const codeql = await getCodeQLWithTracedStub(
|
||||
"codeql-for-testing",
|
||||
logger,
|
||||
env,
|
||||
);
|
||||
sinon.stub(codeql, "getVersion").resolves(makeVersionInfo("2.27.0"));
|
||||
|
||||
await t.throwsAsync(
|
||||
checkRunnerSupportsTracedAnalysis(
|
||||
initAllState({ platform: nonDarwinPlatform, env, logger }),
|
||||
createTestConfig({ languages: [BuiltInLanguage.swift] }),
|
||||
codeql,
|
||||
),
|
||||
{
|
||||
instanceOf: ConfigurationError,
|
||||
message: /^Swift analysis is only supported on macOS runner images/,
|
||||
},
|
||||
);
|
||||
}));
|
||||
}
|
||||
|
||||
test(`checkRunnerSupportsTracedAnalysis doesn't throw for BMN`, async (t) =>
|
||||
withTmpDir(async (tmpDir) => {
|
||||
const logger = new RecordingLogger();
|
||||
const env = getTestEnv();
|
||||
env.set(ActionsEnvVars.RUNNER_TEMP, tmpDir);
|
||||
|
||||
const codeql = await getCodeQLWithTracedStub(
|
||||
"codeql-for-testing",
|
||||
logger,
|
||||
env,
|
||||
);
|
||||
sinon.stub(codeql, "getVersion").resolves(makeVersionInfo("2.27.0"));
|
||||
|
||||
await t.notThrowsAsync(
|
||||
checkRunnerSupportsTracedAnalysis(
|
||||
initAllState({
|
||||
platform: "darwin",
|
||||
osRelease: "27.0.0",
|
||||
env,
|
||||
logger,
|
||||
}),
|
||||
createTestConfig({ buildMode: BuildMode.None }),
|
||||
codeql,
|
||||
),
|
||||
);
|
||||
}));
|
||||
|
||||
// Some languages not in `TEST_DEFAULT_TRACED_LANGUAGES`.
|
||||
const nonTracedLanguages: BuiltInLanguage[] = [
|
||||
BuiltInLanguage.javascript,
|
||||
BuiltInLanguage.actions,
|
||||
];
|
||||
for (const nonTracedLanguage of nonTracedLanguages) {
|
||||
test(`checkRunnerSupportsTracedAnalysis doesn't throw for ${nonTracedLanguage} on unsupported macOS`, async (t) =>
|
||||
withTmpDir(async (tmpDir) => {
|
||||
const logger = new RecordingLogger();
|
||||
const env = getTestEnv();
|
||||
env.set(ActionsEnvVars.RUNNER_TEMP, tmpDir);
|
||||
|
||||
const codeql = await getCodeQLWithTracedStub(
|
||||
"codeql-for-testing",
|
||||
logger,
|
||||
env,
|
||||
);
|
||||
sinon.stub(codeql, "getVersion").resolves(makeVersionInfo("2.27.0"));
|
||||
|
||||
await t.notThrowsAsync(
|
||||
checkRunnerSupportsTracedAnalysis(
|
||||
initAllState({
|
||||
platform: "darwin",
|
||||
osRelease: "27.0.0",
|
||||
env,
|
||||
logger,
|
||||
}),
|
||||
createTestConfig({ languages: [nonTracedLanguage] }),
|
||||
codeql,
|
||||
),
|
||||
);
|
||||
}));
|
||||
}
|
||||
|
||||
test("checkRunnerSupportsTracedAnalysis doesn't perform checks if FF is not enabled", async (t) =>
|
||||
withTmpDir(async (tmpDir) => {
|
||||
const logger = new RecordingLogger();
|
||||
const env = getTestEnv();
|
||||
env.set(ActionsEnvVars.RUNNER_TEMP, tmpDir);
|
||||
const features = createFeatures([]);
|
||||
|
||||
const codeql = await getCodeQLWithTracedStub(
|
||||
"codeql-for-testing",
|
||||
logger,
|
||||
env,
|
||||
);
|
||||
sinon.stub(codeql, "getVersion").resolves(makeVersionInfo("2.27.0"));
|
||||
|
||||
await checkRunnerSupportsTracedAnalysis(
|
||||
initAllState({
|
||||
logger,
|
||||
platform: "darwin",
|
||||
osRelease: "unexpected",
|
||||
env,
|
||||
features,
|
||||
}),
|
||||
createTestConfig({ languages: [BuiltInLanguage.go] }),
|
||||
codeql,
|
||||
);
|
||||
|
||||
checkUnexpectedLogMessages(t, logger.messages, [
|
||||
"Unable to determine version of macOS, got: unexpected",
|
||||
]);
|
||||
}));
|
||||
|
||||
test("checkRunnerSupportsTracedAnalysis warns if version string is not a semver", async (t) =>
|
||||
withTmpDir(async (tmpDir) => {
|
||||
const logger = new RecordingLogger();
|
||||
const env = getTestEnv();
|
||||
env.set(ActionsEnvVars.RUNNER_TEMP, tmpDir);
|
||||
const features = createFeatures([Feature.CheckUnsupportedTracedAnalysis]);
|
||||
|
||||
const codeql = await getCodeQLWithTracedStub(
|
||||
"codeql-for-testing",
|
||||
logger,
|
||||
env,
|
||||
);
|
||||
sinon.stub(codeql, "getVersion").resolves(makeVersionInfo("2.27.0"));
|
||||
|
||||
await checkRunnerSupportsTracedAnalysis(
|
||||
initAllState({
|
||||
logger,
|
||||
platform: "darwin",
|
||||
osRelease: "unexpected",
|
||||
env,
|
||||
features,
|
||||
}),
|
||||
createTestConfig({ languages: [BuiltInLanguage.go] }),
|
||||
codeql,
|
||||
);
|
||||
|
||||
checkExpectedLogMessages(t, logger.messages, [
|
||||
"Unable to determine version of macOS, got: unexpected",
|
||||
]);
|
||||
}));
|
||||
|
||||
// `addDiagnostic` changes global state and we must stub it, so this test must be serial.
|
||||
test.serial(
|
||||
"checkRunnerSupportsTracedAnalysis logs and adds diagnostic if macOS version is unsupported",
|
||||
async (t) =>
|
||||
withTmpDir(async (tmpDir) => {
|
||||
const logger = new RecordingLogger();
|
||||
const features = createFeatures([Feature.CheckUnsupportedTracedAnalysis]);
|
||||
const env = getTestEnv();
|
||||
env.set(ActionsEnvVars.RUNNER_TEMP, tmpDir);
|
||||
|
||||
const codeql = await getCodeQLWithTracedStub(
|
||||
"codeql-for-testing",
|
||||
logger,
|
||||
env,
|
||||
);
|
||||
sinon.stub(codeql, "getVersion").resolves(makeVersionInfo("2.27.0"));
|
||||
|
||||
const addDiagnostic = sinon.stub(diagnostics, "addDiagnostic");
|
||||
|
||||
const config = createTestConfig({ languages: [BuiltInLanguage.swift] });
|
||||
await checkRunnerSupportsTracedAnalysis(
|
||||
initAllState({
|
||||
logger,
|
||||
platform: "darwin",
|
||||
osRelease: "27.0.0",
|
||||
env,
|
||||
features,
|
||||
}),
|
||||
config,
|
||||
codeql,
|
||||
);
|
||||
|
||||
checkExpectedLogMessages(t, logger.messages, [
|
||||
"Traced analysis is not supported on macOS 27",
|
||||
]);
|
||||
|
||||
t.is(addDiagnostic.callCount, 1);
|
||||
t.like(addDiagnostic.args[0], [
|
||||
config,
|
||||
BuiltInLanguage.swift,
|
||||
{
|
||||
attributes: {
|
||||
languages: [BuiltInLanguage.swift],
|
||||
darwinVersion: "27.0.0",
|
||||
},
|
||||
severity: "warning",
|
||||
source: {
|
||||
id: "codeql-action/unsupported-traced-analysis-macos",
|
||||
name: "Traced analysis is not supported on this version of macOS",
|
||||
},
|
||||
visibility: {
|
||||
cliSummaryTable: true,
|
||||
statusPage: true,
|
||||
telemetry: true,
|
||||
},
|
||||
} satisfies Partial<diagnostics.DiagnosticMessage>,
|
||||
]);
|
||||
}),
|
||||
);
|
||||
|
||||
// `addDiagnostic` changes global state and we must stub it, so this test must be serial.
|
||||
test.serial(
|
||||
"checkRunnerSupportsTracedAnalysis throws if macOS version is unsupported and FF is enabled",
|
||||
async (t) =>
|
||||
withTmpDir(async (tmpDir) => {
|
||||
const logger = new RecordingLogger();
|
||||
const env = getTestEnv();
|
||||
env.set(ActionsEnvVars.RUNNER_TEMP, tmpDir);
|
||||
|
||||
const features = createFeatures([
|
||||
Feature.CheckUnsupportedTracedAnalysis,
|
||||
Feature.SkipUnsupportedTracedAnalysis,
|
||||
]);
|
||||
|
||||
const codeql = await getCodeQLWithTracedStub(
|
||||
"codeql-for-testing",
|
||||
logger,
|
||||
env,
|
||||
);
|
||||
sinon.stub(codeql, "getVersion").resolves(makeVersionInfo("2.27.0"));
|
||||
|
||||
const addDiagnostic = sinon.stub(diagnostics, "addDiagnostic");
|
||||
|
||||
const config = createTestConfig({ languages: [BuiltInLanguage.swift] });
|
||||
await t.throwsAsync(
|
||||
checkRunnerSupportsTracedAnalysis(
|
||||
initAllState({
|
||||
logger,
|
||||
platform: "darwin",
|
||||
osRelease: "27.0.0",
|
||||
env,
|
||||
features,
|
||||
}),
|
||||
config,
|
||||
codeql,
|
||||
),
|
||||
);
|
||||
|
||||
t.is(addDiagnostic.callCount, 1);
|
||||
t.like(addDiagnostic.args[0], [
|
||||
config,
|
||||
BuiltInLanguage.swift,
|
||||
{
|
||||
attributes: {
|
||||
languages: [BuiltInLanguage.swift],
|
||||
darwinVersion: "27.0.0",
|
||||
},
|
||||
severity: "error",
|
||||
source: {
|
||||
id: "codeql-action/unsupported-traced-analysis-macos",
|
||||
name: "Traced analysis is not supported on this version of macOS",
|
||||
},
|
||||
visibility: {
|
||||
cliSummaryTable: true,
|
||||
statusPage: true,
|
||||
telemetry: true,
|
||||
},
|
||||
} satisfies Partial<diagnostics.DiagnosticMessage>,
|
||||
]);
|
||||
}),
|
||||
);
|
||||
|
||||
// `addDiagnostic` changes global state and we must stub it, so this test must be serial.
|
||||
test.serial(
|
||||
"checkRunnerSupportsTracedAnalysis doesn't add a diagnostic if Xcode version is supported",
|
||||
async (t) =>
|
||||
withTmpDir(async (tmpDir) => {
|
||||
const logger = new RecordingLogger();
|
||||
const env = getTestEnv();
|
||||
env.set(ActionsEnvVars.RUNNER_TEMP, tmpDir);
|
||||
const features = createFeatures([Feature.CheckUnsupportedTracedAnalysis]);
|
||||
|
||||
const lstatSync = sinon
|
||||
.stub(fs, "lstatSync")
|
||||
.returns({ isSymbolicLink: () => true } as fs.Stats);
|
||||
const readlinkSync = sinon
|
||||
.stub(fs, "readlinkSync")
|
||||
.returns("/Applications/Xcode_26.0.app/Contents/Developer");
|
||||
|
||||
const codeql = await getCodeQLWithTracedStub(
|
||||
"codeql-for-testing",
|
||||
logger,
|
||||
env,
|
||||
);
|
||||
sinon.stub(codeql, "getVersion").resolves(makeVersionInfo("2.27.0"));
|
||||
|
||||
const addDiagnostic = sinon.stub(diagnostics, "addDiagnostic");
|
||||
|
||||
const config = createTestConfig({ languages: [BuiltInLanguage.swift] });
|
||||
await checkRunnerSupportsTracedAnalysis(
|
||||
initAllState({
|
||||
logger,
|
||||
platform: "darwin",
|
||||
osRelease: "26.0.0",
|
||||
env,
|
||||
features,
|
||||
}),
|
||||
config,
|
||||
codeql,
|
||||
);
|
||||
|
||||
t.is(lstatSync.callCount, 1);
|
||||
t.deepEqual(lstatSync.args[0], [
|
||||
XCODE_SELECT_LINK_PATH,
|
||||
{ throwIfNoEntry: false },
|
||||
]);
|
||||
t.is(readlinkSync.callCount, 1);
|
||||
t.deepEqual(readlinkSync.args[0], [XCODE_SELECT_LINK_PATH]);
|
||||
|
||||
checkUnexpectedLogMessages(t, logger.messages, [
|
||||
"Traced analysis is not supported on Xcode 27",
|
||||
]);
|
||||
|
||||
t.is(addDiagnostic.callCount, 0);
|
||||
}),
|
||||
);
|
||||
|
||||
// `addDiagnostic` changes global state and we must stub it, so this test must be serial.
|
||||
test.serial(
|
||||
"checkRunnerSupportsTracedAnalysis logs and adds diagnostic if Xcode version is unsupported",
|
||||
async (t) =>
|
||||
withTmpDir(async (tmpDir) => {
|
||||
const logger = new RecordingLogger();
|
||||
const env = getTestEnv();
|
||||
env.set(ActionsEnvVars.RUNNER_TEMP, tmpDir);
|
||||
const features = createFeatures([Feature.CheckUnsupportedTracedAnalysis]);
|
||||
|
||||
const lstatSync = sinon
|
||||
.stub(fs, "lstatSync")
|
||||
.returns({ isSymbolicLink: () => true } as fs.Stats);
|
||||
const readlinkSync = sinon
|
||||
.stub(fs, "readlinkSync")
|
||||
.returns("/Applications/Xcode_27.0.app/Contents/Developer");
|
||||
|
||||
const codeql = await getCodeQLWithTracedStub(
|
||||
"codeql-for-testing",
|
||||
logger,
|
||||
env,
|
||||
);
|
||||
sinon.stub(codeql, "getVersion").resolves(makeVersionInfo("2.27.0"));
|
||||
|
||||
const addDiagnostic = sinon.stub(diagnostics, "addDiagnostic");
|
||||
|
||||
const config = createTestConfig({ languages: [BuiltInLanguage.swift] });
|
||||
await checkRunnerSupportsTracedAnalysis(
|
||||
initAllState({
|
||||
logger,
|
||||
platform: "darwin",
|
||||
osRelease: "26.0.0",
|
||||
env,
|
||||
features,
|
||||
}),
|
||||
config,
|
||||
codeql,
|
||||
);
|
||||
|
||||
t.is(lstatSync.callCount, 1);
|
||||
t.deepEqual(lstatSync.args[0], [
|
||||
XCODE_SELECT_LINK_PATH,
|
||||
{ throwIfNoEntry: false },
|
||||
]);
|
||||
t.is(readlinkSync.callCount, 1);
|
||||
t.deepEqual(readlinkSync.args[0], [XCODE_SELECT_LINK_PATH]);
|
||||
|
||||
checkExpectedLogMessages(t, logger.messages, [
|
||||
"Traced analysis is not supported on Xcode 27",
|
||||
]);
|
||||
|
||||
t.is(addDiagnostic.callCount, 1);
|
||||
t.like(addDiagnostic.args[0], [
|
||||
config,
|
||||
BuiltInLanguage.swift,
|
||||
{
|
||||
attributes: {
|
||||
languages: [BuiltInLanguage.swift],
|
||||
xcodeVersion: "27.0.0",
|
||||
},
|
||||
severity: "warning",
|
||||
source: {
|
||||
id: "codeql-action/unsupported-traced-analysis-xcode",
|
||||
name: "Traced analysis is not supported on this version of Xcode",
|
||||
},
|
||||
visibility: {
|
||||
cliSummaryTable: true,
|
||||
statusPage: true,
|
||||
telemetry: true,
|
||||
},
|
||||
} satisfies Partial<diagnostics.DiagnosticMessage>,
|
||||
]);
|
||||
}),
|
||||
);
|
||||
|
||||
// `addDiagnostic` changes global state and we must stub it, so this test must be serial.
|
||||
test.serial(
|
||||
"checkRunnerSupportsTracedAnalysis throws if Xcode version is unsupported and FF is enabled",
|
||||
async (t) =>
|
||||
withTmpDir(async (tmpDir) => {
|
||||
const logger = new RecordingLogger();
|
||||
const env = getTestEnv();
|
||||
env.set(ActionsEnvVars.RUNNER_TEMP, tmpDir);
|
||||
|
||||
const lstatSync = sinon
|
||||
.stub(fs, "lstatSync")
|
||||
.returns({ isSymbolicLink: () => true } as fs.Stats);
|
||||
const readlinkSync = sinon
|
||||
.stub(fs, "readlinkSync")
|
||||
.returns("/Applications/Xcode_27.0.app/Contents/Developer");
|
||||
|
||||
const features = createFeatures([
|
||||
Feature.CheckUnsupportedTracedAnalysis,
|
||||
Feature.SkipUnsupportedTracedAnalysis,
|
||||
]);
|
||||
|
||||
const codeql = await getCodeQLWithTracedStub(
|
||||
"codeql-for-testing",
|
||||
logger,
|
||||
env,
|
||||
);
|
||||
sinon.stub(codeql, "getVersion").resolves(makeVersionInfo("2.27.0"));
|
||||
|
||||
const addDiagnostic = sinon.stub(diagnostics, "addDiagnostic");
|
||||
|
||||
const config = createTestConfig({ languages: [BuiltInLanguage.swift] });
|
||||
await t.throwsAsync(
|
||||
checkRunnerSupportsTracedAnalysis(
|
||||
initAllState({
|
||||
logger,
|
||||
platform: "darwin",
|
||||
osRelease: "26.0.0",
|
||||
env,
|
||||
features,
|
||||
}),
|
||||
config,
|
||||
codeql,
|
||||
),
|
||||
);
|
||||
|
||||
t.is(lstatSync.callCount, 1);
|
||||
t.deepEqual(lstatSync.args[0], [
|
||||
XCODE_SELECT_LINK_PATH,
|
||||
{ throwIfNoEntry: false },
|
||||
]);
|
||||
t.is(readlinkSync.callCount, 1);
|
||||
t.deepEqual(readlinkSync.args[0], [XCODE_SELECT_LINK_PATH]);
|
||||
|
||||
t.is(addDiagnostic.callCount, 1);
|
||||
t.like(addDiagnostic.args[0], [
|
||||
config,
|
||||
BuiltInLanguage.swift,
|
||||
{
|
||||
attributes: {
|
||||
languages: [BuiltInLanguage.swift],
|
||||
xcodeVersion: "27.0.0",
|
||||
},
|
||||
severity: "error",
|
||||
source: {
|
||||
id: "codeql-action/unsupported-traced-analysis-xcode",
|
||||
name: "Traced analysis is not supported on this version of Xcode",
|
||||
},
|
||||
visibility: {
|
||||
cliSummaryTable: true,
|
||||
statusPage: true,
|
||||
telemetry: true,
|
||||
},
|
||||
} satisfies Partial<diagnostics.DiagnosticMessage>,
|
||||
]);
|
||||
}),
|
||||
);
|
||||
@@ -0,0 +1,191 @@
|
||||
import * as semver from "semver";
|
||||
|
||||
import type { ActionState, Logger } from "../action-common";
|
||||
import type { CodeQL } from "../codeql";
|
||||
import type { ActionConfig } from "../config/action-config";
|
||||
import { addDiagnostic, makeDiagnostic } from "../diagnostics";
|
||||
import { DocUrl } from "../doc-url";
|
||||
import { Feature } from "../feature-flags";
|
||||
import { darwinVersion, xcodeVersion } from "../platform";
|
||||
import { ConfigurationError } from "../util";
|
||||
|
||||
import { checkSwiftCompatibility } from "./swift";
|
||||
|
||||
/** macOS 27 and above do not support traced extraction. */
|
||||
export const UNSUPPORTED_DARWIN_FOR_TRACED = 27;
|
||||
|
||||
/** Xcode 27 and above do not support traced extraction. */
|
||||
export const UNSUPPORTED_XCODE_FOR_TRACED = 27;
|
||||
|
||||
/**
|
||||
* Creates a diagnostic indicating that `version` of `product` is unsupported for traced analysis.
|
||||
* Depending on `skipUnsupportedTracedAnalysis`, this function then either throws a {@link ConfigurationError}
|
||||
* or logs the problem as a warning.
|
||||
*
|
||||
* @param logger The logger to use.
|
||||
* @param config The CodeQL Action configuration.
|
||||
* @param tracedLanguages Traced languages that are configured for analysis.
|
||||
* @param skipUnsupportedTracedAnalysis Whether this is a fatal error.
|
||||
* @param product The product that the version is unsupported of.
|
||||
* @param version The unsupported version.
|
||||
*/
|
||||
function handleUnsupportedVersion(
|
||||
logger: Logger,
|
||||
config: ActionConfig<"dbLocation" | "tempDir">,
|
||||
tracedLanguages: string[],
|
||||
skipUnsupportedTracedAnalysis: boolean,
|
||||
product: "macOS" | "Xcode",
|
||||
version: semver.SemVer,
|
||||
) {
|
||||
const baseMessage = [
|
||||
`Traced analysis is not supported on ${product} ${UNSUPPORTED_DARWIN_FOR_TRACED} or above.`,
|
||||
`Configure your analysis to run on macOS ${UNSUPPORTED_DARWIN_FOR_TRACED - 1} or below`,
|
||||
`and XCode ${UNSUPPORTED_XCODE_FOR_TRACED - 1} or below.`,
|
||||
].join(" ");
|
||||
|
||||
const attributeName = product === "macOS" ? "darwinVersion" : "xcodeVersion";
|
||||
|
||||
// Create a diagnostic that will show up on the TSP.
|
||||
for (const language of tracedLanguages) {
|
||||
addDiagnostic(
|
||||
config,
|
||||
language,
|
||||
makeDiagnostic(
|
||||
`codeql-action/unsupported-traced-analysis-${product.toLowerCase()}`,
|
||||
`Traced analysis is not supported on this version of ${product}`,
|
||||
{
|
||||
attributes: {
|
||||
languages: config.languages,
|
||||
[attributeName]: version.toString(),
|
||||
},
|
||||
markdownMessage: [
|
||||
baseMessage,
|
||||
`For more information, see [this announcement](${DocUrl.UNSUPPORTED_TRACED_ANALYSIS_MACOS27}).`,
|
||||
].join(" "),
|
||||
severity: skipUnsupportedTracedAnalysis ? "error" : "warning",
|
||||
visibility: {
|
||||
cliSummaryTable: true,
|
||||
statusPage: true,
|
||||
telemetry: true,
|
||||
},
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// Log messages generally don't render as markdown, so we include the URL verbatim there.
|
||||
const logMessage = [
|
||||
baseMessage,
|
||||
`For more information, see ${DocUrl.UNSUPPORTED_TRACED_ANALYSIS_MACOS27}`,
|
||||
].join(" ");
|
||||
|
||||
// Throw an error to abort the analysis if the FF is enabled or log the message.
|
||||
if (skipUnsupportedTracedAnalysis) {
|
||||
// ConfigurationErrors are converted to the "aborted" status by the exception handler
|
||||
// in `init-action.ts` that guards the call to `checkRunnerSupportsTracedAnalysis`.
|
||||
throw new ConfigurationError(logMessage);
|
||||
} else {
|
||||
// This will also show up as a workflow annotation.
|
||||
logger.warning(logMessage);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns traced languages from {@link config} by looking for tracer
|
||||
* configurations in the {@link codeql} CLI installation.
|
||||
*/
|
||||
export async function hasTracedLanguages(
|
||||
config: ActionConfig<"languages">,
|
||||
codeql: CodeQL,
|
||||
): Promise<string[]> {
|
||||
const tracedLanguages: string[] = [];
|
||||
|
||||
for (const language of config.languages) {
|
||||
if (await codeql.isTracedLanguage(language)) {
|
||||
tracedLanguages.push(language);
|
||||
}
|
||||
}
|
||||
|
||||
return tracedLanguages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether we can run a traced analysis on the current runner.
|
||||
*
|
||||
* @throws {ConfigurationError} If traced analysis is not possible on the current runner.
|
||||
*/
|
||||
export async function checkRunnerSupportsTracedAnalysis(
|
||||
action: ActionState<["Base", "Logger", "FeatureFlags"]>,
|
||||
config: ActionConfig<"languages" | "dbLocation" | "tempDir">,
|
||||
codeql: CodeQL,
|
||||
) {
|
||||
// Try to get the Darwin version on macOS.
|
||||
const version = darwinVersion(action);
|
||||
|
||||
// Perform some initial, Swift-specific checks.
|
||||
await checkSwiftCompatibility(config, codeql, version);
|
||||
|
||||
// Skip the checks for unsupported traced analysis if the FF is not enabled.
|
||||
if (
|
||||
!(await action.features.getValue(Feature.CheckUnsupportedTracedAnalysis))
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
// `build-mode: none` doesn't use the tracer, so it is always supported.
|
||||
if (config.buildMode !== undefined && config.buildMode === "none") {
|
||||
return;
|
||||
}
|
||||
|
||||
// These checks don't apply if we are not on macOS.
|
||||
if (version === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If none of the languages are traced, then we can skip the compatibility checks below as well.
|
||||
const tracedLanguages = await hasTracedLanguages(config, codeql);
|
||||
if (tracedLanguages.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const skipUnsupportedTracedAnalysis = await action.features.getValue(
|
||||
Feature.SkipUnsupportedTracedAnalysis,
|
||||
);
|
||||
if (typeof version === "string") {
|
||||
// If we got a string, we are on macOS but couldn't parse the version string.
|
||||
action.logger.warning(
|
||||
`Unable to determine version of macOS, got: ${version}`,
|
||||
);
|
||||
} else if (version.major >= UNSUPPORTED_DARWIN_FOR_TRACED) {
|
||||
handleUnsupportedVersion(
|
||||
action.logger,
|
||||
config,
|
||||
tracedLanguages,
|
||||
skipUnsupportedTracedAnalysis,
|
||||
"macOS",
|
||||
version,
|
||||
);
|
||||
|
||||
// Return early so that we don't end up producing more-or-less the same log message/diagnostic
|
||||
// twice. The ones for macOS already comment on the Xcode requirement.
|
||||
return;
|
||||
}
|
||||
|
||||
// Determining whether the Xcode version is supported only makes sense on macOS, so we only do it
|
||||
// after determining that we are running on macOS.
|
||||
const xcodeVer = xcodeVersion(action.logger);
|
||||
|
||||
if (
|
||||
xcodeVer !== undefined &&
|
||||
xcodeVer.major >= UNSUPPORTED_XCODE_FOR_TRACED
|
||||
) {
|
||||
handleUnsupportedVersion(
|
||||
action.logger,
|
||||
config,
|
||||
tracedLanguages,
|
||||
skipUnsupportedTracedAnalysis,
|
||||
"Xcode",
|
||||
xcodeVer,
|
||||
);
|
||||
}
|
||||
}
|
||||
+266
-2
@@ -1,6 +1,23 @@
|
||||
import test from "ava";
|
||||
import fs from "fs";
|
||||
|
||||
import { BundlePlatform, getBundlePlatform } from "./platform";
|
||||
import test from "ava";
|
||||
import * as sinon from "sinon";
|
||||
|
||||
import {
|
||||
BundlePlatform,
|
||||
getBundlePlatform,
|
||||
darwinVersion,
|
||||
XCODE_SELECT_LINK_PATH,
|
||||
xcodeVersion,
|
||||
} from "./platform";
|
||||
import {
|
||||
checkExpectedLogMessages,
|
||||
initAllState,
|
||||
RecordingLogger,
|
||||
setupTests,
|
||||
} from "./testing-utils";
|
||||
|
||||
setupTests(test);
|
||||
|
||||
for (const [platform, arch, expected] of [
|
||||
["linux", "x64", BundlePlatform.Linux64],
|
||||
@@ -16,3 +33,250 @@ for (const [platform, arch, expected] of [
|
||||
t.is(getBundlePlatform(platform, arch), expected);
|
||||
});
|
||||
}
|
||||
|
||||
const platforms: NodeJS.Platform[] = ["linux", "win32", "freebsd"];
|
||||
for (const platform of platforms) {
|
||||
test(`darwinVersion returns undefined on ${platform}`, (t) => {
|
||||
t.is(darwinVersion(initAllState({ platform })), undefined);
|
||||
});
|
||||
}
|
||||
|
||||
test("darwinVersion returns raw string if semver parsing fails", (t) => {
|
||||
const invalidSemVer = "sealOS-2026";
|
||||
t.is(
|
||||
darwinVersion(
|
||||
initAllState({ platform: "darwin", osRelease: invalidSemVer }),
|
||||
),
|
||||
invalidSemVer,
|
||||
);
|
||||
});
|
||||
|
||||
test("darwinVersion returns semver if parsing succeeds", (t) => {
|
||||
const validSemVer = "27.0.1";
|
||||
|
||||
const version = darwinVersion(
|
||||
initAllState({ platform: "darwin", osRelease: validSemVer }),
|
||||
);
|
||||
|
||||
// Check that `version` is not undefined and narrow the type; throws if undefined.
|
||||
if (t.truthy(version)) {
|
||||
// Check that it's also not just a string.
|
||||
t.not(typeof version, "string");
|
||||
|
||||
// Should be an object with the expected properties.
|
||||
t.is(typeof version, "object");
|
||||
t.is(version["major"], 27);
|
||||
t.is(version["minor"], 0);
|
||||
t.is(version["patch"], 1);
|
||||
}
|
||||
});
|
||||
|
||||
test.serial("xcodeVersion returns undefined if symlink doesn't exist", (t) => {
|
||||
const logger = new RecordingLogger();
|
||||
|
||||
const lstatSync = sinon.stub(fs, "lstatSync").returns(undefined);
|
||||
|
||||
t.is(xcodeVersion(logger), undefined);
|
||||
t.is(lstatSync.callCount, 1);
|
||||
t.deepEqual(lstatSync.args[0], [
|
||||
XCODE_SELECT_LINK_PATH,
|
||||
{ throwIfNoEntry: false },
|
||||
]);
|
||||
|
||||
checkExpectedLogMessages(t, logger.messages, [
|
||||
"Xcode is probably not installed.",
|
||||
]);
|
||||
});
|
||||
|
||||
test.serial("xcodeVersion returns undefined if lstatSync throws", (t) => {
|
||||
const logger = new RecordingLogger();
|
||||
|
||||
const lstatSync = sinon.stub(fs, "lstatSync").throws(new Error("ENOENT"));
|
||||
|
||||
t.is(xcodeVersion(logger), undefined);
|
||||
t.is(lstatSync.callCount, 1);
|
||||
t.deepEqual(lstatSync.args[0], [
|
||||
XCODE_SELECT_LINK_PATH,
|
||||
{ throwIfNoEntry: false },
|
||||
]);
|
||||
|
||||
checkExpectedLogMessages(t, logger.messages, [
|
||||
"Unable to determine Xcode version: ENOENT",
|
||||
]);
|
||||
});
|
||||
|
||||
test.serial("xcodeVersion returns undefined if file is not a symlink", (t) => {
|
||||
const logger = new RecordingLogger();
|
||||
|
||||
const lstatSync = sinon
|
||||
.stub(fs, "lstatSync")
|
||||
.returns({ isSymbolicLink: () => false } as fs.Stats);
|
||||
|
||||
t.is(xcodeVersion(logger), undefined);
|
||||
t.is(lstatSync.callCount, 1);
|
||||
t.deepEqual(lstatSync.args[0], [
|
||||
XCODE_SELECT_LINK_PATH,
|
||||
{ throwIfNoEntry: false },
|
||||
]);
|
||||
|
||||
checkExpectedLogMessages(t, logger.messages, [
|
||||
"exists, but is not a symbolic link",
|
||||
]);
|
||||
});
|
||||
|
||||
test.serial(
|
||||
"xcodeVersion returns undefined if resolving the symlink returns nothing",
|
||||
(t) => {
|
||||
const logger = new RecordingLogger();
|
||||
|
||||
const lstatSync = sinon
|
||||
.stub(fs, "lstatSync")
|
||||
.returns({ isSymbolicLink: () => true } as fs.Stats);
|
||||
const readlinkSync = sinon.stub(fs, "readlinkSync").returns("");
|
||||
|
||||
t.is(xcodeVersion(logger), undefined);
|
||||
t.is(lstatSync.callCount, 1);
|
||||
t.deepEqual(lstatSync.args[0], [
|
||||
XCODE_SELECT_LINK_PATH,
|
||||
{ throwIfNoEntry: false },
|
||||
]);
|
||||
t.is(readlinkSync.callCount, 1);
|
||||
t.deepEqual(readlinkSync.args[0], [XCODE_SELECT_LINK_PATH]);
|
||||
|
||||
checkExpectedLogMessages(t, logger.messages, [
|
||||
"unexpectedly returned nothing",
|
||||
]);
|
||||
},
|
||||
);
|
||||
|
||||
test.serial(
|
||||
"xcodeVersion returns undefined if resolved path doesn't include pattern",
|
||||
(t) => {
|
||||
const logger = new RecordingLogger();
|
||||
|
||||
const lstatSync = sinon
|
||||
.stub(fs, "lstatSync")
|
||||
.returns({ isSymbolicLink: () => true } as fs.Stats);
|
||||
const readlinkSync = sinon
|
||||
.stub(fs, "readlinkSync")
|
||||
.returns("/Applications/Xcode.app/Contents/Developer");
|
||||
|
||||
t.is(xcodeVersion(logger), undefined);
|
||||
t.is(lstatSync.callCount, 1);
|
||||
t.deepEqual(lstatSync.args[0], [
|
||||
XCODE_SELECT_LINK_PATH,
|
||||
{ throwIfNoEntry: false },
|
||||
]);
|
||||
t.is(readlinkSync.callCount, 1);
|
||||
t.deepEqual(readlinkSync.args[0], [XCODE_SELECT_LINK_PATH]);
|
||||
|
||||
checkExpectedLogMessages(t, logger.messages, [
|
||||
"does not contain expected pattern",
|
||||
]);
|
||||
},
|
||||
);
|
||||
|
||||
test.serial("xcodeVersion returns undefined if match can't be parsed", (t) => {
|
||||
const logger = new RecordingLogger();
|
||||
|
||||
const lstatSync = sinon
|
||||
.stub(fs, "lstatSync")
|
||||
.returns({ isSymbolicLink: () => true } as fs.Stats);
|
||||
const readlinkSync = sinon
|
||||
.stub(fs, "readlinkSync")
|
||||
.returns("/Applications/Xcode_00.0.app/Contents/Developer");
|
||||
|
||||
t.is(xcodeVersion(logger), undefined);
|
||||
t.is(lstatSync.callCount, 1);
|
||||
t.deepEqual(lstatSync.args[0], [
|
||||
XCODE_SELECT_LINK_PATH,
|
||||
{ throwIfNoEntry: false },
|
||||
]);
|
||||
t.is(readlinkSync.callCount, 1);
|
||||
t.deepEqual(readlinkSync.args[0], [XCODE_SELECT_LINK_PATH]);
|
||||
|
||||
checkExpectedLogMessages(t, logger.messages, [
|
||||
"Couldn't parse '00.0' as a semantic version.",
|
||||
]);
|
||||
});
|
||||
|
||||
test.serial("xcodeVersion returns version from resolved path", (t) => {
|
||||
const logger = new RecordingLogger();
|
||||
|
||||
const lstatSync = sinon
|
||||
.stub(fs, "lstatSync")
|
||||
.returns({ isSymbolicLink: () => true } as fs.Stats);
|
||||
const readlinkSync = sinon
|
||||
.stub(fs, "readlinkSync")
|
||||
.returns("/Applications/Xcode_16.4.app/Contents/Developer");
|
||||
|
||||
const result = xcodeVersion(logger);
|
||||
|
||||
if (t.truthy(result)) {
|
||||
t.is(result.major, 16);
|
||||
t.is(result.minor, 4);
|
||||
}
|
||||
|
||||
t.is(lstatSync.callCount, 1);
|
||||
t.deepEqual(lstatSync.args[0], [
|
||||
XCODE_SELECT_LINK_PATH,
|
||||
{ throwIfNoEntry: false },
|
||||
]);
|
||||
t.is(readlinkSync.callCount, 1);
|
||||
t.deepEqual(readlinkSync.args[0], [XCODE_SELECT_LINK_PATH]);
|
||||
});
|
||||
|
||||
test.serial("xcodeVersion returns major version from resolved path", (t) => {
|
||||
const logger = new RecordingLogger();
|
||||
|
||||
const lstatSync = sinon
|
||||
.stub(fs, "lstatSync")
|
||||
.returns({ isSymbolicLink: () => true } as fs.Stats);
|
||||
const readlinkSync = sinon
|
||||
.stub(fs, "readlinkSync")
|
||||
.returns("/Applications/Xcode_16.app/Contents/Developer");
|
||||
|
||||
const result = xcodeVersion(logger);
|
||||
|
||||
if (t.truthy(result)) {
|
||||
t.is(result.major, 16);
|
||||
t.is(result.minor, 0);
|
||||
}
|
||||
|
||||
t.is(lstatSync.callCount, 1);
|
||||
t.deepEqual(lstatSync.args[0], [
|
||||
XCODE_SELECT_LINK_PATH,
|
||||
{ throwIfNoEntry: false },
|
||||
]);
|
||||
t.is(readlinkSync.callCount, 1);
|
||||
t.deepEqual(readlinkSync.args[0], [XCODE_SELECT_LINK_PATH]);
|
||||
});
|
||||
|
||||
test.serial(
|
||||
"xcodeVersion allows more version components in resolved path",
|
||||
(t) => {
|
||||
const logger = new RecordingLogger();
|
||||
|
||||
const lstatSync = sinon
|
||||
.stub(fs, "lstatSync")
|
||||
.returns({ isSymbolicLink: () => true } as fs.Stats);
|
||||
const readlinkSync = sinon
|
||||
.stub(fs, "readlinkSync")
|
||||
.returns("/Applications/Xcode_16.5.9.app/Contents/Developer");
|
||||
|
||||
const result = xcodeVersion(logger);
|
||||
|
||||
if (t.truthy(result)) {
|
||||
t.is(result.major, 16);
|
||||
t.is(result.minor, 5);
|
||||
}
|
||||
|
||||
t.is(lstatSync.callCount, 1);
|
||||
t.deepEqual(lstatSync.args[0], [
|
||||
XCODE_SELECT_LINK_PATH,
|
||||
{ throwIfNoEntry: false },
|
||||
]);
|
||||
t.is(readlinkSync.callCount, 1);
|
||||
t.deepEqual(readlinkSync.args[0], [XCODE_SELECT_LINK_PATH]);
|
||||
},
|
||||
);
|
||||
+105
@@ -1,3 +1,10 @@
|
||||
import fs from "fs";
|
||||
|
||||
import * as semver from "semver";
|
||||
|
||||
import type { ActionState, Logger } from "./action-common";
|
||||
import { getErrorMessage } from "./util";
|
||||
|
||||
/** Platform identifiers used in CodeQL bundle asset names. */
|
||||
export enum BundlePlatform {
|
||||
Linux64 = "linux64",
|
||||
@@ -24,3 +31,101 @@ export function getBundlePlatform(
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to determine the version of the kernel on macOS. We approximate this based on the
|
||||
* Darwin kernel version so that we don't have to launch an external process.
|
||||
*
|
||||
* @returns
|
||||
* The version as either a semantic version object, the raw version string
|
||||
* if it is not a semantic version, or `undefined` if we are not on macOS.
|
||||
*/
|
||||
export function darwinVersion(
|
||||
action: ActionState<["Base"]>,
|
||||
): semver.SemVer | string | undefined {
|
||||
// Skip if we are not running on macOS.
|
||||
if (action.platform !== "darwin") {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// Try to parse the kernel version string.
|
||||
const version = semver.parse(action.osRelease);
|
||||
|
||||
if (version === null) {
|
||||
return action.osRelease;
|
||||
}
|
||||
|
||||
return version;
|
||||
}
|
||||
|
||||
/** The static path we check for a symbolic link to the (dynamic) Xcode location. */
|
||||
export const XCODE_SELECT_LINK_PATH = "/private/var/db/xcode_select_link";
|
||||
|
||||
/** The pattern we expect to find in the Xcode path. */
|
||||
export const XCODE_APP_FILENAME_PATTERN = new RegExp(
|
||||
/(?<filename>Xcode_(?<majorMinor>\d+(\.\d+)?).*\.app)/,
|
||||
);
|
||||
|
||||
/**
|
||||
* Tries to determine the version of Xcode that is installed.
|
||||
*
|
||||
* @param logger The logger to use.
|
||||
* @returns The Xcode version or `undefined` if it couldn't be determined.
|
||||
*/
|
||||
export function xcodeVersion(logger: Logger): semver.SemVer | undefined {
|
||||
try {
|
||||
// Stat the expected symbolic link to check that it exists and is a symbolic link.
|
||||
// The `readlinkSync` call below returns an empty string in either case and so
|
||||
// this check allows us to distinguish between the two cases.
|
||||
const stats = fs.lstatSync(XCODE_SELECT_LINK_PATH, {
|
||||
throwIfNoEntry: false,
|
||||
});
|
||||
|
||||
if (stats === undefined) {
|
||||
logger.debug(
|
||||
`'${XCODE_SELECT_LINK_PATH}' does not exist. Xcode is probably not installed.`,
|
||||
);
|
||||
return undefined;
|
||||
}
|
||||
if (!stats.isSymbolicLink()) {
|
||||
logger.warning(
|
||||
`${XCODE_SELECT_LINK_PATH} exists, but is not a symbolic link.`,
|
||||
);
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// Read what the symbolic link points to.
|
||||
const xcodePath = fs.readlinkSync(XCODE_SELECT_LINK_PATH);
|
||||
|
||||
if (xcodePath === "") {
|
||||
logger.warning(
|
||||
`Resolving ${XCODE_SELECT_LINK_PATH} unexpectedly returned nothing.`,
|
||||
);
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// Try to extract the version from the path.
|
||||
const matchResult = xcodePath.match(XCODE_APP_FILENAME_PATTERN);
|
||||
|
||||
if (matchResult?.groups === undefined) {
|
||||
logger.warning(
|
||||
`Xcode path '${xcodePath}' does not contain expected pattern.`,
|
||||
);
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const majorMinor = matchResult.groups["majorMinor"];
|
||||
const version = semver.coerce(majorMinor);
|
||||
|
||||
if (version === null) {
|
||||
logger.warning(`Couldn't parse '${majorMinor}' as a semantic version.`);
|
||||
return undefined;
|
||||
}
|
||||
return version;
|
||||
} catch (err) {
|
||||
logger.warning(
|
||||
`Unable to determine Xcode version: ${getErrorMessage(err)}`,
|
||||
);
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
import { TextDecoder } from "node:util";
|
||||
import * as os from "os";
|
||||
import path from "path";
|
||||
|
||||
import * as github from "@actions/github";
|
||||
@@ -34,6 +35,7 @@ import { joinMessageStrings, Loggable, LoggableError, Logger } from "./logging";
|
||||
import { OverlayDatabaseMode } from "./overlay/overlay-database-mode";
|
||||
import { getBundlePlatform } from "./platform";
|
||||
import { ActionName } from "./status-report";
|
||||
import { ToolsFeature } from "./tools-features";
|
||||
import {
|
||||
DEFAULT_DEBUG_ARTIFACT_NAME,
|
||||
DEFAULT_DEBUG_DATABASE_NAME,
|
||||
@@ -272,6 +274,7 @@ export function initAllState(
|
||||
startedAt: new Date(),
|
||||
platform: process.platform,
|
||||
arch: process.arch,
|
||||
osRelease: os.release(),
|
||||
logger: new RecordingLogger(),
|
||||
env,
|
||||
actions: getTestActionsEnv(env),
|
||||
@@ -911,7 +914,7 @@ export function mockLanguagesInRepo(languages: string[]) {
|
||||
*/
|
||||
export const makeVersionInfo = (
|
||||
version: string,
|
||||
features?: { [name: string]: boolean },
|
||||
features?: { [key in ToolsFeature]?: boolean },
|
||||
overlayVersion?: number,
|
||||
): VersionInfo => ({
|
||||
version,
|
||||
|
||||
@@ -6,6 +6,7 @@ export enum ToolsFeature {
|
||||
BundleSupportsOverlay = "bundleSupportsOverlay",
|
||||
IndirectTracingSupportsStaticBinaries = "indirectTracingSupportsStaticBinaries",
|
||||
SuppressesMissingFileBaselineWarning = "suppressesMissingFileBaselineWarning",
|
||||
SwiftSupportsAllPlatforms = "swiftSupportsAllPlatforms",
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in new issue
Block a user