mirror of
https://github.com/github/codeql-action.git
synced 2026-08-06 13:13:45 -05:00
Compare commits
18 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c719ec0b33 | |||
| 09bfd560f6 | |||
| 33b2045510 | |||
| 93c6b70dc3 | |||
| def4f60c6c | |||
| 34d91a9ce7 | |||
| c49c05b5df | |||
| 2ccaddd459 | |||
| 5dcca8a6e4 | |||
| b6e17a6616 | |||
| e9e73b0cb9 | |||
| bab5a146ac | |||
| 6013661451 | |||
| 26df9a9a4f | |||
| 4ee97e5e55 | |||
| cfce1c4e19 | |||
| da75623c67 | |||
| c29fca48a1 |
@@ -42,6 +42,10 @@ jobs:
|
|||||||
uses: ./.github/prepare-test
|
uses: ./.github/prepare-test
|
||||||
with:
|
with:
|
||||||
version: ${{ matrix.version }}
|
version: ${{ matrix.version }}
|
||||||
|
- uses: swift-actions/setup-swift@5cdaa9161ad1f55ae39a5ea1784ef96de72f95d9
|
||||||
|
if: runner.os != 'Windows'
|
||||||
|
with:
|
||||||
|
swift-version: '5.7'
|
||||||
- uses: ./../action/init
|
- uses: ./../action/init
|
||||||
with:
|
with:
|
||||||
languages: javascript
|
languages: javascript
|
||||||
|
|||||||
+2
-3
@@ -87,8 +87,7 @@ jobs:
|
|||||||
- name: Check sarif
|
- name: Check sarif
|
||||||
uses: ./../action/.github/check-sarif
|
uses: ./../action/.github/check-sarif
|
||||||
# Running on Windows requires CodeQL CLI 2.9.0+.
|
# Running on Windows requires CodeQL CLI 2.9.0+.
|
||||||
if: "!(matrix.version == 'stable-20220120' && (matrix.os == 'windows-latest'\
|
if: "!(matrix.version == 'stable-20220120' && runner.os == 'Windows')"
|
||||||
\ || matrix.os == 'windows-2019'))"
|
|
||||||
with:
|
with:
|
||||||
sarif-file: ${{ runner.temp }}/results/javascript.sarif
|
sarif-file: ${{ runner.temp }}/results/javascript.sarif
|
||||||
queries-run: js/ml-powered/nosql-injection,js/ml-powered/path-injection,js/ml-powered/sql-injection,js/ml-powered/xss
|
queries-run: js/ml-powered/nosql-injection,js/ml-powered/path-injection,js/ml-powered/sql-injection,js/ml-powered/xss
|
||||||
@@ -98,7 +97,7 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
# Running on Windows requires CodeQL CLI 2.9.0+.
|
# Running on Windows requires CodeQL CLI 2.9.0+.
|
||||||
SHOULD_RUN_ML_POWERED_QUERIES: ${{ !(matrix.version == 'stable-20220120' &&
|
SHOULD_RUN_ML_POWERED_QUERIES: ${{ !(matrix.version == 'stable-20220120' &&
|
||||||
(matrix.os == 'windows-latest' || matrix.os == 'windows-2019')) }}
|
runner.os == 'Windows') }}
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
echo "Expecting ML-powered queries to be run: ${SHOULD_RUN_ML_POWERED_QUERIES}"
|
echo "Expecting ML-powered queries to be run: ${SHOULD_RUN_ML_POWERED_QUERIES}"
|
||||||
|
|||||||
+33
-1
@@ -65,16 +65,25 @@ jobs:
|
|||||||
uses: actions/setup-go@v3
|
uses: actions/setup-go@v3
|
||||||
with:
|
with:
|
||||||
go-version: ^1.13.1
|
go-version: ^1.13.1
|
||||||
|
- uses: swift-actions/setup-swift@5cdaa9161ad1f55ae39a5ea1784ef96de72f95d9
|
||||||
|
if: runner.os != 'Windows'
|
||||||
|
with:
|
||||||
|
swift-version: '5.7'
|
||||||
|
|
||||||
- uses: ./../action/init
|
- uses: ./../action/init
|
||||||
with:
|
with:
|
||||||
db-location: ${{ runner.temp }}/customDbLocation
|
db-location: ${{ runner.temp }}/customDbLocation
|
||||||
tools: ${{ steps.prepare-test.outputs.tools-url }}
|
tools: ${{ steps.prepare-test.outputs.tools-url }}
|
||||||
|
|
||||||
- name: Build code
|
- name: Build code
|
||||||
shell: bash
|
shell: bash
|
||||||
run: ./build.sh
|
run: ./build.sh
|
||||||
|
|
||||||
- uses: ./../action/analyze
|
- uses: ./../action/analyze
|
||||||
id: analysis
|
id: analysis
|
||||||
- shell: bash
|
|
||||||
|
- name: Check language autodetect for all languages excluding Ruby, Swift
|
||||||
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
CPP_DB=${{ fromJson(steps.analysis.outputs.db-locations).cpp }}
|
CPP_DB=${{ fromJson(steps.analysis.outputs.db-locations).cpp }}
|
||||||
if [[ ! -d $CPP_DB ]] || [[ ! $CPP_DB == ${{ runner.temp }}/customDbLocation/* ]]; then
|
if [[ ! -d $CPP_DB ]] || [[ ! $CPP_DB == ${{ runner.temp }}/customDbLocation/* ]]; then
|
||||||
@@ -106,5 +115,28 @@ jobs:
|
|||||||
echo "Did not create a database for Python, or created it in the wrong location."
|
echo "Did not create a database for Python, or created it in the wrong location."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
- name: Check language autodetect for Ruby
|
||||||
|
if: (matrix.version == 'cached' || matrix.version == 'latest' || matrix.version
|
||||||
|
== 'nightly-latest')
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
RUBY_DB=${{ fromJson(steps.analysis.outputs.db-locations).ruby }}
|
||||||
|
if [[ ! -d $RUBY_DB ]] || [[ ! $RUBY_DB == ${{ runner.temp }}/customDbLocation/* ]]; then
|
||||||
|
echo "Did not create a database for Ruby, or created it in the wrong location."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Check language autodetect for Swift
|
||||||
|
if: "!startsWith(matrix.os, 'windows') && (matrix.version == 'cached' || matrix.version\
|
||||||
|
\ == 'latest' || matrix.version == 'nightly-latest')"
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
SWIFT_DB=${{ fromJson(steps.analysis.outputs.db-locations).swift }}
|
||||||
|
if [[ ! -d $SWIFT_DB ]] || [[ ! $SWIFT_DB == ${{ runner.temp }}/customDbLocation/* ]]; then
|
||||||
|
echo "Did not create a database for Swift, or created it in the wrong location."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
env:
|
env:
|
||||||
|
CODEQL_ENABLE_EXPERIMENTAL_FEATURES_SWIFT: 'true' # Remove when Swift is GA.
|
||||||
CODEQL_ACTION_TEST_MODE: true
|
CODEQL_ACTION_TEST_MODE: true
|
||||||
|
|||||||
Generated
-66
@@ -1,66 +0,0 @@
|
|||||||
# Warning: This file is generated automatically, and should not be modified.
|
|
||||||
# Instead, please modify the template in the pr-checks directory and run:
|
|
||||||
# pip install ruamel.yaml && python3 sync.py
|
|
||||||
# to regenerate this file.
|
|
||||||
|
|
||||||
name: PR Check - Ruby analysis using autodetect
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
GO111MODULE: auto
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
- releases/v1
|
|
||||||
- releases/v2
|
|
||||||
pull_request:
|
|
||||||
types:
|
|
||||||
- opened
|
|
||||||
- synchronize
|
|
||||||
- reopened
|
|
||||||
- ready_for_review
|
|
||||||
workflow_dispatch: {}
|
|
||||||
jobs:
|
|
||||||
ruby-autodetect:
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
include:
|
|
||||||
- os: ubuntu-latest
|
|
||||||
version: latest
|
|
||||||
- os: macos-latest
|
|
||||||
version: latest
|
|
||||||
- os: ubuntu-latest
|
|
||||||
version: cached
|
|
||||||
- os: macos-latest
|
|
||||||
version: cached
|
|
||||||
- os: ubuntu-latest
|
|
||||||
version: nightly-latest
|
|
||||||
- os: macos-latest
|
|
||||||
version: nightly-latest
|
|
||||||
name: Ruby analysis using autodetect
|
|
||||||
timeout-minutes: 45
|
|
||||||
runs-on: ${{ matrix.os }}
|
|
||||||
steps:
|
|
||||||
- name: Check out repository
|
|
||||||
uses: actions/checkout@v3
|
|
||||||
- name: Prepare test
|
|
||||||
id: prepare-test
|
|
||||||
uses: ./.github/prepare-test
|
|
||||||
with:
|
|
||||||
version: ${{ matrix.version }}
|
|
||||||
- uses: ./../action/init
|
|
||||||
with:
|
|
||||||
tools: ${{ steps.prepare-test.outputs.tools-url }}
|
|
||||||
- uses: ./../action/analyze
|
|
||||||
id: analysis
|
|
||||||
- name: Check database
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
RUBY_DB="${{ fromJson(steps.analysis.outputs.db-locations).ruby }}"
|
|
||||||
if [[ ! -d "$RUBY_DB" ]]; then
|
|
||||||
echo "Did not create a database for Ruby."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
env:
|
|
||||||
CODEQL_ENABLE_EXPERIMENTAL_FEATURES: 'true'
|
|
||||||
CODEQL_ACTION_TEST_MODE: true
|
|
||||||
Generated
-1
@@ -63,5 +63,4 @@ jobs:
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
env:
|
env:
|
||||||
CODEQL_ENABLE_EXPERIMENTAL_FEATURES: 'true'
|
|
||||||
CODEQL_ACTION_TEST_MODE: true
|
CODEQL_ACTION_TEST_MODE: true
|
||||||
|
|||||||
Generated
+3
@@ -42,6 +42,9 @@ jobs:
|
|||||||
uses: ./.github/prepare-test
|
uses: ./.github/prepare-test
|
||||||
with:
|
with:
|
||||||
version: ${{ matrix.version }}
|
version: ${{ matrix.version }}
|
||||||
|
- uses: swift-actions/setup-swift@5cdaa9161ad1f55ae39a5ea1784ef96de72f95d9
|
||||||
|
with:
|
||||||
|
swift-version: '5.7'
|
||||||
- uses: ./../action/init
|
- uses: ./../action/init
|
||||||
with:
|
with:
|
||||||
languages: swift
|
languages: swift
|
||||||
|
|||||||
+3
@@ -48,6 +48,9 @@ jobs:
|
|||||||
uses: ./.github/prepare-test
|
uses: ./.github/prepare-test
|
||||||
with:
|
with:
|
||||||
version: ${{ matrix.version }}
|
version: ${{ matrix.version }}
|
||||||
|
- uses: swift-actions/setup-swift@5cdaa9161ad1f55ae39a5ea1784ef96de72f95d9
|
||||||
|
with:
|
||||||
|
swift-version: '5.7'
|
||||||
- uses: ./../action/init
|
- uses: ./../action/init
|
||||||
with:
|
with:
|
||||||
languages: swift
|
languages: swift
|
||||||
|
|||||||
+1
-1
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
## [UNRELEASED]
|
## [UNRELEASED]
|
||||||
|
|
||||||
No user facing changes.
|
- Fixed a bug where some the `init` action and the `analyze` action would have different sets of experimental feature flags enabled. [#1384](https://github.com/github/codeql-action/pull/1384)
|
||||||
|
|
||||||
## 2.1.33 - 16 Nov 2022
|
## 2.1.33 - 16 Nov 2022
|
||||||
|
|
||||||
|
|||||||
Generated
+1
-1
@@ -155,7 +155,7 @@ async function run() {
|
|||||||
const memory = util.getMemoryFlag(actionsUtil.getOptionalInput("ram") || process.env["CODEQL_RAM"]);
|
const memory = util.getMemoryFlag(actionsUtil.getOptionalInput("ram") || process.env["CODEQL_RAM"]);
|
||||||
const repositoryNwo = (0, repository_1.parseRepositoryNwo)(util.getRequiredEnvParam("GITHUB_REPOSITORY"));
|
const repositoryNwo = (0, repository_1.parseRepositoryNwo)(util.getRequiredEnvParam("GITHUB_REPOSITORY"));
|
||||||
const gitHubVersion = await (0, api_client_1.getGitHubVersion)();
|
const gitHubVersion = await (0, api_client_1.getGitHubVersion)();
|
||||||
const features = new feature_flags_1.Features(gitHubVersion, repositoryNwo, logger);
|
const features = new feature_flags_1.Features(gitHubVersion, repositoryNwo, actionsUtil.getTemporaryDirectory(), logger);
|
||||||
await runAutobuildIfLegacyGoWorkflow(config, logger);
|
await runAutobuildIfLegacyGoWorkflow(config, logger);
|
||||||
dbCreationTimings = await (0, analyze_1.runFinalize)(outputDir, threads, memory, config, logger);
|
dbCreationTimings = await (0, analyze_1.runFinalize)(outputDir, threads, memory, config, logger);
|
||||||
if (actionsUtil.getRequiredInput("skip-queries") !== "true") {
|
if (actionsUtil.getRequiredInput("skip-queries") !== "true") {
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
|
|||||||
{ "maximumVersion": "3.7", "minimumVersion": "3.3" }
|
{ "maximumVersion": "3.8", "minimumVersion": "3.3" }
|
||||||
|
|||||||
Generated
+51
-9
@@ -19,7 +19,9 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
exports.Features = exports.featureConfig = exports.Feature = void 0;
|
exports.Features = exports.FEATURE_FLAGS_FILE_NAME = exports.featureConfig = exports.Feature = void 0;
|
||||||
|
const fs = __importStar(require("fs"));
|
||||||
|
const path = __importStar(require("path"));
|
||||||
const api_client_1 = require("./api-client");
|
const api_client_1 = require("./api-client");
|
||||||
const util = __importStar(require("./util"));
|
const util = __importStar(require("./util"));
|
||||||
var Feature;
|
var Feature;
|
||||||
@@ -57,14 +59,15 @@ exports.featureConfig = {
|
|||||||
minimumVersion: undefined,
|
minimumVersion: undefined,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
exports.FEATURE_FLAGS_FILE_NAME = "cached-feature-flags.json";
|
||||||
/**
|
/**
|
||||||
* Determines the enablement status of a number of features.
|
* Determines the enablement status of a number of features.
|
||||||
* If feature enablement is not able to be determined locally, a request to the
|
* If feature enablement is not able to be determined locally, a request to the
|
||||||
* GitHub API is made to determine the enablement status.
|
* GitHub API is made to determine the enablement status.
|
||||||
*/
|
*/
|
||||||
class Features {
|
class Features {
|
||||||
constructor(gitHubVersion, repositoryNwo, logger) {
|
constructor(gitHubVersion, repositoryNwo, tempDir, logger) {
|
||||||
this.gitHubFeatureFlags = new GitHubFeatureFlags(gitHubVersion, repositoryNwo, logger);
|
this.gitHubFeatureFlags = new GitHubFeatureFlags(gitHubVersion, repositoryNwo, path.join(tempDir, exports.FEATURE_FLAGS_FILE_NAME), logger);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@@ -108,14 +111,15 @@ class Features {
|
|||||||
}
|
}
|
||||||
exports.Features = Features;
|
exports.Features = Features;
|
||||||
class GitHubFeatureFlags {
|
class GitHubFeatureFlags {
|
||||||
constructor(gitHubVersion, repositoryNwo, logger) {
|
constructor(gitHubVersion, repositoryNwo, featureFlagsFile, logger) {
|
||||||
this.gitHubVersion = gitHubVersion;
|
this.gitHubVersion = gitHubVersion;
|
||||||
this.repositoryNwo = repositoryNwo;
|
this.repositoryNwo = repositoryNwo;
|
||||||
|
this.featureFlagsFile = featureFlagsFile;
|
||||||
this.logger = logger;
|
this.logger = logger;
|
||||||
/**/
|
/**/
|
||||||
}
|
}
|
||||||
async getValue(feature) {
|
async getValue(feature) {
|
||||||
const response = await this.getApiResponse();
|
const response = await this.getAllFeatures();
|
||||||
if (response === undefined) {
|
if (response === undefined) {
|
||||||
this.logger.debug(`No feature flags API response for ${feature}, considering it disabled.`);
|
this.logger.debug(`No feature flags API response for ${feature}, considering it disabled.`);
|
||||||
return false;
|
return false;
|
||||||
@@ -127,10 +131,48 @@ class GitHubFeatureFlags {
|
|||||||
}
|
}
|
||||||
return !!featureEnablement;
|
return !!featureEnablement;
|
||||||
}
|
}
|
||||||
async getApiResponse() {
|
async getAllFeatures() {
|
||||||
const apiResponse = this.cachedApiResponse || (await this.loadApiResponse());
|
// if we have an in memory cache, use that
|
||||||
this.cachedApiResponse = apiResponse;
|
if (this.cachedApiResponse !== undefined) {
|
||||||
return apiResponse;
|
return this.cachedApiResponse;
|
||||||
|
}
|
||||||
|
// if a previous step has written a feature flags file to disk, use that
|
||||||
|
const fileFlags = await this.readLocalFlags();
|
||||||
|
if (fileFlags !== undefined) {
|
||||||
|
this.cachedApiResponse = fileFlags;
|
||||||
|
return fileFlags;
|
||||||
|
}
|
||||||
|
// if not, request flags from the server
|
||||||
|
let remoteFlags = await this.loadApiResponse();
|
||||||
|
if (remoteFlags === undefined) {
|
||||||
|
remoteFlags = {};
|
||||||
|
}
|
||||||
|
// cache the response in memory
|
||||||
|
this.cachedApiResponse = remoteFlags;
|
||||||
|
// and cache them to disk so future workflow steps can use them
|
||||||
|
await this.writeLocalFlags(remoteFlags);
|
||||||
|
return remoteFlags;
|
||||||
|
}
|
||||||
|
async readLocalFlags() {
|
||||||
|
try {
|
||||||
|
if (fs.existsSync(this.featureFlagsFile)) {
|
||||||
|
this.logger.debug(`Loading feature flags from ${this.featureFlagsFile}`);
|
||||||
|
return JSON.parse(fs.readFileSync(this.featureFlagsFile, "utf8"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
this.logger.warning(`Error reading cached feature flags file ${this.featureFlagsFile}: ${e}. Requesting from GitHub instead.`);
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
async writeLocalFlags(flags) {
|
||||||
|
try {
|
||||||
|
this.logger.debug(`Writing feature flags to ${this.featureFlagsFile}`);
|
||||||
|
fs.writeFileSync(this.featureFlagsFile, JSON.stringify(flags));
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
this.logger.warning(`Error writing cached feature flags file ${this.featureFlagsFile}: ${e}.`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
async loadApiResponse() {
|
async loadApiResponse() {
|
||||||
// Do nothing when not running against github.com
|
// Do nothing when not running against github.com
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
{"version":3,"file":"feature-flags.js","sourceRoot":"","sources":["../src/feature-flags.ts"],"names":[],"mappings":"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"}
|
{"version":3,"file":"feature-flags.js","sourceRoot":"","sources":["../src/feature-flags.ts"],"names":[],"mappings":"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"}
|
||||||
Generated
+63
-11
@@ -1,8 +1,29 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||||
|
if (k2 === undefined) k2 = k;
|
||||||
|
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
||||||
|
}) : (function(o, m, k, k2) {
|
||||||
|
if (k2 === undefined) k2 = k;
|
||||||
|
o[k2] = m[k];
|
||||||
|
}));
|
||||||
|
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
||||||
|
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
||||||
|
}) : function(o, v) {
|
||||||
|
o["default"] = v;
|
||||||
|
});
|
||||||
|
var __importStar = (this && this.__importStar) || function (mod) {
|
||||||
|
if (mod && mod.__esModule) return mod;
|
||||||
|
var result = {};
|
||||||
|
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
||||||
|
__setModuleDefault(result, mod);
|
||||||
|
return result;
|
||||||
|
};
|
||||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||||
};
|
};
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
const fs = __importStar(require("fs"));
|
||||||
|
const path = __importStar(require("path"));
|
||||||
const ava_1 = __importDefault(require("ava"));
|
const ava_1 = __importDefault(require("ava"));
|
||||||
const feature_flags_1 = require("./feature-flags");
|
const feature_flags_1 = require("./feature-flags");
|
||||||
const logging_1 = require("./logging");
|
const logging_1 = require("./logging");
|
||||||
@@ -25,7 +46,7 @@ for (const variant of ALL_FEATURES_DISABLED_VARIANTS) {
|
|||||||
(0, ava_1.default)(`All features are disabled if running against ${variant.description}`, async (t) => {
|
(0, ava_1.default)(`All features are disabled if running against ${variant.description}`, async (t) => {
|
||||||
await (0, util_1.withTmpDir)(async (tmpDir) => {
|
await (0, util_1.withTmpDir)(async (tmpDir) => {
|
||||||
const loggedMessages = [];
|
const loggedMessages = [];
|
||||||
const featureEnablement = setUpTests(tmpDir, (0, testing_utils_1.getRecordingLogger)(loggedMessages), variant.gitHubVersion);
|
const featureEnablement = setUpFeatureFlagTests(tmpDir, (0, testing_utils_1.getRecordingLogger)(loggedMessages), variant.gitHubVersion);
|
||||||
for (const feature of Object.values(feature_flags_1.Feature)) {
|
for (const feature of Object.values(feature_flags_1.Feature)) {
|
||||||
t.false(await featureEnablement.getValue(feature, includeCodeQlIfRequired(feature)));
|
t.false(await featureEnablement.getValue(feature, includeCodeQlIfRequired(feature)));
|
||||||
}
|
}
|
||||||
@@ -38,7 +59,7 @@ for (const variant of ALL_FEATURES_DISABLED_VARIANTS) {
|
|||||||
(0, ava_1.default)("API response missing", async (t) => {
|
(0, ava_1.default)("API response missing", async (t) => {
|
||||||
await (0, util_1.withTmpDir)(async (tmpDir) => {
|
await (0, util_1.withTmpDir)(async (tmpDir) => {
|
||||||
const loggedMessages = [];
|
const loggedMessages = [];
|
||||||
const featureEnablement = setUpTests(tmpDir, (0, testing_utils_1.getRecordingLogger)(loggedMessages));
|
const featureEnablement = setUpFeatureFlagTests(tmpDir, (0, testing_utils_1.getRecordingLogger)(loggedMessages));
|
||||||
(0, testing_utils_1.mockFeatureFlagApiEndpoint)(403, {});
|
(0, testing_utils_1.mockFeatureFlagApiEndpoint)(403, {});
|
||||||
for (const feature of Object.values(feature_flags_1.Feature)) {
|
for (const feature of Object.values(feature_flags_1.Feature)) {
|
||||||
t.assert((await featureEnablement.getValue(feature, includeCodeQlIfRequired(feature))) === false);
|
t.assert((await featureEnablement.getValue(feature, includeCodeQlIfRequired(feature))) === false);
|
||||||
@@ -49,7 +70,7 @@ for (const variant of ALL_FEATURES_DISABLED_VARIANTS) {
|
|||||||
(0, ava_1.default)("Features are disabled if they're not returned in API response", async (t) => {
|
(0, ava_1.default)("Features are disabled if they're not returned in API response", async (t) => {
|
||||||
await (0, util_1.withTmpDir)(async (tmpDir) => {
|
await (0, util_1.withTmpDir)(async (tmpDir) => {
|
||||||
const loggedMessages = [];
|
const loggedMessages = [];
|
||||||
const featureEnablement = setUpTests(tmpDir, (0, testing_utils_1.getRecordingLogger)(loggedMessages));
|
const featureEnablement = setUpFeatureFlagTests(tmpDir, (0, testing_utils_1.getRecordingLogger)(loggedMessages));
|
||||||
(0, testing_utils_1.mockFeatureFlagApiEndpoint)(200, {});
|
(0, testing_utils_1.mockFeatureFlagApiEndpoint)(200, {});
|
||||||
for (const feature of Object.values(feature_flags_1.Feature)) {
|
for (const feature of Object.values(feature_flags_1.Feature)) {
|
||||||
t.assert((await featureEnablement.getValue(feature, includeCodeQlIfRequired(feature))) === false);
|
t.assert((await featureEnablement.getValue(feature, includeCodeQlIfRequired(feature))) === false);
|
||||||
@@ -59,7 +80,7 @@ for (const variant of ALL_FEATURES_DISABLED_VARIANTS) {
|
|||||||
});
|
});
|
||||||
(0, ava_1.default)("Feature flags exception is propagated if the API request errors", async (t) => {
|
(0, ava_1.default)("Feature flags exception is propagated if the API request errors", async (t) => {
|
||||||
await (0, util_1.withTmpDir)(async (tmpDir) => {
|
await (0, util_1.withTmpDir)(async (tmpDir) => {
|
||||||
const featureEnablement = setUpTests(tmpDir);
|
const featureEnablement = setUpFeatureFlagTests(tmpDir);
|
||||||
(0, testing_utils_1.mockFeatureFlagApiEndpoint)(500, {});
|
(0, testing_utils_1.mockFeatureFlagApiEndpoint)(500, {});
|
||||||
await t.throwsAsync(async () => featureEnablement.getValue(feature_flags_1.Feature.MlPoweredQueriesEnabled, includeCodeQlIfRequired(feature_flags_1.Feature.MlPoweredQueriesEnabled)), {
|
await t.throwsAsync(async () => featureEnablement.getValue(feature_flags_1.Feature.MlPoweredQueriesEnabled, includeCodeQlIfRequired(feature_flags_1.Feature.MlPoweredQueriesEnabled)), {
|
||||||
message: "Encountered an error while trying to determine feature enablement: Error: some error message",
|
message: "Encountered an error while trying to determine feature enablement: Error: some error message",
|
||||||
@@ -69,7 +90,7 @@ for (const variant of ALL_FEATURES_DISABLED_VARIANTS) {
|
|||||||
for (const feature of Object.keys(feature_flags_1.featureConfig)) {
|
for (const feature of Object.keys(feature_flags_1.featureConfig)) {
|
||||||
(0, ava_1.default)(`Only feature '${feature}' is enabled if enabled in the API response. Other features disabled`, async (t) => {
|
(0, ava_1.default)(`Only feature '${feature}' is enabled if enabled in the API response. Other features disabled`, async (t) => {
|
||||||
await (0, util_1.withTmpDir)(async (tmpDir) => {
|
await (0, util_1.withTmpDir)(async (tmpDir) => {
|
||||||
const featureEnablement = setUpTests(tmpDir);
|
const featureEnablement = setUpFeatureFlagTests(tmpDir);
|
||||||
// set all features to false except the one we're testing
|
// set all features to false except the one we're testing
|
||||||
const expectedFeatureEnablement = {};
|
const expectedFeatureEnablement = {};
|
||||||
for (const f of Object.keys(feature_flags_1.featureConfig)) {
|
for (const f of Object.keys(feature_flags_1.featureConfig)) {
|
||||||
@@ -87,7 +108,7 @@ for (const feature of Object.keys(feature_flags_1.featureConfig)) {
|
|||||||
});
|
});
|
||||||
(0, ava_1.default)(`Only feature '${feature}' is enabled if the associated environment variable is true. Others disabled.`, async (t) => {
|
(0, ava_1.default)(`Only feature '${feature}' is enabled if the associated environment variable is true. Others disabled.`, async (t) => {
|
||||||
await (0, util_1.withTmpDir)(async (tmpDir) => {
|
await (0, util_1.withTmpDir)(async (tmpDir) => {
|
||||||
const featureEnablement = setUpTests(tmpDir);
|
const featureEnablement = setUpFeatureFlagTests(tmpDir);
|
||||||
const expectedFeatureEnablement = initializeFeatures(false);
|
const expectedFeatureEnablement = initializeFeatures(false);
|
||||||
(0, testing_utils_1.mockFeatureFlagApiEndpoint)(200, expectedFeatureEnablement);
|
(0, testing_utils_1.mockFeatureFlagApiEndpoint)(200, expectedFeatureEnablement);
|
||||||
// feature should be disabled initially
|
// feature should be disabled initially
|
||||||
@@ -99,7 +120,7 @@ for (const feature of Object.keys(feature_flags_1.featureConfig)) {
|
|||||||
});
|
});
|
||||||
(0, ava_1.default)(`Feature '${feature}' is disabled if the associated environment variable is false, even if enabled in API`, async (t) => {
|
(0, ava_1.default)(`Feature '${feature}' is disabled if the associated environment variable is false, even if enabled in API`, async (t) => {
|
||||||
await (0, util_1.withTmpDir)(async (tmpDir) => {
|
await (0, util_1.withTmpDir)(async (tmpDir) => {
|
||||||
const featureEnablement = setUpTests(tmpDir);
|
const featureEnablement = setUpFeatureFlagTests(tmpDir);
|
||||||
const expectedFeatureEnablement = initializeFeatures(true);
|
const expectedFeatureEnablement = initializeFeatures(true);
|
||||||
(0, testing_utils_1.mockFeatureFlagApiEndpoint)(200, expectedFeatureEnablement);
|
(0, testing_utils_1.mockFeatureFlagApiEndpoint)(200, expectedFeatureEnablement);
|
||||||
// feature should be enabled initially
|
// feature should be enabled initially
|
||||||
@@ -112,7 +133,7 @@ for (const feature of Object.keys(feature_flags_1.featureConfig)) {
|
|||||||
if (feature_flags_1.featureConfig[feature].minimumVersion !== undefined) {
|
if (feature_flags_1.featureConfig[feature].minimumVersion !== undefined) {
|
||||||
(0, ava_1.default)(`Getting feature '${feature} should throw if no codeql is provided`, async (t) => {
|
(0, ava_1.default)(`Getting feature '${feature} should throw if no codeql is provided`, async (t) => {
|
||||||
await (0, util_1.withTmpDir)(async (tmpDir) => {
|
await (0, util_1.withTmpDir)(async (tmpDir) => {
|
||||||
const featureEnablement = setUpTests(tmpDir);
|
const featureEnablement = setUpFeatureFlagTests(tmpDir);
|
||||||
const expectedFeatureEnablement = initializeFeatures(true);
|
const expectedFeatureEnablement = initializeFeatures(true);
|
||||||
(0, testing_utils_1.mockFeatureFlagApiEndpoint)(200, expectedFeatureEnablement);
|
(0, testing_utils_1.mockFeatureFlagApiEndpoint)(200, expectedFeatureEnablement);
|
||||||
await t.throwsAsync(async () => featureEnablement.getValue(feature), {
|
await t.throwsAsync(async () => featureEnablement.getValue(feature), {
|
||||||
@@ -124,7 +145,7 @@ for (const feature of Object.keys(feature_flags_1.featureConfig)) {
|
|||||||
if (feature_flags_1.featureConfig[feature].minimumVersion !== undefined) {
|
if (feature_flags_1.featureConfig[feature].minimumVersion !== undefined) {
|
||||||
(0, ava_1.default)(`Feature '${feature}' is disabled if the minimum CLI version is below ${feature_flags_1.featureConfig[feature].minimumVersion}`, async (t) => {
|
(0, ava_1.default)(`Feature '${feature}' is disabled if the minimum CLI version is below ${feature_flags_1.featureConfig[feature].minimumVersion}`, async (t) => {
|
||||||
await (0, util_1.withTmpDir)(async (tmpDir) => {
|
await (0, util_1.withTmpDir)(async (tmpDir) => {
|
||||||
const featureEnablement = setUpTests(tmpDir);
|
const featureEnablement = setUpFeatureFlagTests(tmpDir);
|
||||||
const expectedFeatureEnablement = initializeFeatures(true);
|
const expectedFeatureEnablement = initializeFeatures(true);
|
||||||
(0, testing_utils_1.mockFeatureFlagApiEndpoint)(200, expectedFeatureEnablement);
|
(0, testing_utils_1.mockFeatureFlagApiEndpoint)(200, expectedFeatureEnablement);
|
||||||
// feature should be disabled when an old CLI version is set
|
// feature should be disabled when an old CLI version is set
|
||||||
@@ -156,6 +177,37 @@ for (const feature of Object.keys(feature_flags_1.featureConfig)) {
|
|||||||
// An even less likely scenario is that we no longer have any features.
|
// An even less likely scenario is that we no longer have any features.
|
||||||
t.assert(Object.values(feature_flags_1.featureConfig).length > 0, "There should be at least one feature");
|
t.assert(Object.values(feature_flags_1.featureConfig).length > 0, "There should be at least one feature");
|
||||||
});
|
});
|
||||||
|
(0, ava_1.default)("Feature flags are saved to disk", async (t) => {
|
||||||
|
await (0, util_1.withTmpDir)(async (tmpDir) => {
|
||||||
|
const featureEnablement = setUpFeatureFlagTests(tmpDir);
|
||||||
|
const expectedFeatureEnablement = initializeFeatures(true);
|
||||||
|
(0, testing_utils_1.mockFeatureFlagApiEndpoint)(200, expectedFeatureEnablement);
|
||||||
|
const cachedFeatureFlags = path.join(tmpDir, feature_flags_1.FEATURE_FLAGS_FILE_NAME);
|
||||||
|
t.false(fs.existsSync(cachedFeatureFlags), "Feature flag cached file should not exist before getting feature flags");
|
||||||
|
t.true(await featureEnablement.getValue(feature_flags_1.Feature.CliConfigFileEnabled, includeCodeQlIfRequired(feature_flags_1.Feature.CliConfigFileEnabled)), "Feature flag should be enabled initially");
|
||||||
|
t.true(fs.existsSync(cachedFeatureFlags), "Feature flag cached file should exist after getting feature flags");
|
||||||
|
const actualFeatureEnablement = JSON.parse(fs.readFileSync(cachedFeatureFlags, "utf8"));
|
||||||
|
t.deepEqual(actualFeatureEnablement, expectedFeatureEnablement);
|
||||||
|
// now test that we actually use the feature flag cache instead of the server
|
||||||
|
actualFeatureEnablement[feature_flags_1.Feature.CliConfigFileEnabled] = false;
|
||||||
|
fs.writeFileSync(cachedFeatureFlags, JSON.stringify(actualFeatureEnablement));
|
||||||
|
// delete the in memory cache so that we are forced to use the cached file
|
||||||
|
featureEnablement.gitHubFeatureFlags.cachedApiResponse = undefined;
|
||||||
|
t.false(await featureEnablement.getValue(feature_flags_1.Feature.CliConfigFileEnabled, includeCodeQlIfRequired(feature_flags_1.Feature.CliConfigFileEnabled)), "Feature flag should be enabled after reading from cached file");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
(0, ava_1.default)("Environment variable can override feature flag cache", async (t) => {
|
||||||
|
await (0, util_1.withTmpDir)(async (tmpDir) => {
|
||||||
|
const featureEnablement = setUpFeatureFlagTests(tmpDir);
|
||||||
|
const expectedFeatureEnablement = initializeFeatures(true);
|
||||||
|
(0, testing_utils_1.mockFeatureFlagApiEndpoint)(200, expectedFeatureEnablement);
|
||||||
|
const cachedFeatureFlags = path.join(tmpDir, feature_flags_1.FEATURE_FLAGS_FILE_NAME);
|
||||||
|
t.true(await featureEnablement.getValue(feature_flags_1.Feature.CliConfigFileEnabled, includeCodeQlIfRequired(feature_flags_1.Feature.CliConfigFileEnabled)), "Feature flag should be enabled initially");
|
||||||
|
t.true(fs.existsSync(cachedFeatureFlags), "Feature flag cached file should exist after getting feature flags");
|
||||||
|
process.env.CODEQL_PASS_CONFIG_TO_CLI = "false";
|
||||||
|
t.false(await featureEnablement.getValue(feature_flags_1.Feature.CliConfigFileEnabled, includeCodeQlIfRequired(feature_flags_1.Feature.CliConfigFileEnabled)), "Feature flag should be disabled after setting env var");
|
||||||
|
});
|
||||||
|
});
|
||||||
function assertAllFeaturesUndefinedInApi(t, loggedMessages) {
|
function assertAllFeaturesUndefinedInApi(t, loggedMessages) {
|
||||||
for (const feature of Object.keys(feature_flags_1.featureConfig)) {
|
for (const feature of Object.keys(feature_flags_1.featureConfig)) {
|
||||||
t.assert(loggedMessages.find((v) => v.type === "debug" &&
|
t.assert(loggedMessages.find((v) => v.type === "debug" &&
|
||||||
@@ -169,9 +221,9 @@ function initializeFeatures(initialValue) {
|
|||||||
return features;
|
return features;
|
||||||
}, {});
|
}, {});
|
||||||
}
|
}
|
||||||
function setUpTests(tmpDir, logger = (0, logging_1.getRunnerLogger)(true), gitHubVersion = { type: util_1.GitHubVariant.DOTCOM }) {
|
function setUpFeatureFlagTests(tmpDir, logger = (0, logging_1.getRunnerLogger)(true), gitHubVersion = { type: util_1.GitHubVariant.DOTCOM }) {
|
||||||
(0, testing_utils_1.setupActionsVars)(tmpDir, tmpDir);
|
(0, testing_utils_1.setupActionsVars)(tmpDir, tmpDir);
|
||||||
return new feature_flags_1.Features(gitHubVersion, testRepositoryNwo, logger);
|
return new feature_flags_1.Features(gitHubVersion, testRepositoryNwo, tmpDir, logger);
|
||||||
}
|
}
|
||||||
function includeCodeQlIfRequired(feature) {
|
function includeCodeQlIfRequired(feature) {
|
||||||
return feature_flags_1.featureConfig[feature].minimumVersion !== undefined
|
return feature_flags_1.featureConfig[feature].minimumVersion !== undefined
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Generated
+1
-1
@@ -88,7 +88,7 @@ async function run() {
|
|||||||
const gitHubVersion = await (0, api_client_1.getGitHubVersion)();
|
const gitHubVersion = await (0, api_client_1.getGitHubVersion)();
|
||||||
(0, util_1.checkGitHubVersionInRange)(gitHubVersion, logger);
|
(0, util_1.checkGitHubVersionInRange)(gitHubVersion, logger);
|
||||||
const repositoryNwo = (0, repository_1.parseRepositoryNwo)((0, util_1.getRequiredEnvParam)("GITHUB_REPOSITORY"));
|
const repositoryNwo = (0, repository_1.parseRepositoryNwo)((0, util_1.getRequiredEnvParam)("GITHUB_REPOSITORY"));
|
||||||
const features = new feature_flags_1.Features(gitHubVersion, repositoryNwo, logger);
|
const features = new feature_flags_1.Features(gitHubVersion, repositoryNwo, (0, actions_util_1.getTemporaryDirectory)(), logger);
|
||||||
try {
|
try {
|
||||||
const workflowErrors = await (0, actions_util_1.validateWorkflow)();
|
const workflowErrors = await (0, actions_util_1.validateWorkflow)();
|
||||||
if (!(await (0, actions_util_1.sendStatusReport)(await (0, actions_util_1.createStatusReportBase)("init", "starting", startedAt, workflowErrors)))) {
|
if (!(await (0, actions_util_1.sendStatusReport)(await (0, actions_util_1.createStatusReportBase)("init", "starting", startedAt, workflowErrors)))) {
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Generated
+1
-1
@@ -545,7 +545,7 @@ async function checkActionVersion(version) {
|
|||||||
githubVersion.type === GitHubVariant.GHAE ||
|
githubVersion.type === GitHubVariant.GHAE ||
|
||||||
(githubVersion.type === GitHubVariant.GHES &&
|
(githubVersion.type === GitHubVariant.GHES &&
|
||||||
semver.satisfies((_a = semver.coerce(githubVersion.version)) !== null && _a !== void 0 ? _a : "0.0.0", ">=3.4"))) {
|
semver.satisfies((_a = semver.coerce(githubVersion.version)) !== null && _a !== void 0 ? _a : "0.0.0", ">=3.4"))) {
|
||||||
core.warning("CodeQL Action v1 will be deprecated on December 7th, 2022. Please upgrade to v2. For " +
|
core.warning("CodeQL Action v1 will be deprecated on January 18th, 2023. Please upgrade to v2. For " +
|
||||||
"more information, see " +
|
"more information, see " +
|
||||||
"https://github.blog/changelog/2022-04-27-code-scanning-deprecation-of-codeql-action-v1/");
|
"https://github.blog/changelog/2022-04-27-code-scanning-deprecation-of-codeql-action-v1/");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,10 @@ name: "Export file baseline information"
|
|||||||
description: "Tests that file baseline information is exported when the feature is enabled"
|
description: "Tests that file baseline information is exported when the feature is enabled"
|
||||||
versions: ["nightly-latest"]
|
versions: ["nightly-latest"]
|
||||||
steps:
|
steps:
|
||||||
|
- uses: swift-actions/setup-swift@5cdaa9161ad1f55ae39a5ea1784ef96de72f95d9
|
||||||
|
if: runner.os != 'Windows'
|
||||||
|
with:
|
||||||
|
swift-version: "5.7"
|
||||||
- uses: ./../action/init
|
- uses: ./../action/init
|
||||||
with:
|
with:
|
||||||
languages: javascript
|
languages: javascript
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ steps:
|
|||||||
- name: Check sarif
|
- name: Check sarif
|
||||||
uses: ./../action/.github/check-sarif
|
uses: ./../action/.github/check-sarif
|
||||||
# Running on Windows requires CodeQL CLI 2.9.0+.
|
# Running on Windows requires CodeQL CLI 2.9.0+.
|
||||||
if: "!(matrix.version == 'stable-20220120' && (matrix.os == 'windows-latest' || matrix.os == 'windows-2019'))"
|
if: "!(matrix.version == 'stable-20220120' && runner.os == 'Windows')"
|
||||||
with:
|
with:
|
||||||
sarif-file: ${{ runner.temp }}/results/javascript.sarif
|
sarif-file: ${{ runner.temp }}/results/javascript.sarif
|
||||||
queries-run: js/ml-powered/nosql-injection,js/ml-powered/path-injection,js/ml-powered/sql-injection,js/ml-powered/xss
|
queries-run: js/ml-powered/nosql-injection,js/ml-powered/path-injection,js/ml-powered/sql-injection,js/ml-powered/xss
|
||||||
@@ -39,7 +39,7 @@ steps:
|
|||||||
- name: Check results
|
- name: Check results
|
||||||
env:
|
env:
|
||||||
# Running on Windows requires CodeQL CLI 2.9.0+.
|
# Running on Windows requires CodeQL CLI 2.9.0+.
|
||||||
SHOULD_RUN_ML_POWERED_QUERIES: ${{ !(matrix.version == 'stable-20220120' && (matrix.os == 'windows-latest' || matrix.os == 'windows-2019')) }}
|
SHOULD_RUN_ML_POWERED_QUERIES: ${{ !(matrix.version == 'stable-20220120' && runner.os == 'Windows') }}
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
echo "Expecting ML-powered queries to be run: ${SHOULD_RUN_ML_POWERED_QUERIES}"
|
echo "Expecting ML-powered queries to be run: ${SHOULD_RUN_ML_POWERED_QUERIES}"
|
||||||
|
|||||||
@@ -1,17 +1,28 @@
|
|||||||
name: "Multi-language repository"
|
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: ["ubuntu", "macos"]
|
operatingSystems: ["ubuntu", "macos"]
|
||||||
|
env:
|
||||||
|
CODEQL_ENABLE_EXPERIMENTAL_FEATURES_SWIFT: "true" # Remove when Swift is GA.
|
||||||
steps:
|
steps:
|
||||||
|
- uses: swift-actions/setup-swift@5cdaa9161ad1f55ae39a5ea1784ef96de72f95d9
|
||||||
|
if: runner.os != 'Windows'
|
||||||
|
with:
|
||||||
|
swift-version: "5.7"
|
||||||
|
|
||||||
- uses: ./../action/init
|
- uses: ./../action/init
|
||||||
with:
|
with:
|
||||||
db-location: "${{ runner.temp }}/customDbLocation"
|
db-location: "${{ runner.temp }}/customDbLocation"
|
||||||
tools: ${{ steps.prepare-test.outputs.tools-url }}
|
tools: ${{ steps.prepare-test.outputs.tools-url }}
|
||||||
|
|
||||||
- name: Build code
|
- name: Build code
|
||||||
shell: bash
|
shell: bash
|
||||||
run: ./build.sh
|
run: ./build.sh
|
||||||
|
|
||||||
- uses: ./../action/analyze
|
- uses: ./../action/analyze
|
||||||
id: analysis
|
id: analysis
|
||||||
- shell: bash
|
|
||||||
|
- name: Check language autodetect for all languages excluding Ruby, Swift
|
||||||
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
CPP_DB=${{ fromJson(steps.analysis.outputs.db-locations).cpp }}
|
CPP_DB=${{ fromJson(steps.analysis.outputs.db-locations).cpp }}
|
||||||
if [[ ! -d $CPP_DB ]] || [[ ! $CPP_DB == ${{ runner.temp }}/customDbLocation/* ]]; then
|
if [[ ! -d $CPP_DB ]] || [[ ! $CPP_DB == ${{ runner.temp }}/customDbLocation/* ]]; then
|
||||||
@@ -43,3 +54,23 @@ steps:
|
|||||||
echo "Did not create a database for Python, or created it in the wrong location."
|
echo "Did not create a database for Python, or created it in the wrong location."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
- name: Check language autodetect for Ruby
|
||||||
|
if: "(matrix.version == 'cached' || matrix.version == 'latest' || matrix.version == 'nightly-latest')"
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
RUBY_DB=${{ fromJson(steps.analysis.outputs.db-locations).ruby }}
|
||||||
|
if [[ ! -d $RUBY_DB ]] || [[ ! $RUBY_DB == ${{ runner.temp }}/customDbLocation/* ]]; then
|
||||||
|
echo "Did not create a database for Ruby, or created it in the wrong location."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Check language autodetect for Swift
|
||||||
|
if: "!startsWith(matrix.os, 'windows') && (matrix.version == 'cached' || matrix.version == 'latest' || matrix.version == 'nightly-latest')"
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
SWIFT_DB=${{ fromJson(steps.analysis.outputs.db-locations).swift }}
|
||||||
|
if [[ ! -d $SWIFT_DB ]] || [[ ! $SWIFT_DB == ${{ runner.temp }}/customDbLocation/* ]]; then
|
||||||
|
echo "Did not create a database for Swift, or created it in the wrong location."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|||||||
@@ -1,22 +0,0 @@
|
|||||||
# This check should be combined into `multi-language-autodetect.yml` once Ruby is GA'ed
|
|
||||||
# and the `CODEQL_ENABLE_EXPERIMENTAL_FEATURES` environment variable is not needed.
|
|
||||||
name: "Ruby analysis using autodetect"
|
|
||||||
description: "Tests creation of a Ruby database when language isn't specified in init"
|
|
||||||
versions: ["latest", "cached", "nightly-latest"]
|
|
||||||
operatingSystems: ["ubuntu", "macos"]
|
|
||||||
env:
|
|
||||||
CODEQL_ENABLE_EXPERIMENTAL_FEATURES: "true"
|
|
||||||
steps:
|
|
||||||
- uses: ./../action/init
|
|
||||||
with:
|
|
||||||
tools: ${{ steps.prepare-test.outputs.tools-url }}
|
|
||||||
- uses: ./../action/analyze
|
|
||||||
id: analysis
|
|
||||||
- name: Check database
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
RUBY_DB="${{ fromJson(steps.analysis.outputs.db-locations).ruby }}"
|
|
||||||
if [[ ! -d "$RUBY_DB" ]]; then
|
|
||||||
echo "Did not create a database for Ruby."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
@@ -2,8 +2,6 @@ name: "Ruby analysis"
|
|||||||
description: "Tests creation of a Ruby database"
|
description: "Tests creation of a Ruby database"
|
||||||
versions: ["latest", "cached", "nightly-latest"]
|
versions: ["latest", "cached", "nightly-latest"]
|
||||||
operatingSystems: ["ubuntu", "macos"]
|
operatingSystems: ["ubuntu", "macos"]
|
||||||
env:
|
|
||||||
CODEQL_ENABLE_EXPERIMENTAL_FEATURES: "true"
|
|
||||||
steps:
|
steps:
|
||||||
- uses: ./../action/init
|
- uses: ./../action/init
|
||||||
with:
|
with:
|
||||||
|
|||||||
@@ -6,6 +6,9 @@ operatingSystems: ["macos"]
|
|||||||
env:
|
env:
|
||||||
CODEQL_ENABLE_EXPERIMENTAL_FEATURES_SWIFT: "true"
|
CODEQL_ENABLE_EXPERIMENTAL_FEATURES_SWIFT: "true"
|
||||||
steps:
|
steps:
|
||||||
|
- uses: swift-actions/setup-swift@5cdaa9161ad1f55ae39a5ea1784ef96de72f95d9
|
||||||
|
with:
|
||||||
|
swift-version: "5.7"
|
||||||
- uses: ./../action/init
|
- uses: ./../action/init
|
||||||
with:
|
with:
|
||||||
languages: swift
|
languages: swift
|
||||||
|
|||||||
@@ -6,6 +6,9 @@ env:
|
|||||||
CODEQL_ENABLE_EXPERIMENTAL_FEATURES_SWIFT: "true"
|
CODEQL_ENABLE_EXPERIMENTAL_FEATURES_SWIFT: "true"
|
||||||
DOTNET_GENERATE_ASPNET_CERTIFICATE: "false"
|
DOTNET_GENERATE_ASPNET_CERTIFICATE: "false"
|
||||||
steps:
|
steps:
|
||||||
|
- uses: swift-actions/setup-swift@5cdaa9161ad1f55ae39a5ea1784ef96de72f95d9
|
||||||
|
with:
|
||||||
|
swift-version: "5.7"
|
||||||
- uses: ./../action/init
|
- uses: ./../action/init
|
||||||
with:
|
with:
|
||||||
languages: swift
|
languages: swift
|
||||||
|
|||||||
@@ -217,7 +217,12 @@ async function run() {
|
|||||||
|
|
||||||
const gitHubVersion = await getGitHubVersion();
|
const gitHubVersion = await getGitHubVersion();
|
||||||
|
|
||||||
const features = new Features(gitHubVersion, repositoryNwo, logger);
|
const features = new Features(
|
||||||
|
gitHubVersion,
|
||||||
|
repositoryNwo,
|
||||||
|
actionsUtil.getTemporaryDirectory(),
|
||||||
|
logger
|
||||||
|
);
|
||||||
|
|
||||||
await runAutobuildIfLegacyGoWorkflow(config, logger);
|
await runAutobuildIfLegacyGoWorkflow(config, logger);
|
||||||
|
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
{"maximumVersion": "3.7", "minimumVersion": "3.3"}
|
{"maximumVersion": "3.8", "minimumVersion": "3.3"}
|
||||||
|
|||||||
+97
-11
@@ -1,3 +1,6 @@
|
|||||||
|
import * as fs from "fs";
|
||||||
|
import * as path from "path";
|
||||||
|
|
||||||
import test from "ava";
|
import test from "ava";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@@ -5,6 +8,7 @@ import {
|
|||||||
featureConfig,
|
featureConfig,
|
||||||
FeatureEnablement,
|
FeatureEnablement,
|
||||||
Features,
|
Features,
|
||||||
|
FEATURE_FLAGS_FILE_NAME,
|
||||||
} from "./feature-flags";
|
} from "./feature-flags";
|
||||||
import { getRunnerLogger } from "./logging";
|
import { getRunnerLogger } from "./logging";
|
||||||
import { parseRepositoryNwo } from "./repository";
|
import { parseRepositoryNwo } from "./repository";
|
||||||
@@ -42,7 +46,7 @@ for (const variant of ALL_FEATURES_DISABLED_VARIANTS) {
|
|||||||
test(`All features are disabled if running against ${variant.description}`, async (t) => {
|
test(`All features are disabled if running against ${variant.description}`, async (t) => {
|
||||||
await withTmpDir(async (tmpDir) => {
|
await withTmpDir(async (tmpDir) => {
|
||||||
const loggedMessages = [];
|
const loggedMessages = [];
|
||||||
const featureEnablement = setUpTests(
|
const featureEnablement = setUpFeatureFlagTests(
|
||||||
tmpDir,
|
tmpDir,
|
||||||
getRecordingLogger(loggedMessages),
|
getRecordingLogger(loggedMessages),
|
||||||
variant.gitHubVersion
|
variant.gitHubVersion
|
||||||
@@ -72,7 +76,7 @@ for (const variant of ALL_FEATURES_DISABLED_VARIANTS) {
|
|||||||
test("API response missing", async (t) => {
|
test("API response missing", async (t) => {
|
||||||
await withTmpDir(async (tmpDir) => {
|
await withTmpDir(async (tmpDir) => {
|
||||||
const loggedMessages: LoggedMessage[] = [];
|
const loggedMessages: LoggedMessage[] = [];
|
||||||
const featureEnablement = setUpTests(
|
const featureEnablement = setUpFeatureFlagTests(
|
||||||
tmpDir,
|
tmpDir,
|
||||||
getRecordingLogger(loggedMessages)
|
getRecordingLogger(loggedMessages)
|
||||||
);
|
);
|
||||||
@@ -94,7 +98,7 @@ test("API response missing", async (t) => {
|
|||||||
test("Features are disabled if they're not returned in API response", async (t) => {
|
test("Features are disabled if they're not returned in API response", async (t) => {
|
||||||
await withTmpDir(async (tmpDir) => {
|
await withTmpDir(async (tmpDir) => {
|
||||||
const loggedMessages: LoggedMessage[] = [];
|
const loggedMessages: LoggedMessage[] = [];
|
||||||
const featureEnablement = setUpTests(
|
const featureEnablement = setUpFeatureFlagTests(
|
||||||
tmpDir,
|
tmpDir,
|
||||||
getRecordingLogger(loggedMessages)
|
getRecordingLogger(loggedMessages)
|
||||||
);
|
);
|
||||||
@@ -116,7 +120,7 @@ test("Features are disabled if they're not returned in API response", async (t)
|
|||||||
|
|
||||||
test("Feature flags exception is propagated if the API request errors", async (t) => {
|
test("Feature flags exception is propagated if the API request errors", async (t) => {
|
||||||
await withTmpDir(async (tmpDir) => {
|
await withTmpDir(async (tmpDir) => {
|
||||||
const featureEnablement = setUpTests(tmpDir);
|
const featureEnablement = setUpFeatureFlagTests(tmpDir);
|
||||||
|
|
||||||
mockFeatureFlagApiEndpoint(500, {});
|
mockFeatureFlagApiEndpoint(500, {});
|
||||||
|
|
||||||
@@ -137,7 +141,7 @@ test("Feature flags exception is propagated if the API request errors", async (t
|
|||||||
for (const feature of Object.keys(featureConfig)) {
|
for (const feature of Object.keys(featureConfig)) {
|
||||||
test(`Only feature '${feature}' is enabled if enabled in the API response. Other features disabled`, async (t) => {
|
test(`Only feature '${feature}' is enabled if enabled in the API response. Other features disabled`, async (t) => {
|
||||||
await withTmpDir(async (tmpDir) => {
|
await withTmpDir(async (tmpDir) => {
|
||||||
const featureEnablement = setUpTests(tmpDir);
|
const featureEnablement = setUpFeatureFlagTests(tmpDir);
|
||||||
|
|
||||||
// set all features to false except the one we're testing
|
// set all features to false except the one we're testing
|
||||||
const expectedFeatureEnablement: { [feature: string]: boolean } = {};
|
const expectedFeatureEnablement: { [feature: string]: boolean } = {};
|
||||||
@@ -162,7 +166,7 @@ for (const feature of Object.keys(featureConfig)) {
|
|||||||
|
|
||||||
test(`Only feature '${feature}' is enabled if the associated environment variable is true. Others disabled.`, async (t) => {
|
test(`Only feature '${feature}' is enabled if the associated environment variable is true. Others disabled.`, async (t) => {
|
||||||
await withTmpDir(async (tmpDir) => {
|
await withTmpDir(async (tmpDir) => {
|
||||||
const featureEnablement = setUpTests(tmpDir);
|
const featureEnablement = setUpFeatureFlagTests(tmpDir);
|
||||||
|
|
||||||
const expectedFeatureEnablement = initializeFeatures(false);
|
const expectedFeatureEnablement = initializeFeatures(false);
|
||||||
mockFeatureFlagApiEndpoint(200, expectedFeatureEnablement);
|
mockFeatureFlagApiEndpoint(200, expectedFeatureEnablement);
|
||||||
@@ -188,7 +192,7 @@ for (const feature of Object.keys(featureConfig)) {
|
|||||||
|
|
||||||
test(`Feature '${feature}' is disabled if the associated environment variable is false, even if enabled in API`, async (t) => {
|
test(`Feature '${feature}' is disabled if the associated environment variable is false, even if enabled in API`, async (t) => {
|
||||||
await withTmpDir(async (tmpDir) => {
|
await withTmpDir(async (tmpDir) => {
|
||||||
const featureEnablement = setUpTests(tmpDir);
|
const featureEnablement = setUpFeatureFlagTests(tmpDir);
|
||||||
|
|
||||||
const expectedFeatureEnablement = initializeFeatures(true);
|
const expectedFeatureEnablement = initializeFeatures(true);
|
||||||
mockFeatureFlagApiEndpoint(200, expectedFeatureEnablement);
|
mockFeatureFlagApiEndpoint(200, expectedFeatureEnablement);
|
||||||
@@ -215,7 +219,7 @@ for (const feature of Object.keys(featureConfig)) {
|
|||||||
if (featureConfig[feature].minimumVersion !== undefined) {
|
if (featureConfig[feature].minimumVersion !== undefined) {
|
||||||
test(`Getting feature '${feature} should throw if no codeql is provided`, async (t) => {
|
test(`Getting feature '${feature} should throw if no codeql is provided`, async (t) => {
|
||||||
await withTmpDir(async (tmpDir) => {
|
await withTmpDir(async (tmpDir) => {
|
||||||
const featureEnablement = setUpTests(tmpDir);
|
const featureEnablement = setUpFeatureFlagTests(tmpDir);
|
||||||
|
|
||||||
const expectedFeatureEnablement = initializeFeatures(true);
|
const expectedFeatureEnablement = initializeFeatures(true);
|
||||||
mockFeatureFlagApiEndpoint(200, expectedFeatureEnablement);
|
mockFeatureFlagApiEndpoint(200, expectedFeatureEnablement);
|
||||||
@@ -233,7 +237,7 @@ for (const feature of Object.keys(featureConfig)) {
|
|||||||
if (featureConfig[feature].minimumVersion !== undefined) {
|
if (featureConfig[feature].minimumVersion !== undefined) {
|
||||||
test(`Feature '${feature}' is disabled if the minimum CLI version is below ${featureConfig[feature].minimumVersion}`, async (t) => {
|
test(`Feature '${feature}' is disabled if the minimum CLI version is below ${featureConfig[feature].minimumVersion}`, async (t) => {
|
||||||
await withTmpDir(async (tmpDir) => {
|
await withTmpDir(async (tmpDir) => {
|
||||||
const featureEnablement = setUpTests(tmpDir);
|
const featureEnablement = setUpFeatureFlagTests(tmpDir);
|
||||||
|
|
||||||
const expectedFeatureEnablement = initializeFeatures(true);
|
const expectedFeatureEnablement = initializeFeatures(true);
|
||||||
mockFeatureFlagApiEndpoint(200, expectedFeatureEnablement);
|
mockFeatureFlagApiEndpoint(200, expectedFeatureEnablement);
|
||||||
@@ -285,6 +289,88 @@ test("At least one feature has a minimum version specified", (t) => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("Feature flags are saved to disk", async (t) => {
|
||||||
|
await withTmpDir(async (tmpDir) => {
|
||||||
|
const featureEnablement = setUpFeatureFlagTests(tmpDir);
|
||||||
|
const expectedFeatureEnablement = initializeFeatures(true);
|
||||||
|
mockFeatureFlagApiEndpoint(200, expectedFeatureEnablement);
|
||||||
|
|
||||||
|
const cachedFeatureFlags = path.join(tmpDir, FEATURE_FLAGS_FILE_NAME);
|
||||||
|
|
||||||
|
t.false(
|
||||||
|
fs.existsSync(cachedFeatureFlags),
|
||||||
|
"Feature flag cached file should not exist before getting feature flags"
|
||||||
|
);
|
||||||
|
|
||||||
|
t.true(
|
||||||
|
await featureEnablement.getValue(
|
||||||
|
Feature.CliConfigFileEnabled,
|
||||||
|
includeCodeQlIfRequired(Feature.CliConfigFileEnabled)
|
||||||
|
),
|
||||||
|
"Feature flag should be enabled initially"
|
||||||
|
);
|
||||||
|
|
||||||
|
t.true(
|
||||||
|
fs.existsSync(cachedFeatureFlags),
|
||||||
|
"Feature flag cached file should exist after getting feature flags"
|
||||||
|
);
|
||||||
|
|
||||||
|
const actualFeatureEnablement = JSON.parse(
|
||||||
|
fs.readFileSync(cachedFeatureFlags, "utf8")
|
||||||
|
);
|
||||||
|
t.deepEqual(actualFeatureEnablement, expectedFeatureEnablement);
|
||||||
|
|
||||||
|
// now test that we actually use the feature flag cache instead of the server
|
||||||
|
actualFeatureEnablement[Feature.CliConfigFileEnabled] = false;
|
||||||
|
fs.writeFileSync(
|
||||||
|
cachedFeatureFlags,
|
||||||
|
JSON.stringify(actualFeatureEnablement)
|
||||||
|
);
|
||||||
|
|
||||||
|
// delete the in memory cache so that we are forced to use the cached file
|
||||||
|
(featureEnablement as any).gitHubFeatureFlags.cachedApiResponse = undefined;
|
||||||
|
|
||||||
|
t.false(
|
||||||
|
await featureEnablement.getValue(
|
||||||
|
Feature.CliConfigFileEnabled,
|
||||||
|
includeCodeQlIfRequired(Feature.CliConfigFileEnabled)
|
||||||
|
),
|
||||||
|
"Feature flag should be enabled after reading from cached file"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Environment variable can override feature flag cache", async (t) => {
|
||||||
|
await withTmpDir(async (tmpDir) => {
|
||||||
|
const featureEnablement = setUpFeatureFlagTests(tmpDir);
|
||||||
|
const expectedFeatureEnablement = initializeFeatures(true);
|
||||||
|
mockFeatureFlagApiEndpoint(200, expectedFeatureEnablement);
|
||||||
|
|
||||||
|
const cachedFeatureFlags = path.join(tmpDir, FEATURE_FLAGS_FILE_NAME);
|
||||||
|
t.true(
|
||||||
|
await featureEnablement.getValue(
|
||||||
|
Feature.CliConfigFileEnabled,
|
||||||
|
includeCodeQlIfRequired(Feature.CliConfigFileEnabled)
|
||||||
|
),
|
||||||
|
"Feature flag should be enabled initially"
|
||||||
|
);
|
||||||
|
|
||||||
|
t.true(
|
||||||
|
fs.existsSync(cachedFeatureFlags),
|
||||||
|
"Feature flag cached file should exist after getting feature flags"
|
||||||
|
);
|
||||||
|
process.env.CODEQL_PASS_CONFIG_TO_CLI = "false";
|
||||||
|
|
||||||
|
t.false(
|
||||||
|
await featureEnablement.getValue(
|
||||||
|
Feature.CliConfigFileEnabled,
|
||||||
|
includeCodeQlIfRequired(Feature.CliConfigFileEnabled)
|
||||||
|
),
|
||||||
|
"Feature flag should be disabled after setting env var"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
function assertAllFeaturesUndefinedInApi(t, loggedMessages: LoggedMessage[]) {
|
function assertAllFeaturesUndefinedInApi(t, loggedMessages: LoggedMessage[]) {
|
||||||
for (const feature of Object.keys(featureConfig)) {
|
for (const feature of Object.keys(featureConfig)) {
|
||||||
t.assert(
|
t.assert(
|
||||||
@@ -305,14 +391,14 @@ function initializeFeatures(initialValue: boolean) {
|
|||||||
}, {});
|
}, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
function setUpTests(
|
function setUpFeatureFlagTests(
|
||||||
tmpDir: string,
|
tmpDir: string,
|
||||||
logger = getRunnerLogger(true),
|
logger = getRunnerLogger(true),
|
||||||
gitHubVersion = { type: GitHubVariant.DOTCOM } as util.GitHubVersion
|
gitHubVersion = { type: GitHubVariant.DOTCOM } as util.GitHubVersion
|
||||||
): FeatureEnablement {
|
): FeatureEnablement {
|
||||||
setupActionsVars(tmpDir, tmpDir);
|
setupActionsVars(tmpDir, tmpDir);
|
||||||
|
|
||||||
return new Features(gitHubVersion, testRepositoryNwo, logger);
|
return new Features(gitHubVersion, testRepositoryNwo, tmpDir, logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
function includeCodeQlIfRequired(feature: string) {
|
function includeCodeQlIfRequired(feature: string) {
|
||||||
|
|||||||
+69
-10
@@ -1,3 +1,6 @@
|
|||||||
|
import * as fs from "fs";
|
||||||
|
import * as path from "path";
|
||||||
|
|
||||||
import { getApiClient } from "./api-client";
|
import { getApiClient } from "./api-client";
|
||||||
import { CodeQL } from "./codeql";
|
import { CodeQL } from "./codeql";
|
||||||
import { Logger } from "./logging";
|
import { Logger } from "./logging";
|
||||||
@@ -55,6 +58,8 @@ export const featureConfig: Record<
|
|||||||
*/
|
*/
|
||||||
type GitHubFeatureFlagsApiResponse = Partial<Record<Feature, boolean>>;
|
type GitHubFeatureFlagsApiResponse = Partial<Record<Feature, boolean>>;
|
||||||
|
|
||||||
|
export const FEATURE_FLAGS_FILE_NAME = "cached-feature-flags.json";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines the enablement status of a number of features.
|
* Determines the enablement status of a number of features.
|
||||||
* If feature enablement is not able to be determined locally, a request to the
|
* If feature enablement is not able to be determined locally, a request to the
|
||||||
@@ -66,11 +71,13 @@ export class Features implements FeatureEnablement {
|
|||||||
constructor(
|
constructor(
|
||||||
gitHubVersion: util.GitHubVersion,
|
gitHubVersion: util.GitHubVersion,
|
||||||
repositoryNwo: RepositoryNwo,
|
repositoryNwo: RepositoryNwo,
|
||||||
|
tempDir: string,
|
||||||
logger: Logger
|
logger: Logger
|
||||||
) {
|
) {
|
||||||
this.gitHubFeatureFlags = new GitHubFeatureFlags(
|
this.gitHubFeatureFlags = new GitHubFeatureFlags(
|
||||||
gitHubVersion,
|
gitHubVersion,
|
||||||
repositoryNwo,
|
repositoryNwo,
|
||||||
|
path.join(tempDir, FEATURE_FLAGS_FILE_NAME),
|
||||||
logger
|
logger
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -120,7 +127,6 @@ export class Features implements FeatureEnablement {
|
|||||||
if (envVar === "true") {
|
if (envVar === "true") {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ask the GitHub API if the feature is enabled.
|
// Ask the GitHub API if the feature is enabled.
|
||||||
return await this.gitHubFeatureFlags.getValue(feature);
|
return await this.gitHubFeatureFlags.getValue(feature);
|
||||||
}
|
}
|
||||||
@@ -130,15 +136,16 @@ class GitHubFeatureFlags implements FeatureEnablement {
|
|||||||
private cachedApiResponse: GitHubFeatureFlagsApiResponse | undefined;
|
private cachedApiResponse: GitHubFeatureFlagsApiResponse | undefined;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private gitHubVersion: util.GitHubVersion,
|
private readonly gitHubVersion: util.GitHubVersion,
|
||||||
private repositoryNwo: RepositoryNwo,
|
private readonly repositoryNwo: RepositoryNwo,
|
||||||
private logger: Logger
|
private readonly featureFlagsFile: string,
|
||||||
|
private readonly logger: Logger
|
||||||
) {
|
) {
|
||||||
/**/
|
/**/
|
||||||
}
|
}
|
||||||
|
|
||||||
async getValue(feature: Feature): Promise<boolean> {
|
async getValue(feature: Feature): Promise<boolean> {
|
||||||
const response = await this.getApiResponse();
|
const response = await this.getAllFeatures();
|
||||||
if (response === undefined) {
|
if (response === undefined) {
|
||||||
this.logger.debug(
|
this.logger.debug(
|
||||||
`No feature flags API response for ${feature}, considering it disabled.`
|
`No feature flags API response for ${feature}, considering it disabled.`
|
||||||
@@ -155,11 +162,63 @@ class GitHubFeatureFlags implements FeatureEnablement {
|
|||||||
return !!featureEnablement;
|
return !!featureEnablement;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async getApiResponse(): Promise<GitHubFeatureFlagsApiResponse> {
|
private async getAllFeatures(): Promise<GitHubFeatureFlagsApiResponse> {
|
||||||
const apiResponse =
|
// if we have an in memory cache, use that
|
||||||
this.cachedApiResponse || (await this.loadApiResponse());
|
if (this.cachedApiResponse !== undefined) {
|
||||||
this.cachedApiResponse = apiResponse;
|
return this.cachedApiResponse;
|
||||||
return apiResponse;
|
}
|
||||||
|
|
||||||
|
// if a previous step has written a feature flags file to disk, use that
|
||||||
|
const fileFlags = await this.readLocalFlags();
|
||||||
|
if (fileFlags !== undefined) {
|
||||||
|
this.cachedApiResponse = fileFlags;
|
||||||
|
return fileFlags;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if not, request flags from the server
|
||||||
|
let remoteFlags = await this.loadApiResponse();
|
||||||
|
if (remoteFlags === undefined) {
|
||||||
|
remoteFlags = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
// cache the response in memory
|
||||||
|
this.cachedApiResponse = remoteFlags;
|
||||||
|
|
||||||
|
// and cache them to disk so future workflow steps can use them
|
||||||
|
await this.writeLocalFlags(remoteFlags);
|
||||||
|
|
||||||
|
return remoteFlags;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async readLocalFlags(): Promise<
|
||||||
|
GitHubFeatureFlagsApiResponse | undefined
|
||||||
|
> {
|
||||||
|
try {
|
||||||
|
if (fs.existsSync(this.featureFlagsFile)) {
|
||||||
|
this.logger.debug(
|
||||||
|
`Loading feature flags from ${this.featureFlagsFile}`
|
||||||
|
);
|
||||||
|
return JSON.parse(fs.readFileSync(this.featureFlagsFile, "utf8"));
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
this.logger.warning(
|
||||||
|
`Error reading cached feature flags file ${this.featureFlagsFile}: ${e}. Requesting from GitHub instead.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async writeLocalFlags(
|
||||||
|
flags: GitHubFeatureFlagsApiResponse
|
||||||
|
): Promise<void> {
|
||||||
|
try {
|
||||||
|
this.logger.debug(`Writing feature flags to ${this.featureFlagsFile}`);
|
||||||
|
fs.writeFileSync(this.featureFlagsFile, JSON.stringify(flags));
|
||||||
|
} catch (e) {
|
||||||
|
this.logger.warning(
|
||||||
|
`Error writing cached feature flags file ${this.featureFlagsFile}: ${e}.`
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async loadApiResponse() {
|
private async loadApiResponse() {
|
||||||
|
|||||||
+6
-1
@@ -158,7 +158,12 @@ async function run() {
|
|||||||
getRequiredEnvParam("GITHUB_REPOSITORY")
|
getRequiredEnvParam("GITHUB_REPOSITORY")
|
||||||
);
|
);
|
||||||
|
|
||||||
const features = new Features(gitHubVersion, repositoryNwo, logger);
|
const features = new Features(
|
||||||
|
gitHubVersion,
|
||||||
|
repositoryNwo,
|
||||||
|
getTemporaryDirectory(),
|
||||||
|
logger
|
||||||
|
);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const workflowErrors = await validateWorkflow();
|
const workflowErrors = await validateWorkflow();
|
||||||
|
|||||||
+1
-1
@@ -651,7 +651,7 @@ export async function checkActionVersion(version: string) {
|
|||||||
))
|
))
|
||||||
) {
|
) {
|
||||||
core.warning(
|
core.warning(
|
||||||
"CodeQL Action v1 will be deprecated on December 7th, 2022. Please upgrade to v2. For " +
|
"CodeQL Action v1 will be deprecated on January 18th, 2023. Please upgrade to v2. For " +
|
||||||
"more information, see " +
|
"more information, see " +
|
||||||
"https://github.blog/changelog/2022-04-27-code-scanning-deprecation-of-codeql-action-v1/"
|
"https://github.blog/changelog/2022-04-27-code-scanning-deprecation-of-codeql-action-v1/"
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user