diff --git a/Gitea.Declarative.Lib/ConfigSchema.fs b/Gitea.Declarative.Lib/ConfigSchema.fs index e68d706..7ca0a08 100644 --- a/Gitea.Declarative.Lib/ConfigSchema.fs +++ b/Gitea.Declarative.Lib/ConfigSchema.fs @@ -212,6 +212,7 @@ type GitHubRepo = type Repo = { Description : string + Deleted : bool option GitHub : GitHubRepo option Native : NativeRepo option } @@ -232,6 +233,7 @@ type Repo = } |> Some Native = None + Deleted = None } |> async.Return else @@ -259,6 +261,7 @@ type Repo = { Description = u.Description + Deleted = None GitHub = None Native = { @@ -308,6 +311,7 @@ type Repo = Repo.Description = s.Description GitHub = Option.ofNullable s.GitHub |> Option.map GitHubRepo.OfSerialised Native = s.Native |> Option.ofNullable |> Option.map NativeRepo.OfSerialised + Deleted = s.Deleted |> Option.ofNullable } member internal this.ToSerialised () : SerialisedRepo = @@ -321,6 +325,10 @@ type Repo = match this.Native with | None -> Nullable () | Some native -> Nullable (native.ToSerialised ()) + Deleted = + match this.Deleted with + | None -> Nullable () + | Some v -> Nullable v } type UserInfoUpdate = diff --git a/Gitea.Declarative.Lib/Gitea.fs b/Gitea.Declarative.Lib/Gitea.fs index 956e043..a176fb0 100644 --- a/Gitea.Declarative.Lib/Gitea.fs +++ b/Gitea.Declarative.Lib/Gitea.fs @@ -67,6 +67,7 @@ module Gitea = // TODO: check whether mirrors are out of sync e.g. in Public/Private status let checkRepos + (logger : ILogger) (config : GiteaConfig) (client : Gitea.Client) : Async>>>> @@ -115,7 +116,17 @@ module Gitea = |> Map.toSeq |> Seq.choose (fun (repo, desired) -> match Map.tryFind repo actualRepos with - | None -> Some (repo, AlignmentError.DoesNotExist desired) + | None -> + if desired.Deleted = Some true then + logger.LogInformation ( + "The repo {User}:{Repo} is configured as Deleted, and is absent from the server. Remove this repo from configuration.", + user, + let (RepoName repo) = repo in repo + ) + + None + else + Some (repo, AlignmentError.DoesNotExist desired) | Some actual -> if desired <> actual then (repo, AlignmentError.ConfigurationDiffers (desired, actual)) |> Some @@ -146,7 +157,15 @@ module Gitea = (repoName : string) (desired : Repo) (actual : Repo) + : Async = + if desired.Deleted = Some true then + async { + logger.LogWarning ("Deleting repo {User}:{Repo}", user, repoName) + return! Async.AwaitTask (client.RepoDelete (user, repoName)) + } + else + match desired.GitHub, actual.GitHub with | None, Some gitHub -> async { @@ -585,7 +604,7 @@ module Gitea = | AlignmentError.UnexpectedlyPresent -> async { logger.LogError ( - "For safety, refusing to delete unexpectedly present repo: {User}, {Repo}", + "In the absence of the `deleted: true` configuration, refusing to delete unexpectedly present repo: {User}, {Repo}", user, r ) diff --git a/Gitea.Declarative.Lib/GiteaConfig.schema.json b/Gitea.Declarative.Lib/GiteaConfig.schema.json index 098d73c..6fa2bbb 100644 --- a/Gitea.Declarative.Lib/GiteaConfig.schema.json +++ b/Gitea.Declarative.Lib/GiteaConfig.schema.json @@ -82,6 +82,13 @@ "$ref": "#/definitions/SerialisedNativeRepo" } ] + }, + "deleted": { + "type": [ + "boolean", + "null" + ], + "description": "Set this to true to delete the repo. dotnet-gitea-declarative will refuse to delete any repo that is absent from configuration; the workflow is to first set its `deleted` to `true` (whereupon dotnet-gitea-declarative will delete it from Gitea) and then to delete it from configuration." } }, "oneOf": [ diff --git a/Gitea.Declarative.Lib/SerialisedConfigSchema.fs b/Gitea.Declarative.Lib/SerialisedConfigSchema.fs index 3de2901..fab9f23 100644 --- a/Gitea.Declarative.Lib/SerialisedConfigSchema.fs +++ b/Gitea.Declarative.Lib/SerialisedConfigSchema.fs @@ -117,6 +117,9 @@ type internal SerialisedRepo = [] [] Native : Nullable + [] + [] + Deleted : Nullable } [] diff --git a/Gitea.Declarative/Program.fs b/Gitea.Declarative/Program.fs index 7514f63..10253f9 100644 --- a/Gitea.Declarative/Program.fs +++ b/Gitea.Declarative/Program.fs @@ -99,7 +99,7 @@ module Program = ) logger.LogInformation "Checking repos..." - let! repoErrors = Gitea.checkRepos config client + let! repoErrors = Gitea.checkRepos logger config client match repoErrors, args.DryRun with | Ok (), _ -> ()