forked from github/codeql-action
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfile.ts
More file actions
137 lines (122 loc) · 4.55 KB
/
Copy pathfile.ts
File metadata and controls
137 lines (122 loc) · 4.55 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
import { ActionState } from "../action-common";
import { AnalysisKind } from "../analyses";
import * as api from "../api-client";
import * as errorMessages from "../error-messages";
import { Feature } from "../feature-flags";
import {
RepositoryProperties,
RepositoryPropertyName,
} from "../feature-flags/properties";
import { ConfigurationError } from "../util";
import { parseUserConfig, UserConfig } from "./db-config";
import { parseRemoteFileAddress } from "./remote-file";
/**
* The prefix that can be specified to indicate that a path should be treated as a local file address.
*/
export const LOCAL_PATH_PREFIX = "./";
/**
* The prefix that can be specified to indicate that a path should be treated as a remote file address.
* The new remote file address format must start with either an owner or repository name. Both
* are restricted to ASCII characters, '.', and '-'. The prefix chosen here does not interfere with
* those (since it contains an `=`) and is _unlikely_ (but not impossible) to appear in a local file path.
*/
export const REMOTE_PATH_PREFIX = "remote=";
/**
* Gets the value that is configured for the configuration file, if any.
*/
export async function getConfigFileInput(
{
logger,
actions,
features,
}: ActionState<["Logger", "Actions", "FeatureFlags"]>,
repositoryProperties: Partial<RepositoryProperties>,
analysisKinds: AnalysisKind[] | undefined,
): Promise<string | undefined> {
const input = actions.getOptionalInput("config-file");
if (input !== undefined) {
logger.info(`Using configuration file input from workflow: ${input}`);
return input;
}
const propertyValue =
repositoryProperties[RepositoryPropertyName.CONFIG_FILE];
// Only allow the repository property to be used for standard Code Scanning analyses,
// since we don't currently support some customisation options for Code Quality.
// We don't expect customisations for Risk Assessments either.
const analysisKindSupported =
analysisKinds === undefined ||
(analysisKinds.includes(AnalysisKind.CodeScanning) &&
analysisKinds.length === 1);
if (propertyValue !== undefined && propertyValue.trim().length > 0) {
// Only use the repository property value if the FF is enabled.
const useRepositoryProperty = await features.getValue(
Feature.ConfigFileRepositoryProperty,
);
if (analysisKindSupported && useRepositoryProperty) {
logger.info(
`Using configuration file input from repository property: ${propertyValue}`,
);
return propertyValue;
} else if (!analysisKindSupported) {
logger.info(
"Ignoring configuration file input from repository property, because it is unsupported for the current analysis kind.",
);
} else {
logger.info(
"Ignoring configuration file input from repository property, because the corresponding feature flag is disabled.",
);
}
}
return undefined;
}
/**
* Attempts to fetch a `UserConfig` from a remote `address`.
*
* @param actionState The current Action state.
* @param configFile The remote address of the configuration file.
* @param apiDetails Information about how to connect to the API.
*
* @returns The `UserConfig`, if it could be fetched and parsed successfully.
*/
export async function getRemoteConfig(
actionState: ActionState<["Logger", "Env", "FeatureFlags"]>,
configFile: string,
apiDetails: api.GitHubApiCombinedDetails,
): Promise<UserConfig> {
const address = await parseRemoteFileAddress(actionState, configFile);
const shouldProxyRequest = await actionState.features.getValue(
Feature.ProxyApiRequests,
);
const proxy = shouldProxyRequest
? api.getRegistryProxy(actionState)
: undefined;
const response = await api
.getApiClientWithExternalAuth(apiDetails, proxy)
.rest.repos.getContent({
owner: address.owner,
repo: address.repo,
path: address.path,
ref: address.ref,
});
let fileContents: string;
if ("content" in response.data && response.data.content !== undefined) {
fileContents = response.data.content;
} else if (Array.isArray(response.data)) {
throw new ConfigurationError(
errorMessages.getConfigFileDirectoryGivenMessage(configFile),
);
} else {
throw new ConfigurationError(
errorMessages.getConfigFileFormatInvalidMessage(configFile),
);
}
const validateConfig = await actionState.features.getValue(
Feature.ValidateDbConfig,
);
return parseUserConfig(
actionState.logger,
configFile,
Buffer.from(fileContents, "base64").toString("binary"),
validateConfig,
);
}