diff --git a/src/Octokit.Webhooks/Events/RepositoryAdvisory/RepositoryAdvisoryAction.cs b/src/Octokit.Webhooks/Events/RepositoryAdvisory/RepositoryAdvisoryAction.cs new file mode 100644 index 00000000..2e089150 --- /dev/null +++ b/src/Octokit.Webhooks/Events/RepositoryAdvisory/RepositoryAdvisoryAction.cs @@ -0,0 +1,14 @@ +namespace Octokit.Webhooks.Events.RepositoryAdvisory; + +[PublicAPI] +public sealed record RepositoryAdvisoryAction : WebhookEventAction +{ + public static readonly RepositoryAdvisoryAction Reported = new(RepositoryAdvisoryActionValue.Reported); + + public static readonly RepositoryAdvisoryAction Published = new(RepositoryAdvisoryActionValue.Published); + + private RepositoryAdvisoryAction(string value) + : base(value) + { + } +} diff --git a/src/Octokit.Webhooks/Events/RepositoryAdvisory/RepositoryAdvisoryActionValue.cs b/src/Octokit.Webhooks/Events/RepositoryAdvisory/RepositoryAdvisoryActionValue.cs new file mode 100644 index 00000000..9fd4cb30 --- /dev/null +++ b/src/Octokit.Webhooks/Events/RepositoryAdvisory/RepositoryAdvisoryActionValue.cs @@ -0,0 +1,8 @@ +namespace Octokit.Webhooks.Events.RepositoryAdvisory; + +public static class RepositoryAdvisoryActionValue +{ + public const string Reported = "reported"; + + public const string Published = "published"; +} diff --git a/src/Octokit.Webhooks/Events/RepositoryAdvisory/RepositoryAdvisoryPublishedEvent.cs b/src/Octokit.Webhooks/Events/RepositoryAdvisory/RepositoryAdvisoryPublishedEvent.cs new file mode 100644 index 00000000..9524bf47 --- /dev/null +++ b/src/Octokit.Webhooks/Events/RepositoryAdvisory/RepositoryAdvisoryPublishedEvent.cs @@ -0,0 +1,9 @@ +namespace Octokit.Webhooks.Events.RepositoryAdvisory; + +[PublicAPI] +[WebhookActionType(RepositoryAdvisoryActionValue.Published)] +public sealed record RepositoryAdvisoryPublishedEvent : RepositoryAdvisoryEvent +{ + [JsonPropertyName("action")] + public override string Action => RepositoryAdvisoryAction.Published; +} diff --git a/src/Octokit.Webhooks/Events/RepositoryAdvisory/RepositoryAdvisoryReportedEvent.cs b/src/Octokit.Webhooks/Events/RepositoryAdvisory/RepositoryAdvisoryReportedEvent.cs new file mode 100644 index 00000000..7966ff45 --- /dev/null +++ b/src/Octokit.Webhooks/Events/RepositoryAdvisory/RepositoryAdvisoryReportedEvent.cs @@ -0,0 +1,9 @@ +namespace Octokit.Webhooks.Events.RepositoryAdvisory; + +[PublicAPI] +[WebhookActionType(RepositoryAdvisoryActionValue.Reported)] +public sealed record RepositoryAdvisoryReportedEvent : RepositoryAdvisoryEvent +{ + [JsonPropertyName("action")] + public override string Action => RepositoryAdvisoryAction.Reported; +} diff --git a/src/Octokit.Webhooks/Events/RepositoryAdvisoryEvent.cs b/src/Octokit.Webhooks/Events/RepositoryAdvisoryEvent.cs new file mode 100644 index 00000000..da29e2b8 --- /dev/null +++ b/src/Octokit.Webhooks/Events/RepositoryAdvisoryEvent.cs @@ -0,0 +1,10 @@ +namespace Octokit.Webhooks.Events; + +[PublicAPI] +[WebhookEventType(WebhookEventType.RepositoryAdvisory)] +[JsonConverter(typeof(WebhookConverter))] +public abstract record RepositoryAdvisoryEvent : WebhookEvent +{ + [JsonPropertyName("repository_advisory")] + public Models.RepositoryAdvisoryEvent.RepositoryAdvisory RepositoryAdvisory { get; init; } = null!; +} diff --git a/src/Octokit.Webhooks/Models/RepositoryAdvisoryEvent/RepositoryAdvisory.cs b/src/Octokit.Webhooks/Models/RepositoryAdvisoryEvent/RepositoryAdvisory.cs new file mode 100644 index 00000000..4114b93e --- /dev/null +++ b/src/Octokit.Webhooks/Models/RepositoryAdvisoryEvent/RepositoryAdvisory.cs @@ -0,0 +1,93 @@ +namespace Octokit.Webhooks.Models.RepositoryAdvisoryEvent; + +[PublicAPI] +public sealed record RepositoryAdvisory +{ + [JsonPropertyName("ghsa_id")] + public string GhsaId { get; init; } = null!; + + [JsonPropertyName("cve_id")] + public string? CveId { get; init; } + + [JsonPropertyName("url")] + public string Url { get; init; } = null!; + + [JsonPropertyName("html_url")] + public string HtmlUrl { get; init; } = null!; + + [JsonPropertyName("summary")] + public string Summary { get; init; } = null!; + + [JsonPropertyName("description")] + public string Description { get; init; } = null!; + + [JsonPropertyName("severity")] + [JsonConverter(typeof(StringEnumConverter))] + public StringEnum? Severity { get; init; } + + [JsonPropertyName("author")] + public User? Author { get; init; } + + [JsonPropertyName("publisher")] + public User? Publisher { get; init; } + + [JsonPropertyName("identifiers")] + public IEnumerable Identifiers { get; init; } = null!; + + [JsonPropertyName("state")] + [JsonConverter(typeof(StringEnumConverter))] + public StringEnum State { get; init; } = null!; + + [JsonPropertyName("created_at")] + [JsonConverter(typeof(DateTimeOffsetConverter))] + public DateTimeOffset? CreatedAt { get; init; } + + [JsonPropertyName("updated_at")] + [JsonConverter(typeof(DateTimeOffsetConverter))] + public DateTimeOffset? UpdatedAt { get; init; } + + [JsonPropertyName("published_at")] + [JsonConverter(typeof(DateTimeOffsetConverter))] + public DateTimeOffset? PublishedAt { get; init; } + + [JsonPropertyName("closed_at")] + [JsonConverter(typeof(NullableDateTimeOffsetConverter))] + public DateTimeOffset? ClosedAt { get; init; } + + [JsonPropertyName("withdrawn_at")] + [JsonConverter(typeof(NullableDateTimeOffsetConverter))] + public DateTimeOffset? WithdrawnAt { get; init; } + + [JsonPropertyName("submission")] + public RepositoryAdvisorySubmission? Submission { get; init; } + + [JsonPropertyName("vulnerabilities")] + public IEnumerable? Vulnerabilities { get; init; } + + [JsonPropertyName("cvss")] + public RepositoryAdvisoryCvss? Cvss { get; init; } + + [JsonPropertyName("cvss_severities")] + public RepositoryAdvisoryCvssSeverities? CvssSeverities { get; init; } + + [JsonPropertyName("cwes")] + public IEnumerable? Cwes { get; init; } + + [JsonPropertyName("cwe_ids")] + public IEnumerable? CweIds { get; init; } + + [JsonPropertyName("credits")] + public IEnumerable? Credits { get; init; } + + [JsonPropertyName("credits_detailed")] + public IEnumerable? CreditsDetailed { get; init; } + + [JsonPropertyName("collaborating_users")] + public IEnumerable? CollaboratingUsers { get; init; } + + [JsonPropertyName("collaborating_teams")] + public IEnumerable? CollaboratingTeams { get; init; } + + [JsonPropertyName("private_fork")] + public Repository? PrivateFork { get; init; } +} diff --git a/src/Octokit.Webhooks/Models/RepositoryAdvisoryEvent/RepositoryAdvisoryCredit.cs b/src/Octokit.Webhooks/Models/RepositoryAdvisoryEvent/RepositoryAdvisoryCredit.cs new file mode 100644 index 00000000..bc6a8e1e --- /dev/null +++ b/src/Octokit.Webhooks/Models/RepositoryAdvisoryEvent/RepositoryAdvisoryCredit.cs @@ -0,0 +1,12 @@ +namespace Octokit.Webhooks.Models.RepositoryAdvisoryEvent; + +[PublicAPI] +public sealed record RepositoryAdvisoryCredit +{ + [JsonPropertyName("login")] + public string Login { get; init; } = null!; + + [JsonPropertyName("type")] + [JsonConverter(typeof(StringEnumConverter))] + public StringEnum Type { get; init; } = null!; +} diff --git a/src/Octokit.Webhooks/Models/RepositoryAdvisoryEvent/RepositoryAdvisoryCreditDetailed.cs b/src/Octokit.Webhooks/Models/RepositoryAdvisoryEvent/RepositoryAdvisoryCreditDetailed.cs new file mode 100644 index 00000000..48efb6eb --- /dev/null +++ b/src/Octokit.Webhooks/Models/RepositoryAdvisoryEvent/RepositoryAdvisoryCreditDetailed.cs @@ -0,0 +1,16 @@ +namespace Octokit.Webhooks.Models.RepositoryAdvisoryEvent; + +[PublicAPI] +public sealed record RepositoryAdvisoryCreditDetailed +{ + [JsonPropertyName("user")] + public User User { get; init; } = null!; + + [JsonPropertyName("type")] + [JsonConverter(typeof(StringEnumConverter))] + public StringEnum Type { get; init; } = null!; + + [JsonPropertyName("state")] + [JsonConverter(typeof(StringEnumConverter))] + public StringEnum? State { get; init; } +} diff --git a/src/Octokit.Webhooks/Models/RepositoryAdvisoryEvent/RepositoryAdvisoryCreditState.cs b/src/Octokit.Webhooks/Models/RepositoryAdvisoryEvent/RepositoryAdvisoryCreditState.cs new file mode 100644 index 00000000..1e6c170c --- /dev/null +++ b/src/Octokit.Webhooks/Models/RepositoryAdvisoryEvent/RepositoryAdvisoryCreditState.cs @@ -0,0 +1,12 @@ +namespace Octokit.Webhooks.Models.RepositoryAdvisoryEvent; + +[PublicAPI] +public enum RepositoryAdvisoryCreditState +{ + [EnumMember(Value = "accepted")] + Accepted, + [EnumMember(Value = "declined")] + Declined, + [EnumMember(Value = "pending")] + Pending, +} diff --git a/src/Octokit.Webhooks/Models/RepositoryAdvisoryEvent/RepositoryAdvisoryCreditType.cs b/src/Octokit.Webhooks/Models/RepositoryAdvisoryEvent/RepositoryAdvisoryCreditType.cs new file mode 100644 index 00000000..00b16800 --- /dev/null +++ b/src/Octokit.Webhooks/Models/RepositoryAdvisoryEvent/RepositoryAdvisoryCreditType.cs @@ -0,0 +1,26 @@ +namespace Octokit.Webhooks.Models.RepositoryAdvisoryEvent; + +[PublicAPI] +public enum RepositoryAdvisoryCreditType +{ + [EnumMember(Value = "analyst")] + Analyst, + [EnumMember(Value = "finder")] + Finder, + [EnumMember(Value = "reporter")] + Reporter, + [EnumMember(Value = "coordinator")] + Coordinator, + [EnumMember(Value = "remediation_developer")] + RemediationDeveloper, + [EnumMember(Value = "remediation_reviewer")] + RemediationReviewer, + [EnumMember(Value = "remediation_verifier")] + RemediationVerifier, + [EnumMember(Value = "tool")] + Tool, + [EnumMember(Value = "sponsor")] + Sponsor, + [EnumMember(Value = "other")] + Other, +} diff --git a/src/Octokit.Webhooks/Models/RepositoryAdvisoryEvent/RepositoryAdvisoryCvss.cs b/src/Octokit.Webhooks/Models/RepositoryAdvisoryEvent/RepositoryAdvisoryCvss.cs new file mode 100644 index 00000000..f676fc77 --- /dev/null +++ b/src/Octokit.Webhooks/Models/RepositoryAdvisoryEvent/RepositoryAdvisoryCvss.cs @@ -0,0 +1,11 @@ +namespace Octokit.Webhooks.Models.RepositoryAdvisoryEvent; + +[PublicAPI] +public sealed record RepositoryAdvisoryCvss +{ + [JsonPropertyName("vector_string")] + public string? VectorString { get; init; } + + [JsonPropertyName("score")] + public float? Score { get; init; } +} diff --git a/src/Octokit.Webhooks/Models/RepositoryAdvisoryEvent/RepositoryAdvisoryCvssSeverities.cs b/src/Octokit.Webhooks/Models/RepositoryAdvisoryEvent/RepositoryAdvisoryCvssSeverities.cs new file mode 100644 index 00000000..a938a989 --- /dev/null +++ b/src/Octokit.Webhooks/Models/RepositoryAdvisoryEvent/RepositoryAdvisoryCvssSeverities.cs @@ -0,0 +1,11 @@ +namespace Octokit.Webhooks.Models.RepositoryAdvisoryEvent; + +[PublicAPI] +public sealed record RepositoryAdvisoryCvssSeverities +{ + [JsonPropertyName("cvss_v3")] + public RepositoryAdvisoryCvss? CvssV3 { get; init; } + + [JsonPropertyName("cvss_v4")] + public RepositoryAdvisoryCvss? CvssV4 { get; init; } +} diff --git a/src/Octokit.Webhooks/Models/RepositoryAdvisoryEvent/RepositoryAdvisoryCwe.cs b/src/Octokit.Webhooks/Models/RepositoryAdvisoryEvent/RepositoryAdvisoryCwe.cs new file mode 100644 index 00000000..d7e5484e --- /dev/null +++ b/src/Octokit.Webhooks/Models/RepositoryAdvisoryEvent/RepositoryAdvisoryCwe.cs @@ -0,0 +1,11 @@ +namespace Octokit.Webhooks.Models.RepositoryAdvisoryEvent; + +[PublicAPI] +public sealed record RepositoryAdvisoryCwe +{ + [JsonPropertyName("cwe_id")] + public string CweId { get; init; } = null!; + + [JsonPropertyName("name")] + public string Name { get; init; } = null!; +} diff --git a/src/Octokit.Webhooks/Models/RepositoryAdvisoryEvent/RepositoryAdvisoryIdentifier.cs b/src/Octokit.Webhooks/Models/RepositoryAdvisoryEvent/RepositoryAdvisoryIdentifier.cs new file mode 100644 index 00000000..939fb6c3 --- /dev/null +++ b/src/Octokit.Webhooks/Models/RepositoryAdvisoryEvent/RepositoryAdvisoryIdentifier.cs @@ -0,0 +1,11 @@ +namespace Octokit.Webhooks.Models.RepositoryAdvisoryEvent; + +[PublicAPI] +public sealed record RepositoryAdvisoryIdentifier +{ + [JsonPropertyName("value")] + public string Value { get; init; } = null!; + + [JsonPropertyName("type")] + public string Type { get; init; } = null!; +} diff --git a/src/Octokit.Webhooks/Models/RepositoryAdvisoryEvent/RepositoryAdvisorySeverity.cs b/src/Octokit.Webhooks/Models/RepositoryAdvisoryEvent/RepositoryAdvisorySeverity.cs new file mode 100644 index 00000000..0925961d --- /dev/null +++ b/src/Octokit.Webhooks/Models/RepositoryAdvisoryEvent/RepositoryAdvisorySeverity.cs @@ -0,0 +1,14 @@ +namespace Octokit.Webhooks.Models.RepositoryAdvisoryEvent; + +[PublicAPI] +public enum RepositoryAdvisorySeverity +{ + [EnumMember(Value = "critical")] + Critical, + [EnumMember(Value = "high")] + High, + [EnumMember(Value = "medium")] + Medium, + [EnumMember(Value = "low")] + Low, +} diff --git a/src/Octokit.Webhooks/Models/RepositoryAdvisoryEvent/RepositoryAdvisoryState.cs b/src/Octokit.Webhooks/Models/RepositoryAdvisoryEvent/RepositoryAdvisoryState.cs new file mode 100644 index 00000000..d3fa25cf --- /dev/null +++ b/src/Octokit.Webhooks/Models/RepositoryAdvisoryEvent/RepositoryAdvisoryState.cs @@ -0,0 +1,16 @@ +namespace Octokit.Webhooks.Models.RepositoryAdvisoryEvent; + +[PublicAPI] +public enum RepositoryAdvisoryState +{ + [EnumMember(Value = "published")] + Published, + [EnumMember(Value = "closed")] + Closed, + [EnumMember(Value = "withdrawn")] + Withdrawn, + [EnumMember(Value = "draft")] + Draft, + [EnumMember(Value = "triage")] + Triage, +} diff --git a/src/Octokit.Webhooks/Models/RepositoryAdvisoryEvent/RepositoryAdvisorySubmission.cs b/src/Octokit.Webhooks/Models/RepositoryAdvisoryEvent/RepositoryAdvisorySubmission.cs new file mode 100644 index 00000000..acd06d31 --- /dev/null +++ b/src/Octokit.Webhooks/Models/RepositoryAdvisoryEvent/RepositoryAdvisorySubmission.cs @@ -0,0 +1,8 @@ +namespace Octokit.Webhooks.Models.RepositoryAdvisoryEvent; + +[PublicAPI] +public sealed record RepositoryAdvisorySubmission +{ + [JsonPropertyName("accepted")] + public bool Accepted { get; init; } +} diff --git a/src/Octokit.Webhooks/Models/RepositoryAdvisoryEvent/RepositoryAdvisoryVulnerability.cs b/src/Octokit.Webhooks/Models/RepositoryAdvisoryEvent/RepositoryAdvisoryVulnerability.cs new file mode 100644 index 00000000..c7efa61b --- /dev/null +++ b/src/Octokit.Webhooks/Models/RepositoryAdvisoryEvent/RepositoryAdvisoryVulnerability.cs @@ -0,0 +1,17 @@ +namespace Octokit.Webhooks.Models.RepositoryAdvisoryEvent; + +[PublicAPI] +public sealed record RepositoryAdvisoryVulnerability +{ + [JsonPropertyName("package")] + public RepositoryAdvisoryVulnerabilityPackage? Package { get; init; } + + [JsonPropertyName("vulnerable_version_range")] + public string? VulnerableVersionRange { get; init; } + + [JsonPropertyName("patched_versions")] + public string? PatchedVersions { get; init; } + + [JsonPropertyName("vulnerable_functions")] + public IEnumerable? VulnerableFunctions { get; init; } +} diff --git a/src/Octokit.Webhooks/Models/RepositoryAdvisoryEvent/RepositoryAdvisoryVulnerabilityPackage.cs b/src/Octokit.Webhooks/Models/RepositoryAdvisoryEvent/RepositoryAdvisoryVulnerabilityPackage.cs new file mode 100644 index 00000000..651241b8 --- /dev/null +++ b/src/Octokit.Webhooks/Models/RepositoryAdvisoryEvent/RepositoryAdvisoryVulnerabilityPackage.cs @@ -0,0 +1,12 @@ +namespace Octokit.Webhooks.Models.RepositoryAdvisoryEvent; + +[PublicAPI] +public sealed record RepositoryAdvisoryVulnerabilityPackage +{ + [JsonPropertyName("ecosystem")] + [JsonConverter(typeof(StringEnumConverter))] + public StringEnum Ecosystem { get; init; } = null!; + + [JsonPropertyName("name")] + public string? Name { get; init; } +} diff --git a/src/Octokit.Webhooks/Models/RepositoryAdvisoryEvent/RepositoryAdvisoryVulnerabilityPackageEcosystem.cs b/src/Octokit.Webhooks/Models/RepositoryAdvisoryEvent/RepositoryAdvisoryVulnerabilityPackageEcosystem.cs new file mode 100644 index 00000000..a3c34b8f --- /dev/null +++ b/src/Octokit.Webhooks/Models/RepositoryAdvisoryEvent/RepositoryAdvisoryVulnerabilityPackageEcosystem.cs @@ -0,0 +1,32 @@ +namespace Octokit.Webhooks.Models.RepositoryAdvisoryEvent; + +[PublicAPI] +public enum RepositoryAdvisoryVulnerabilityPackageEcosystem +{ + [EnumMember(Value = "rubygems")] + Rubygems, + [EnumMember(Value = "npm")] + Npm, + [EnumMember(Value = "pip")] + Pip, + [EnumMember(Value = "maven")] + Maven, + [EnumMember(Value = "nuget")] + Nuget, + [EnumMember(Value = "composer")] + Composer, + [EnumMember(Value = "go")] + Go, + [EnumMember(Value = "rust")] + Rust, + [EnumMember(Value = "erlang")] + Erlang, + [EnumMember(Value = "actions")] + Actions, + [EnumMember(Value = "pub")] + Pub, + [EnumMember(Value = "other")] + Other, + [EnumMember(Value = "swift")] + Swift, +} diff --git a/src/Octokit.Webhooks/WebHookEventType.cs b/src/Octokit.Webhooks/WebHookEventType.cs index 0a3ca135..47d38cb6 100644 --- a/src/Octokit.Webhooks/WebHookEventType.cs +++ b/src/Octokit.Webhooks/WebHookEventType.cs @@ -54,6 +54,7 @@ public static class WebhookEventType public const string RegistryPackage = "registry_package"; public const string Release = "release"; public const string Repository = "repository"; + public const string RepositoryAdvisory = "repository_advisory"; public const string RepositoryDispatch = "repository_dispatch"; public const string RepositoryImport = "repository_import"; public const string RepositoryRuleset = "repository_ruleset"; diff --git a/src/Octokit.Webhooks/WebhookEventProcessor.cs b/src/Octokit.Webhooks/WebhookEventProcessor.cs index 8acd9b74..fb8d03d8 100644 --- a/src/Octokit.Webhooks/WebhookEventProcessor.cs +++ b/src/Octokit.Webhooks/WebhookEventProcessor.cs @@ -46,6 +46,7 @@ namespace Octokit.Webhooks; using Octokit.Webhooks.Events.RegistryPackage; using Octokit.Webhooks.Events.Release; using Octokit.Webhooks.Events.Repository; +using Octokit.Webhooks.Events.RepositoryAdvisory; using Octokit.Webhooks.Events.RepositoryDispatch; using Octokit.Webhooks.Events.RepositoryRuleset; using Octokit.Webhooks.Events.RepositoryVulnerabilityAlert; @@ -135,6 +136,7 @@ PullRequestReviewThreadEvent pullRequestReviewThreadEvent ReleaseEvent releaseEvent => this.ProcessReleaseWebhookAsync(headers, releaseEvent), RegistryPackageEvent registryPackageEvent => this.ProcessRegistryPackageWebhookAsync(headers, registryPackageEvent), RepositoryEvent repositoryEvent => this.ProcessRepositoryWebhookAsync(headers, repositoryEvent), + RepositoryAdvisoryEvent repositoryAdvisoryEvent => this.ProcessRepositoryAdvisoryWebhookAsync(headers, repositoryAdvisoryEvent), RepositoryDispatchEvent repositoryDispatchEvent => this.ProcessRepositoryDispatchWebhookAsync(headers, repositoryDispatchEvent), RepositoryImportEvent repositoryImportEvent => this.ProcessRepositoryImportWebhookAsync(headers, repositoryImportEvent), @@ -214,6 +216,7 @@ public virtual WebhookEvent DeserializeWebhookEvent(WebhookHeaders headers, stri WebhookEventType.Release => JsonSerializer.Deserialize(body)!, WebhookEventType.RegistryPackage => JsonSerializer.Deserialize(body)!, WebhookEventType.Repository => JsonSerializer.Deserialize(body)!, + WebhookEventType.RepositoryAdvisory => JsonSerializer.Deserialize(body)!, WebhookEventType.RepositoryDispatch => JsonSerializer.Deserialize(body)!, WebhookEventType.RepositoryImport => JsonSerializer.Deserialize(body)!, WebhookEventType.RepositoryRuleset => JsonSerializer.Deserialize(body)!, @@ -1072,6 +1075,26 @@ protected virtual Task ProcessRepositoryWebhookAsync( RepositoryEvent repositoryEvent, RepositoryAction action) => Task.CompletedTask; + private Task ProcessRepositoryAdvisoryWebhookAsync(WebhookHeaders headers, RepositoryAdvisoryEvent repositoryAdvisoryEvent) => + repositoryAdvisoryEvent.Action switch + { + RepositoryAdvisoryActionValue.Reported => this.ProcessRepositoryAdvisoryWebhookAsync( + headers, + repositoryAdvisoryEvent, + RepositoryAdvisoryAction.Reported), + RepositoryAdvisoryActionValue.Published => this.ProcessRepositoryAdvisoryWebhookAsync( + headers, + repositoryAdvisoryEvent, + RepositoryAdvisoryAction.Published), + _ => Task.CompletedTask, + }; + + [PublicAPI] + protected virtual Task ProcessRepositoryAdvisoryWebhookAsync( + WebhookHeaders headers, + RepositoryAdvisoryEvent repositoryAdvisoryEvent, + RepositoryAdvisoryAction action) => Task.CompletedTask; + private Task ProcessRepositoryDispatchWebhookAsync(WebhookHeaders headers, RepositoryDispatchEvent repositoryDispatchEvent) => repositoryDispatchEvent.Action switch { diff --git a/test/Octokit.Webhooks.Test/Resources/repository_advisory/published.payload.json b/test/Octokit.Webhooks.Test/Resources/repository_advisory/published.payload.json new file mode 100644 index 00000000..108aaf6c --- /dev/null +++ b/test/Octokit.Webhooks.Test/Resources/repository_advisory/published.payload.json @@ -0,0 +1,230 @@ +{ + "action": "published", + "repository_advisory": { + "ghsa_id": "GHSA-343j-49q4-v8gw", + "cve_id": null, + "url": "https://api.github.com/repos/pi-hole/land_of_confusion/security-advisories/GHSA-343j-49q4-v8gw", + "html_url": "https://github.com/pi-hole/land_of_confusion/security/advisories/GHSA-343j-49q4-v8gw", + "summary": "12314", + "description": "1231242145", + "severity": "low", + "author": null, + "publisher": { + "login": "PromoFaux", + "id": 1998970, + "node_id": "MDQ6VXNlcjE5OTg5NzA=", + "avatar_url": "https://avatars.githubusercontent.com/u/1998970?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/PromoFaux", + "html_url": "https://github.com/PromoFaux", + "followers_url": "https://api.github.com/users/PromoFaux/followers", + "following_url": "https://api.github.com/users/PromoFaux/following{/other_user}", + "gists_url": "https://api.github.com/users/PromoFaux/gists{/gist_id}", + "starred_url": "https://api.github.com/users/PromoFaux/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/PromoFaux/subscriptions", + "organizations_url": "https://api.github.com/users/PromoFaux/orgs", + "repos_url": "https://api.github.com/users/PromoFaux/repos", + "events_url": "https://api.github.com/users/PromoFaux/events{/privacy}", + "received_events_url": "https://api.github.com/users/PromoFaux/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "identifiers": [ + { + "value": "GHSA-343j-49q4-v8gw", + "type": "GHSA" + } + ], + "state": "published", + "created_at": null, + "updated_at": "2025-04-15T17:12:43Z", + "published_at": "2025-04-15T17:12:43Z", + "closed_at": null, + "withdrawn_at": null, + "submission": null, + "vulnerabilities": [ + { + "package": { + "ecosystem": "", + "name": "" + }, + "vulnerable_version_range": "<0", + "patched_versions": ">0", + "vulnerable_functions": [ + + ] + } + ], + "cvss_severities": { + "cvss_v3": { + "vector_string": null, + "score": null + }, + "cvss_v4": { + "vector_string": null, + "score": null + } + }, + "cwes": [ + + ], + "cwe_ids": [ + + ], + "credits": [ + + ], + "credits_detailed": [ + + ], + "collaborating_users": null, + "collaborating_teams": null, + "private_fork": null, + "cvss": { + "vector_string": null, + "score": null + } + }, + "repository": { + "id": 256280292, + "node_id": "MDEwOlJlcG9zaXRvcnkyNTYyODAyOTI=", + "name": "land_of_confusion", + "full_name": "pi-hole/land_of_confusion", + "private": false, + "owner": { + "login": "pi-hole", + "id": 16827203, + "node_id": "MDEyOk9yZ2FuaXphdGlvbjE2ODI3MjAz", + "avatar_url": "https://avatars.githubusercontent.com/u/16827203?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/pi-hole", + "html_url": "https://github.com/pi-hole", + "followers_url": "https://api.github.com/users/pi-hole/followers", + "following_url": "https://api.github.com/users/pi-hole/following{/other_user}", + "gists_url": "https://api.github.com/users/pi-hole/gists{/gist_id}", + "starred_url": "https://api.github.com/users/pi-hole/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/pi-hole/subscriptions", + "organizations_url": "https://api.github.com/users/pi-hole/orgs", + "repos_url": "https://api.github.com/users/pi-hole/repos", + "events_url": "https://api.github.com/users/pi-hole/events{/privacy}", + "received_events_url": "https://api.github.com/users/pi-hole/received_events", + "type": "Organization", + "user_view_type": "public", + "site_admin": false + }, + "html_url": "https://github.com/pi-hole/land_of_confusion", + "description": "Test it, break it, see what happens.", + "fork": false, + "url": "https://api.github.com/repos/pi-hole/land_of_confusion", + "forks_url": "https://api.github.com/repos/pi-hole/land_of_confusion/forks", + "keys_url": "https://api.github.com/repos/pi-hole/land_of_confusion/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/pi-hole/land_of_confusion/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/pi-hole/land_of_confusion/teams", + "hooks_url": "https://api.github.com/repos/pi-hole/land_of_confusion/hooks", + "issue_events_url": "https://api.github.com/repos/pi-hole/land_of_confusion/issues/events{/number}", + "events_url": "https://api.github.com/repos/pi-hole/land_of_confusion/events", + "assignees_url": "https://api.github.com/repos/pi-hole/land_of_confusion/assignees{/user}", + "branches_url": "https://api.github.com/repos/pi-hole/land_of_confusion/branches{/branch}", + "tags_url": "https://api.github.com/repos/pi-hole/land_of_confusion/tags", + "blobs_url": "https://api.github.com/repos/pi-hole/land_of_confusion/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/pi-hole/land_of_confusion/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/pi-hole/land_of_confusion/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/pi-hole/land_of_confusion/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/pi-hole/land_of_confusion/statuses/{sha}", + "languages_url": "https://api.github.com/repos/pi-hole/land_of_confusion/languages", + "stargazers_url": "https://api.github.com/repos/pi-hole/land_of_confusion/stargazers", + "contributors_url": "https://api.github.com/repos/pi-hole/land_of_confusion/contributors", + "subscribers_url": "https://api.github.com/repos/pi-hole/land_of_confusion/subscribers", + "subscription_url": "https://api.github.com/repos/pi-hole/land_of_confusion/subscription", + "commits_url": "https://api.github.com/repos/pi-hole/land_of_confusion/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/pi-hole/land_of_confusion/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/pi-hole/land_of_confusion/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/pi-hole/land_of_confusion/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/pi-hole/land_of_confusion/contents/{+path}", + "compare_url": "https://api.github.com/repos/pi-hole/land_of_confusion/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/pi-hole/land_of_confusion/merges", + "archive_url": "https://api.github.com/repos/pi-hole/land_of_confusion/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/pi-hole/land_of_confusion/downloads", + "issues_url": "https://api.github.com/repos/pi-hole/land_of_confusion/issues{/number}", + "pulls_url": "https://api.github.com/repos/pi-hole/land_of_confusion/pulls{/number}", + "milestones_url": "https://api.github.com/repos/pi-hole/land_of_confusion/milestones{/number}", + "notifications_url": "https://api.github.com/repos/pi-hole/land_of_confusion/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/pi-hole/land_of_confusion/labels{/name}", + "releases_url": "https://api.github.com/repos/pi-hole/land_of_confusion/releases{/id}", + "deployments_url": "https://api.github.com/repos/pi-hole/land_of_confusion/deployments", + "created_at": "2020-04-16T17:12:48Z", + "updated_at": "2025-04-15T17:09:40Z", + "pushed_at": "2024-06-15T10:53:47Z", + "git_url": "git://github.com/pi-hole/land_of_confusion.git", + "ssh_url": "git@github.com:pi-hole/land_of_confusion.git", + "clone_url": "https://github.com/pi-hole/land_of_confusion.git", + "svn_url": "https://github.com/pi-hole/land_of_confusion", + "homepage": null, + "size": 114, + "stargazers_count": 0, + "watchers_count": 0, + "language": null, + "has_issues": true, + "has_projects": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": false, + "has_discussions": true, + "forks_count": 0, + "mirror_url": null, + "archived": false, + "disabled": false, + "open_issues_count": 9, + "license": null, + "allow_forking": true, + "is_template": false, + "web_commit_signoff_required": true, + "topics": [ + + ], + "visibility": "public", + "forks": 0, + "open_issues": 9, + "watchers": 0, + "default_branch": "master", + "custom_properties": { + + } + }, + "organization": { + "login": "pi-hole", + "id": 16827203, + "node_id": "MDEyOk9yZ2FuaXphdGlvbjE2ODI3MjAz", + "url": "https://api.github.com/orgs/pi-hole", + "repos_url": "https://api.github.com/orgs/pi-hole/repos", + "events_url": "https://api.github.com/orgs/pi-hole/events", + "hooks_url": "https://api.github.com/orgs/pi-hole/hooks", + "issues_url": "https://api.github.com/orgs/pi-hole/issues", + "members_url": "https://api.github.com/orgs/pi-hole/members{/member}", + "public_members_url": "https://api.github.com/orgs/pi-hole/public_members{/member}", + "avatar_url": "https://avatars.githubusercontent.com/u/16827203?v=4", + "description": "A black hole for Internet advertisements" + }, + "sender": { + "login": "PromoFaux", + "id": 1998970, + "node_id": "MDQ6VXNlcjE5OTg5NzA=", + "avatar_url": "https://avatars.githubusercontent.com/u/1998970?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/PromoFaux", + "html_url": "https://github.com/PromoFaux", + "followers_url": "https://api.github.com/users/PromoFaux/followers", + "following_url": "https://api.github.com/users/PromoFaux/following{/other_user}", + "gists_url": "https://api.github.com/users/PromoFaux/gists{/gist_id}", + "starred_url": "https://api.github.com/users/PromoFaux/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/PromoFaux/subscriptions", + "organizations_url": "https://api.github.com/users/PromoFaux/orgs", + "repos_url": "https://api.github.com/users/PromoFaux/repos", + "events_url": "https://api.github.com/users/PromoFaux/events{/privacy}", + "received_events_url": "https://api.github.com/users/PromoFaux/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + } + } \ No newline at end of file diff --git a/test/Octokit.Webhooks.Test/Resources/repository_advisory/reported.payload.json b/test/Octokit.Webhooks.Test/Resources/repository_advisory/reported.payload.json new file mode 100644 index 00000000..5a527601 --- /dev/null +++ b/test/Octokit.Webhooks.Test/Resources/repository_advisory/reported.payload.json @@ -0,0 +1,210 @@ +{ + "action": "reported", + "repository_advisory": { + "ghsa_id": "GHSA-hv58-4hqr-7vxj", + "cve_id": null, + "url": "https://api.github.com/repos/pi-hole/land_of_confusion/security-advisories/GHSA-hv58-4hqr-7vxj", + "html_url": "https://github.com/pi-hole/land_of_confusion/security/advisories/GHSA-hv58-4hqr-7vxj", + "summary": "Test", + "description": "Testing from an account that doesn't have write access", + "severity": "low", + "author": null, + "publisher": null, + "identifiers": [ + { + "value": "GHSA-hv58-4hqr-7vxj", + "type": "GHSA" + } + ], + "state": "triage", + "created_at": null, + "updated_at": "2025-04-15T17:22:36Z", + "published_at": null, + "closed_at": null, + "withdrawn_at": null, + "submission": null, + "vulnerabilities": [ + { + "package": { + "ecosystem": "", + "name": "" + }, + "vulnerable_version_range": "<0", + "patched_versions": ">0", + "vulnerable_functions": [ + + ] + } + ], + "cvss_severities": { + "cvss_v3": { + "vector_string": null, + "score": null + }, + "cvss_v4": { + "vector_string": null, + "score": null + } + }, + "cwes": [ + + ], + "cwe_ids": [ + + ], + "credits": [ + + ], + "credits_detailed": [ + + ], + "collaborating_users": null, + "collaborating_teams": null, + "private_fork": null, + "cvss": { + "vector_string": null, + "score": null + } + }, + "repository": { + "id": 256280292, + "node_id": "MDEwOlJlcG9zaXRvcnkyNTYyODAyOTI=", + "name": "land_of_confusion", + "full_name": "pi-hole/land_of_confusion", + "private": false, + "owner": { + "login": "pi-hole", + "id": 16827203, + "node_id": "MDEyOk9yZ2FuaXphdGlvbjE2ODI3MjAz", + "avatar_url": "https://avatars.githubusercontent.com/u/16827203?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/pi-hole", + "html_url": "https://github.com/pi-hole", + "followers_url": "https://api.github.com/users/pi-hole/followers", + "following_url": "https://api.github.com/users/pi-hole/following{/other_user}", + "gists_url": "https://api.github.com/users/pi-hole/gists{/gist_id}", + "starred_url": "https://api.github.com/users/pi-hole/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/pi-hole/subscriptions", + "organizations_url": "https://api.github.com/users/pi-hole/orgs", + "repos_url": "https://api.github.com/users/pi-hole/repos", + "events_url": "https://api.github.com/users/pi-hole/events{/privacy}", + "received_events_url": "https://api.github.com/users/pi-hole/received_events", + "type": "Organization", + "user_view_type": "public", + "site_admin": false + }, + "html_url": "https://github.com/pi-hole/land_of_confusion", + "description": "Test it, break it, see what happens.", + "fork": false, + "url": "https://api.github.com/repos/pi-hole/land_of_confusion", + "forks_url": "https://api.github.com/repos/pi-hole/land_of_confusion/forks", + "keys_url": "https://api.github.com/repos/pi-hole/land_of_confusion/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/pi-hole/land_of_confusion/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/pi-hole/land_of_confusion/teams", + "hooks_url": "https://api.github.com/repos/pi-hole/land_of_confusion/hooks", + "issue_events_url": "https://api.github.com/repos/pi-hole/land_of_confusion/issues/events{/number}", + "events_url": "https://api.github.com/repos/pi-hole/land_of_confusion/events", + "assignees_url": "https://api.github.com/repos/pi-hole/land_of_confusion/assignees{/user}", + "branches_url": "https://api.github.com/repos/pi-hole/land_of_confusion/branches{/branch}", + "tags_url": "https://api.github.com/repos/pi-hole/land_of_confusion/tags", + "blobs_url": "https://api.github.com/repos/pi-hole/land_of_confusion/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/pi-hole/land_of_confusion/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/pi-hole/land_of_confusion/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/pi-hole/land_of_confusion/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/pi-hole/land_of_confusion/statuses/{sha}", + "languages_url": "https://api.github.com/repos/pi-hole/land_of_confusion/languages", + "stargazers_url": "https://api.github.com/repos/pi-hole/land_of_confusion/stargazers", + "contributors_url": "https://api.github.com/repos/pi-hole/land_of_confusion/contributors", + "subscribers_url": "https://api.github.com/repos/pi-hole/land_of_confusion/subscribers", + "subscription_url": "https://api.github.com/repos/pi-hole/land_of_confusion/subscription", + "commits_url": "https://api.github.com/repos/pi-hole/land_of_confusion/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/pi-hole/land_of_confusion/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/pi-hole/land_of_confusion/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/pi-hole/land_of_confusion/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/pi-hole/land_of_confusion/contents/{+path}", + "compare_url": "https://api.github.com/repos/pi-hole/land_of_confusion/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/pi-hole/land_of_confusion/merges", + "archive_url": "https://api.github.com/repos/pi-hole/land_of_confusion/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/pi-hole/land_of_confusion/downloads", + "issues_url": "https://api.github.com/repos/pi-hole/land_of_confusion/issues{/number}", + "pulls_url": "https://api.github.com/repos/pi-hole/land_of_confusion/pulls{/number}", + "milestones_url": "https://api.github.com/repos/pi-hole/land_of_confusion/milestones{/number}", + "notifications_url": "https://api.github.com/repos/pi-hole/land_of_confusion/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/pi-hole/land_of_confusion/labels{/name}", + "releases_url": "https://api.github.com/repos/pi-hole/land_of_confusion/releases{/id}", + "deployments_url": "https://api.github.com/repos/pi-hole/land_of_confusion/deployments", + "created_at": "2020-04-16T17:12:48Z", + "updated_at": "2025-04-15T17:09:40Z", + "pushed_at": "2024-06-15T10:53:47Z", + "git_url": "git://github.com/pi-hole/land_of_confusion.git", + "ssh_url": "git@github.com:pi-hole/land_of_confusion.git", + "clone_url": "https://github.com/pi-hole/land_of_confusion.git", + "svn_url": "https://github.com/pi-hole/land_of_confusion", + "homepage": null, + "size": 114, + "stargazers_count": 0, + "watchers_count": 0, + "language": null, + "has_issues": true, + "has_projects": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": false, + "has_discussions": true, + "forks_count": 0, + "mirror_url": null, + "archived": false, + "disabled": false, + "open_issues_count": 9, + "license": null, + "allow_forking": true, + "is_template": false, + "web_commit_signoff_required": true, + "topics": [ + + ], + "visibility": "public", + "forks": 0, + "open_issues": 9, + "watchers": 0, + "default_branch": "master", + "custom_properties": { + + } + }, + "organization": { + "login": "pi-hole", + "id": 16827203, + "node_id": "MDEyOk9yZ2FuaXphdGlvbjE2ODI3MjAz", + "url": "https://api.github.com/orgs/pi-hole", + "repos_url": "https://api.github.com/orgs/pi-hole/repos", + "events_url": "https://api.github.com/orgs/pi-hole/events", + "hooks_url": "https://api.github.com/orgs/pi-hole/hooks", + "issues_url": "https://api.github.com/orgs/pi-hole/issues", + "members_url": "https://api.github.com/orgs/pi-hole/members{/member}", + "public_members_url": "https://api.github.com/orgs/pi-hole/public_members{/member}", + "avatar_url": "https://avatars.githubusercontent.com/u/16827203?v=4", + "description": "A black hole for Internet advertisements" + }, + "sender": { + "login": "promofaux2", + "id": 207756468, + "node_id": "U_kgDODGIctA", + "avatar_url": "https://avatars.githubusercontent.com/u/207756468?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/promofaux2", + "html_url": "https://github.com/promofaux2", + "followers_url": "https://api.github.com/users/promofaux2/followers", + "following_url": "https://api.github.com/users/promofaux2/following{/other_user}", + "gists_url": "https://api.github.com/users/promofaux2/gists{/gist_id}", + "starred_url": "https://api.github.com/users/promofaux2/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/promofaux2/subscriptions", + "organizations_url": "https://api.github.com/users/promofaux2/orgs", + "repos_url": "https://api.github.com/users/promofaux2/repos", + "events_url": "https://api.github.com/users/promofaux2/events{/privacy}", + "received_events_url": "https://api.github.com/users/promofaux2/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + } + } \ No newline at end of file