-
Notifications
You must be signed in to change notification settings - Fork 433
Tolerate errors loading repository properties #3421
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
e142eee
4e14537
f4b47e7
d9e374e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -159,6 +159,9 @@ inputs: | |
| description: >- | ||
| Explicitly enable or disable caching of project build dependencies. | ||
| required: false | ||
| repository-owner-type: | ||
| default: ${{ github.event.repository.owner.type }} | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This seems like a reasonable solution that avoids an (additional) API call. To check: whether Alternative ideas:
|
||
| required: false | ||
| outputs: | ||
| codeql-path: | ||
| description: The path of the CodeQL binary used for analysis | ||
|
|
||
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -36,8 +36,11 @@ import { | |
| makeTelemetryDiagnostic, | ||
| } from "./diagnostics"; | ||
| import { EnvVar } from "./environment"; | ||
| import { Feature, Features } from "./feature-flags"; | ||
| import { loadPropertiesFromApi } from "./feature-flags/properties"; | ||
| import { Feature, FeatureEnablement, Features } from "./feature-flags"; | ||
| import { | ||
| loadPropertiesFromApi, | ||
| RepositoryProperties, | ||
| } from "./feature-flags/properties"; | ||
| import { | ||
| checkInstallPython311, | ||
| checkPacksForOverlayCompatibility, | ||
|
|
@@ -53,7 +56,7 @@ import { | |
| OverlayBaseDatabaseDownloadStats, | ||
| OverlayDatabaseMode, | ||
| } from "./overlay-database-utils"; | ||
| import { getRepositoryNwo } from "./repository"; | ||
| import { getRepositoryNwo, RepositoryNwo } from "./repository"; | ||
| import { ToolsSource } from "./setup-codeql"; | ||
| import { | ||
| ActionName, | ||
|
|
@@ -87,6 +90,8 @@ import { | |
| checkActionVersion, | ||
| getErrorMessage, | ||
| BuildMode, | ||
| GitHubVersion, | ||
| Result, | ||
| } from "./util"; | ||
| import { checkWorkflow } from "./workflow"; | ||
|
|
||
|
|
@@ -237,12 +242,12 @@ async function run(startedAt: Date) { | |
| ); | ||
|
|
||
| // Fetch the values of known repository properties that affect us. | ||
| const enableRepoProps = await features.getValue( | ||
| Feature.UseRepositoryProperties, | ||
| const repositoryProperties = await loadRepositoryProperties( | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Minor: Name this to indicate that it isn't a repository properties object itself, but a |
||
| repositoryNwo, | ||
| gitHubVersion, | ||
| features, | ||
| logger, | ||
| ); | ||
| const repositoryProperties = enableRepoProps | ||
| ? await loadPropertiesFromApi(gitHubVersion, logger, repositoryNwo) | ||
| : {}; | ||
|
|
||
| // Create a unique identifier for this run. | ||
| const jobRunUuid = uuidV4(); | ||
|
|
@@ -363,10 +368,26 @@ async function run(startedAt: Date) { | |
| githubVersion: gitHubVersion, | ||
| apiDetails, | ||
| features, | ||
| repositoryProperties, | ||
| repositoryProperties: repositoryProperties.orElse({}), | ||
| logger, | ||
| }); | ||
|
|
||
| if (repositoryProperties.isError()) { | ||
| addDiagnostic( | ||
| config, | ||
| // Arbitrarily choose the first language. We could also choose all languages, but that | ||
| // increases the risk of misinterpreting the data. | ||
| config.languages[0], | ||
|
Comment on lines
+376
to
+380
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Minor: We keep using this pattern; time to add a function for it so we don't have to repeat it / the comment every time? |
||
| makeTelemetryDiagnostic( | ||
| "codeql-action/repository-properties-load-failure", | ||
| "Failed to load repository properties", | ||
| { | ||
| error: getErrorMessage(repositoryProperties.value), | ||
| }, | ||
| ), | ||
| ); | ||
| } | ||
|
|
||
| await checkInstallPython311(config.languages, codeql); | ||
| } catch (unwrappedError) { | ||
| const error = wrapError(unwrappedError); | ||
|
|
@@ -775,6 +796,41 @@ async function run(startedAt: Date) { | |
| ); | ||
| } | ||
|
|
||
| async function loadRepositoryProperties( | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Move this to |
||
| repositoryNwo: RepositoryNwo, | ||
| gitHubVersion: GitHubVersion, | ||
| features: FeatureEnablement, | ||
| logger: Logger, | ||
| ): Promise<Result<RepositoryProperties, unknown>> { | ||
| const repositoryOwnerType = getOptionalInput("repository-owner-type"); | ||
| if (repositoryOwnerType === "User") { | ||
| // Users cannot have repository properties, so skip the API call. | ||
| logger.debug( | ||
| "Skipping loading repository properties because the repository is owned by a user and " + | ||
| "therefore cannot have repository properties.", | ||
| ); | ||
| return Result.ok({}); | ||
| } | ||
|
|
||
| if (!(await features.getValue(Feature.UseRepositoryProperties))) { | ||
| logger.debug( | ||
| "Skipping loading repository properties because the UseRepositoryProperties feature flag is disabled.", | ||
| ); | ||
| return Result.ok({}); | ||
| } | ||
|
|
||
| try { | ||
| return Result.ok( | ||
| await loadPropertiesFromApi(gitHubVersion, logger, repositoryNwo), | ||
| ); | ||
| } catch (error) { | ||
| logger.warning( | ||
| `Failed to load repository properties: ${getErrorMessage(error)}`, | ||
| ); | ||
| return Result.error(error); | ||
| } | ||
| } | ||
|
|
||
| function getTrapCachingEnabled(): boolean { | ||
| // If the workflow specified something always respect that | ||
| const trapCaching = getOptionalInput("trap-caching"); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1292,3 +1292,33 @@ export function joinAtMost( | |
|
|
||
| return array.join(separator); | ||
| } | ||
|
|
||
| type Success<T> = Result<T, never>; | ||
| type Failure<E> = Result<never, E>; | ||
|
|
||
| export class Result<T, E> { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I like this -- it's a good idea to start including errors in the types. Would you mind adding docs and unit tests for this? |
||
| private constructor( | ||
| private readonly _ok: boolean, | ||
| public readonly value: T | E, | ||
| ) {} | ||
|
|
||
| static ok<T>(value: T): Success<T> { | ||
| return new Result(true, value) as Success<T>; | ||
| } | ||
|
|
||
| static error<E>(error: E): Failure<E> { | ||
| return new Result(false, error) as Failure<E>; | ||
| } | ||
|
|
||
| isOk(): this is Success<T> { | ||
| return this._ok; | ||
| } | ||
|
|
||
| isError(): this is Failure<E> { | ||
| return !this._ok; | ||
| } | ||
|
|
||
| orElse(defaultValue: T): T { | ||
| return this._ok ? (this.value as T) : defaultValue; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would TS accept |
||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.