mirror of
https://github.com/Smaug123/gitea-repo-config
synced 2025-10-07 00:18:40 +00:00
Allow multiple push mirrors (#97)
This commit is contained in:
@@ -27,14 +27,28 @@ type MergeStyle =
|
|||||||
|
|
||||||
static member toString (m : MergeStyle) = m.ToString ()
|
static member toString (m : MergeStyle) = m.ToString ()
|
||||||
|
|
||||||
|
[<NoComparison>]
|
||||||
|
[<CustomEquality>]
|
||||||
type PushMirror =
|
type PushMirror =
|
||||||
{
|
{
|
||||||
GitHubAddress : Uri
|
GitHubAddress : Uri
|
||||||
|
/// Gitea should always tell us a remote name, but a user in their config can't.
|
||||||
|
RemoteName : string option
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Equality check ignores remote names, which are not known to the user but which Gitea tracks internally.
|
||||||
|
override this.Equals (other : obj) : bool =
|
||||||
|
match other with
|
||||||
|
| :? PushMirror as other -> this.GitHubAddress.ToString () = other.GitHubAddress.ToString ()
|
||||||
|
| _ -> false
|
||||||
|
|
||||||
|
override this.GetHashCode () : int =
|
||||||
|
this.GitHubAddress.ToString().GetHashCode ()
|
||||||
|
|
||||||
static member OfSerialised (s : SerialisedPushMirror) : PushMirror =
|
static member OfSerialised (s : SerialisedPushMirror) : PushMirror =
|
||||||
{
|
{
|
||||||
GitHubAddress = Uri s.GitHubAddress
|
GitHubAddress = Uri s.GitHubAddress
|
||||||
|
RemoteName = None
|
||||||
}
|
}
|
||||||
|
|
||||||
member this.ToSerialised () : SerialisedPushMirror =
|
member this.ToSerialised () : SerialisedPushMirror =
|
||||||
@@ -82,7 +96,7 @@ type NativeRepo =
|
|||||||
AllowRebase : bool option
|
AllowRebase : bool option
|
||||||
AllowRebaseExplicit : bool option
|
AllowRebaseExplicit : bool option
|
||||||
AllowMergeCommits : bool option
|
AllowMergeCommits : bool option
|
||||||
Mirror : PushMirror option
|
Mirrors : PushMirror list
|
||||||
ProtectedBranches : ProtectedBranch Set
|
ProtectedBranches : ProtectedBranch Set
|
||||||
Collaborators : string Set
|
Collaborators : string Set
|
||||||
}
|
}
|
||||||
@@ -103,7 +117,7 @@ type NativeRepo =
|
|||||||
AllowRebase = Some false
|
AllowRebase = Some false
|
||||||
AllowRebaseExplicit = Some false
|
AllowRebaseExplicit = Some false
|
||||||
AllowMergeCommits = Some false
|
AllowMergeCommits = Some false
|
||||||
Mirror = None
|
Mirrors = []
|
||||||
ProtectedBranches = Set.empty
|
ProtectedBranches = Set.empty
|
||||||
Collaborators = Set.empty
|
Collaborators = Set.empty
|
||||||
}
|
}
|
||||||
@@ -128,7 +142,7 @@ type NativeRepo =
|
|||||||
AllowRebase = this.AllowRebase |> Option.orElse NativeRepo.Default.AllowRebase
|
AllowRebase = this.AllowRebase |> Option.orElse NativeRepo.Default.AllowRebase
|
||||||
AllowRebaseExplicit = this.AllowRebaseExplicit |> Option.orElse NativeRepo.Default.AllowRebaseExplicit
|
AllowRebaseExplicit = this.AllowRebaseExplicit |> Option.orElse NativeRepo.Default.AllowRebaseExplicit
|
||||||
AllowMergeCommits = this.AllowMergeCommits |> Option.orElse NativeRepo.Default.AllowMergeCommits
|
AllowMergeCommits = this.AllowMergeCommits |> Option.orElse NativeRepo.Default.AllowMergeCommits
|
||||||
Mirror = this.Mirror
|
Mirrors = this.Mirrors
|
||||||
ProtectedBranches = this.ProtectedBranches // TODO should this replace null with empty?
|
ProtectedBranches = this.ProtectedBranches // TODO should this replace null with empty?
|
||||||
Collaborators = this.Collaborators
|
Collaborators = this.Collaborators
|
||||||
}
|
}
|
||||||
@@ -149,7 +163,12 @@ type NativeRepo =
|
|||||||
AllowRebase = s.AllowRebase |> Option.ofNullable
|
AllowRebase = s.AllowRebase |> Option.ofNullable
|
||||||
AllowRebaseExplicit = s.AllowRebaseExplicit |> Option.ofNullable
|
AllowRebaseExplicit = s.AllowRebaseExplicit |> Option.ofNullable
|
||||||
AllowMergeCommits = s.AllowMergeCommits |> Option.ofNullable
|
AllowMergeCommits = s.AllowMergeCommits |> Option.ofNullable
|
||||||
Mirror = s.Mirror |> Option.ofNullable |> Option.map PushMirror.OfSerialised
|
Mirrors =
|
||||||
|
s.Mirrors
|
||||||
|
|> Option.ofObj
|
||||||
|
|> Option.defaultValue [||]
|
||||||
|
|> List.ofArray
|
||||||
|
|> List.map PushMirror.OfSerialised
|
||||||
ProtectedBranches =
|
ProtectedBranches =
|
||||||
match s.ProtectedBranches with
|
match s.ProtectedBranches with
|
||||||
| null -> Set.empty
|
| null -> Set.empty
|
||||||
@@ -179,10 +198,7 @@ type NativeRepo =
|
|||||||
AllowRebase = this.AllowRebase |> Option.toNullable
|
AllowRebase = this.AllowRebase |> Option.toNullable
|
||||||
AllowRebaseExplicit = this.AllowRebaseExplicit |> Option.toNullable
|
AllowRebaseExplicit = this.AllowRebaseExplicit |> Option.toNullable
|
||||||
AllowMergeCommits = this.AllowMergeCommits |> Option.toNullable
|
AllowMergeCommits = this.AllowMergeCommits |> Option.toNullable
|
||||||
Mirror =
|
Mirrors = this.Mirrors |> List.toArray |> Array.map (fun a -> a.ToSerialised ())
|
||||||
match this.Mirror with
|
|
||||||
| None -> Nullable ()
|
|
||||||
| Some mirror -> Nullable (mirror.ToSerialised ())
|
|
||||||
ProtectedBranches = this.ProtectedBranches |> Seq.map (fun b -> b.ToSerialised ()) |> Array.ofSeq
|
ProtectedBranches = this.ProtectedBranches |> Seq.map (fun b -> b.ToSerialised ()) |> Array.ofSeq
|
||||||
Collaborators = Set.toArray this.Collaborators
|
Collaborators = Set.toArray this.Collaborators
|
||||||
}
|
}
|
||||||
@@ -239,16 +255,17 @@ type Repo =
|
|||||||
}
|
}
|
||||||
|> async.Return
|
|> async.Return
|
||||||
else
|
else
|
||||||
async {
|
let repoFullName = u.FullName
|
||||||
let! mirror =
|
|
||||||
getAllPaginated (fun page count ->
|
|
||||||
client.RepoListPushMirrors (u.Owner.LoginName, u.FullName, Some page, Some count)
|
|
||||||
)
|
|
||||||
|
|
||||||
let mirror =
|
async {
|
||||||
if mirror.Length = 0 then None
|
let owner = u.Owner
|
||||||
elif mirror.Length = 1 then Some mirror.[0]
|
|
||||||
else failwith "Multiple mirrors not supported yet"
|
let loginName = owner.LoginName
|
||||||
|
|
||||||
|
let! mirrors =
|
||||||
|
getAllPaginated (fun page count ->
|
||||||
|
client.RepoListPushMirrors (loginName, repoFullName, Some page, Some count)
|
||||||
|
)
|
||||||
|
|
||||||
let! (branchProtections : Gitea.BranchProtection[]) =
|
let! (branchProtections : Gitea.BranchProtection[]) =
|
||||||
client.RepoListBranchProtection (u.Owner.LoginName, u.FullName)
|
client.RepoListBranchProtection (u.Owner.LoginName, u.FullName)
|
||||||
@@ -259,16 +276,23 @@ type Repo =
|
|||||||
client.RepoListCollaborators (u.Owner.LoginName, u.FullName, Some page, Some count)
|
client.RepoListCollaborators (u.Owner.LoginName, u.FullName, Some page, Some count)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
let defaultBranch = u.DefaultBranch
|
||||||
|
|
||||||
|
let collaborators =
|
||||||
|
collaborators |> Seq.map (fun user -> user.LoginName) |> Set.ofSeq
|
||||||
|
|
||||||
|
let description = u.Description
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
{
|
{
|
||||||
Description = u.Description
|
Description = description
|
||||||
Deleted = None
|
Deleted = None
|
||||||
GitHub = None
|
GitHub = None
|
||||||
Native =
|
Native =
|
||||||
{
|
{
|
||||||
Private = u.Private
|
Private = u.Private
|
||||||
DefaultBranch = u.DefaultBranch
|
DefaultBranch = defaultBranch
|
||||||
IgnoreWhitespaceConflicts = u.IgnoreWhitespaceConflicts
|
IgnoreWhitespaceConflicts = u.IgnoreWhitespaceConflicts
|
||||||
HasPullRequests = u.HasPullRequests
|
HasPullRequests = u.HasPullRequests
|
||||||
HasProjects = u.HasProjects
|
HasProjects = u.HasProjects
|
||||||
@@ -281,11 +305,13 @@ type Repo =
|
|||||||
AllowRebase = u.AllowRebase
|
AllowRebase = u.AllowRebase
|
||||||
AllowRebaseExplicit = u.AllowRebaseExplicit
|
AllowRebaseExplicit = u.AllowRebaseExplicit
|
||||||
AllowMergeCommits = u.AllowMergeCommits
|
AllowMergeCommits = u.AllowMergeCommits
|
||||||
Mirror =
|
Mirrors =
|
||||||
mirror
|
mirrors
|
||||||
|> Option.map (fun m ->
|
|> Array.toList
|
||||||
|
|> List.map (fun m ->
|
||||||
{
|
{
|
||||||
GitHubAddress = Uri m.RemoteAddress
|
GitHubAddress = Uri m.RemoteAddress
|
||||||
|
RemoteName = Some m.RemoteName
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
ProtectedBranches =
|
ProtectedBranches =
|
||||||
@@ -302,7 +328,7 @@ type Repo =
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|> Set.ofSeq
|
|> Set.ofSeq
|
||||||
Collaborators = collaborators |> Seq.map (fun user -> user.LoginName) |> Set.ofSeq
|
Collaborators = collaborators
|
||||||
}
|
}
|
||||||
|> Some
|
|> Some
|
||||||
}
|
}
|
||||||
|
@@ -361,34 +361,134 @@ module Gitea =
|
|||||||
else
|
else
|
||||||
async.Return ()
|
async.Return ()
|
||||||
|
|
||||||
|
// Push mirrors
|
||||||
do!
|
do!
|
||||||
match desired.Mirror, actual.Mirror with
|
let desired =
|
||||||
| None, None -> async.Return ()
|
desired.Mirrors
|
||||||
| None, Some m ->
|
|> List.groupBy (fun m -> (m.GitHubAddress : Uri).ToString ())
|
||||||
async { logger.LogError ("Refusing to delete push mirror for {User}:{Repo}", user, repoName) }
|
|> Map.ofList
|
||||||
| Some desired, None ->
|
|
||||||
match githubApiToken with
|
|
||||||
| None ->
|
|
||||||
async {
|
|
||||||
logger.LogCritical (
|
|
||||||
"Cannot add push mirror for {User}:{Repo} due to lack of GitHub API token",
|
|
||||||
user,
|
|
||||||
repoName
|
|
||||||
)
|
|
||||||
}
|
|
||||||
| Some token ->
|
|
||||||
async {
|
|
||||||
logger.LogInformation ("Setting up push mirror on {User}:{Repo}", user, repoName)
|
|
||||||
let pushMirrorOption = createPushMirrorOption desired.GitHubAddress token
|
|
||||||
let! _ = client.RepoAddPushMirror (user, repoName, pushMirrorOption) |> Async.AwaitTask
|
|
||||||
return ()
|
|
||||||
}
|
|
||||||
| Some desired, Some actual ->
|
|
||||||
if desired <> actual then
|
|
||||||
async { logger.LogCritical ("Push mirror on {User}:{Repo} differs.", user, repoName) }
|
|
||||||
else
|
|
||||||
async.Return ()
|
|
||||||
|
|
||||||
|
let desired =
|
||||||
|
desired
|
||||||
|
|> Map.toSeq
|
||||||
|
|> Seq.map (fun (name, pm) ->
|
||||||
|
match pm with
|
||||||
|
| [] -> failwith "LOGIC ERROR"
|
||||||
|
| [ pm ] -> pm.GitHubAddress.ToString ()
|
||||||
|
| _ ->
|
||||||
|
failwith
|
||||||
|
$"Config validation failed on repo %s{repoName}: multiple push mirrors configured for target %s{name}"
|
||||||
|
)
|
||||||
|
|> Set.ofSeq
|
||||||
|
|
||||||
|
let actual =
|
||||||
|
actual.Mirrors
|
||||||
|
|> List.groupBy (fun m -> (m.GitHubAddress : Uri).ToString ())
|
||||||
|
|> Map.ofList
|
||||||
|
|
||||||
|
// If any mirror target has multiple push mirrors for it, just delete them all before continuing.
|
||||||
|
let deleteExisting =
|
||||||
|
actual
|
||||||
|
|> Map.toSeq
|
||||||
|
|> Seq.choose (fun (k, vs) ->
|
||||||
|
match vs with
|
||||||
|
| [] -> failwith "LOGIC ERROR"
|
||||||
|
| [ _ ] -> None
|
||||||
|
| vs ->
|
||||||
|
vs
|
||||||
|
|> List.map (fun pm ->
|
||||||
|
async {
|
||||||
|
logger.LogWarning (
|
||||||
|
"Multiple push mirrors on repo {Owner}/{RepoName} for target {PushMirrorTarget} found. Deleting them all before recreating.",
|
||||||
|
user,
|
||||||
|
repoName,
|
||||||
|
k
|
||||||
|
)
|
||||||
|
|
||||||
|
let! ct = Async.CancellationToken
|
||||||
|
// sigh, domain model - it's *such* a faff to represent this correctly though
|
||||||
|
do!
|
||||||
|
client.RepoDeletePushMirror (user, repoName, Option.get pm.RemoteName)
|
||||||
|
|> Async.AwaitTask
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|> Async.Sequential
|
||||||
|
|> Async.map (Array.iter id)
|
||||||
|
|> Some
|
||||||
|
)
|
||||||
|
|> Seq.toList
|
||||||
|
|
||||||
|
let actual =
|
||||||
|
match deleteExisting with
|
||||||
|
| [] -> actual
|
||||||
|
| _ -> Map.empty
|
||||||
|
|
||||||
|
let distinctActual = actual.Keys |> Set.ofSeq
|
||||||
|
let presentButNotDesired = Set.difference distinctActual desired
|
||||||
|
let desiredButNotPresent = Set.difference desired distinctActual
|
||||||
|
|
||||||
|
let deleteUndesired =
|
||||||
|
presentButNotDesired
|
||||||
|
|> Seq.map (fun toDelete ->
|
||||||
|
logger.LogWarning (
|
||||||
|
"Deleting push mirror on repo {Owner}/{RepoName} for target {PushMirrorTarget}",
|
||||||
|
user,
|
||||||
|
repoName,
|
||||||
|
toDelete
|
||||||
|
)
|
||||||
|
|
||||||
|
let toDelete = actual.[toDelete]
|
||||||
|
|
||||||
|
toDelete
|
||||||
|
|> Seq.map (fun pm ->
|
||||||
|
async {
|
||||||
|
let! ct = Async.CancellationToken
|
||||||
|
|
||||||
|
do!
|
||||||
|
client.RepoDeletePushMirror (user, repoName, Option.get pm.RemoteName)
|
||||||
|
|> Async.AwaitTask
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|> Async.Sequential
|
||||||
|
|> Async.map (Array.iter id)
|
||||||
|
)
|
||||||
|
|> Seq.toList
|
||||||
|
|
||||||
|
let addDesired =
|
||||||
|
desiredButNotPresent
|
||||||
|
|> Seq.map (fun toAdd ->
|
||||||
|
match githubApiToken with
|
||||||
|
| None ->
|
||||||
|
async {
|
||||||
|
logger.LogCritical (
|
||||||
|
"Cannot add push mirror for {User}:{Repo} due to lack of GitHub API token",
|
||||||
|
user,
|
||||||
|
repoName
|
||||||
|
)
|
||||||
|
}
|
||||||
|
| Some token ->
|
||||||
|
async {
|
||||||
|
logger.LogInformation ("Setting up push mirror on {User}:{Repo}", user, repoName)
|
||||||
|
let! ct = Async.CancellationToken
|
||||||
|
let pushMirrorOption = createPushMirrorOption (Uri toAdd) token
|
||||||
|
|
||||||
|
let! _ = client.RepoAddPushMirror (user, repoName, pushMirrorOption) |> Async.AwaitTask
|
||||||
|
|
||||||
|
return ()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|> Seq.toList
|
||||||
|
|
||||||
|
if deleteExisting.IsEmpty && deleteUndesired.IsEmpty && addDesired.IsEmpty then
|
||||||
|
async.Return ()
|
||||||
|
else
|
||||||
|
async {
|
||||||
|
do! deleteExisting |> Async.Sequential |> Async.map (Array.iter id)
|
||||||
|
do! deleteUndesired |> Async.Sequential |> Async.map (Array.iter id)
|
||||||
|
do! addDesired |> Async.Sequential |> Async.map (Array.iter id)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Collaborators
|
||||||
do!
|
do!
|
||||||
let desiredButNotPresent = Set.difference desired.Collaborators actual.Collaborators
|
let desiredButNotPresent = Set.difference desired.Collaborators actual.Collaborators
|
||||||
let presentButNotDesired = Set.difference actual.Collaborators desired.Collaborators
|
let presentButNotDesired = Set.difference actual.Collaborators desired.Collaborators
|
||||||
@@ -547,30 +647,44 @@ module Gitea =
|
|||||||
| Choice2Of2 e -> raise (AggregateException ($"Error creating {user}:{r}", e))
|
| Choice2Of2 e -> raise (AggregateException ($"Error creating {user}:{r}", e))
|
||||||
| Choice1Of2 _ -> ()
|
| Choice1Of2 _ -> ()
|
||||||
|
|
||||||
match native.Mirror, githubApiToken with
|
match native.Mirrors, githubApiToken with
|
||||||
| None, _ -> ()
|
| [], _ -> ()
|
||||||
| Some mirror, None -> failwith "Cannot push to GitHub mirror with an API key"
|
| _ :: _, None -> failwith "Cannot push to GitHub mirror without an API key"
|
||||||
| Some mirror, Some token ->
|
| mirrors, Some token ->
|
||||||
logger.LogInformation ("Setting up push mirror for {User}:{Repo}", user, r)
|
logger.LogInformation ("Setting up push mirror for {User}:{Repo}", user, r)
|
||||||
let options = Gitea.CreatePushMirrorOption ()
|
|
||||||
options.SyncOnCommit <- Some true
|
|
||||||
options.RemoteAddress <- (mirror.GitHubAddress : Uri).ToString ()
|
|
||||||
options.RemoteUsername <- token
|
|
||||||
options.RemotePassword <- token
|
|
||||||
options.Interval <- "8h0m0s"
|
|
||||||
|
|
||||||
let! mirrors =
|
let! actualMirrors =
|
||||||
getAllPaginated (fun page count ->
|
getAllPaginated (fun page count ->
|
||||||
client.RepoListPushMirrors (user, r, Some page, Some count)
|
client.RepoListPushMirrors (user, r, Some page, Some count)
|
||||||
)
|
)
|
||||||
|
|
||||||
match mirrors |> Array.tryFind (fun m -> m.RemoteAddress = options.RemoteAddress) with
|
do!
|
||||||
| None ->
|
mirrors
|
||||||
let! _ = client.RepoAddPushMirror (user, r, options) |> Async.AwaitTask
|
|> List.map (fun mirror ->
|
||||||
()
|
let options = Gitea.CreatePushMirrorOption ()
|
||||||
| Some existing ->
|
options.SyncOnCommit <- Some true
|
||||||
if existing.SyncOnCommit <> Some true then
|
options.RemoteAddress <- (mirror.GitHubAddress : Uri).ToString ()
|
||||||
failwith $"sync on commit should have been true for {user}:{r}"
|
options.RemoteUsername <- token
|
||||||
|
options.RemotePassword <- token
|
||||||
|
options.Interval <- "8h0m0s"
|
||||||
|
|
||||||
|
async {
|
||||||
|
match
|
||||||
|
actualMirrors
|
||||||
|
|> Array.tryFind (fun m -> m.RemoteAddress = options.RemoteAddress)
|
||||||
|
with
|
||||||
|
| None ->
|
||||||
|
let! _ =
|
||||||
|
client.RepoAddPushMirror (user, r, options) |> Async.AwaitTask
|
||||||
|
|
||||||
|
()
|
||||||
|
| Some existing ->
|
||||||
|
if existing.SyncOnCommit <> Some true then
|
||||||
|
failwith $"sync on commit should have been true for {user}:{r}"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|> Async.Sequential
|
||||||
|
|> Async.map (Array.iter id)
|
||||||
|
|
||||||
()
|
()
|
||||||
| Some github, None ->
|
| Some github, None ->
|
||||||
|
@@ -188,13 +188,12 @@
|
|||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "either `true` to allow merging pull requests with a merge commit, or `false` to prevent merging pull requests with merge commits."
|
"description": "either `true` to allow merging pull requests with a merge commit, or `false` to prevent merging pull requests with merge commits."
|
||||||
},
|
},
|
||||||
"mirror": {
|
"mirrors": {
|
||||||
"description": "Configure a GitHub push mirror to sync this repo to",
|
"type": "array",
|
||||||
"oneOf": [
|
"description": "Configure GitHub push mirrors to sync this repo to",
|
||||||
{
|
"items": {
|
||||||
"$ref": "#/definitions/SerialisedPushMirror"
|
"$ref": "#/definitions/SerialisedPushMirror"
|
||||||
}
|
}
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"protectedBranches": {
|
"protectedBranches": {
|
||||||
"type": [
|
"type": [
|
||||||
|
@@ -81,8 +81,8 @@ type internal SerialisedNativeRepo =
|
|||||||
[<Description "either `true` to allow merging pull requests with a merge commit, or `false` to prevent merging pull requests with merge commits.">]
|
[<Description "either `true` to allow merging pull requests with a merge commit, or `false` to prevent merging pull requests with merge commits.">]
|
||||||
AllowMergeCommits : Nullable<bool>
|
AllowMergeCommits : Nullable<bool>
|
||||||
[<JsonProperty(Required = Required.DisallowNull)>]
|
[<JsonProperty(Required = Required.DisallowNull)>]
|
||||||
[<Description "Configure a GitHub push mirror to sync this repo to">]
|
[<Description "Configure GitHub push mirrors to sync this repo to">]
|
||||||
Mirror : Nullable<SerialisedPushMirror>
|
Mirrors : SerialisedPushMirror[]
|
||||||
[<JsonProperty(Required = Required.Default)>]
|
[<JsonProperty(Required = Required.Default)>]
|
||||||
[<Description "Protected branch configuration">]
|
[<Description "Protected branch configuration">]
|
||||||
ProtectedBranches : SerialisedProtectedBranch array
|
ProtectedBranches : SerialisedProtectedBranch array
|
||||||
|
@@ -38,9 +38,11 @@
|
|||||||
"native": {
|
"native": {
|
||||||
"defaultBranch": "main",
|
"defaultBranch": "main",
|
||||||
"private": false,
|
"private": false,
|
||||||
"mirror": {
|
"mirrors": [
|
||||||
"gitHubAddress": "https://github.com/MyName/repo-name-3"
|
{
|
||||||
}
|
"gitHubAddress": "https://github.com/MyName/repo-name-3"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"new-repo-mirrored-with-branches": {
|
"new-repo-mirrored-with-branches": {
|
||||||
@@ -48,9 +50,11 @@
|
|||||||
"native": {
|
"native": {
|
||||||
"defaultBranch": "main",
|
"defaultBranch": "main",
|
||||||
"private": false,
|
"private": false,
|
||||||
"mirror": {
|
"mirrors": [
|
||||||
"gitHubAddress": "https://github.com/MyName/repo-name-3"
|
{
|
||||||
},
|
"gitHubAddress": "https://github.com/MyName/repo-name-3"
|
||||||
|
}
|
||||||
|
],
|
||||||
"protectedBranches": [
|
"protectedBranches": [
|
||||||
{
|
{
|
||||||
"branchName": "main"
|
"branchName": "main"
|
||||||
@@ -63,9 +67,11 @@
|
|||||||
"native": {
|
"native": {
|
||||||
"defaultBranch": "main",
|
"defaultBranch": "main",
|
||||||
"private": false,
|
"private": false,
|
||||||
"mirror": {
|
"mirrors": [
|
||||||
"gitHubAddress": "https://github.com/MyName/repo-name-3"
|
{
|
||||||
},
|
"gitHubAddress": "https://github.com/MyName/repo-name-3"
|
||||||
|
}
|
||||||
|
],
|
||||||
"protectedBranches": [
|
"protectedBranches": [
|
||||||
{
|
{
|
||||||
"branchName": "main",
|
"branchName": "main",
|
||||||
@@ -83,9 +89,11 @@
|
|||||||
"native": {
|
"native": {
|
||||||
"defaultBranch": "main",
|
"defaultBranch": "main",
|
||||||
"private": false,
|
"private": false,
|
||||||
"mirror": {
|
"mirrors": [
|
||||||
"gitHubAddress": "https://github.com/MyName/repo-name-3"
|
{
|
||||||
},
|
"gitHubAddress": "https://github.com/MyName/repo-name-3"
|
||||||
|
}
|
||||||
|
],
|
||||||
"protectedBranches": [
|
"protectedBranches": [
|
||||||
{
|
{
|
||||||
"branchName": "main",
|
"branchName": "main",
|
||||||
|
@@ -46,15 +46,14 @@ module TestSchema =
|
|||||||
let schema = reader.ReadToEnd ()
|
let schema = reader.ReadToEnd ()
|
||||||
schema.Contains "SerialisedGiteaConfig" |> shouldEqual true
|
schema.Contains "SerialisedGiteaConfig" |> shouldEqual true
|
||||||
|
|
||||||
[<Test>]
|
let schemaFile : Lazy<FileInfo> =
|
||||||
[<Explicit "Run this to regenerate the schema file">]
|
lazy
|
||||||
let ``Update schema file`` () =
|
|
||||||
let schemaFile =
|
|
||||||
Assembly.GetExecutingAssembly().Location
|
Assembly.GetExecutingAssembly().Location
|
||||||
|> FileInfo
|
|> FileInfo
|
||||||
|> fun fi -> fi.Directory
|
|> fun fi -> fi.Directory
|
||||||
|> Utils.findFileAbove "Gitea.Declarative.Lib/GiteaConfig.schema.json"
|
|> Utils.findFileAbove "Gitea.Declarative.Lib/GiteaConfig.schema.json"
|
||||||
|
|
||||||
|
let computeSchema () =
|
||||||
let settings = JsonSchemaGeneratorSettings ()
|
let settings = JsonSchemaGeneratorSettings ()
|
||||||
|
|
||||||
settings.SerializerSettings <-
|
settings.SerializerSettings <-
|
||||||
@@ -78,4 +77,16 @@ module TestSchema =
|
|||||||
schema.RequiredProperties.Add "native"
|
schema.RequiredProperties.Add "native"
|
||||||
serialisedRepoSchema.OneOf.Add schema
|
serialisedRepoSchema.OneOf.Add schema
|
||||||
|
|
||||||
File.WriteAllText (schemaFile.FullName, schema.ToJson ())
|
schema
|
||||||
|
|
||||||
|
[<Test>]
|
||||||
|
let ``Schema hasn't changed`` () =
|
||||||
|
let computed = computeSchema () |> fun x -> x.ToJson ()
|
||||||
|
let actual = File.ReadAllText (schemaFile.Force().FullName)
|
||||||
|
computed |> shouldEqual actual
|
||||||
|
|
||||||
|
[<Test>]
|
||||||
|
[<Explicit "Run this to regenerate the schema file">]
|
||||||
|
let ``Update schema file`` () =
|
||||||
|
let schema = computeSchema ()
|
||||||
|
File.WriteAllText (schemaFile.Force().FullName, schema.ToJson ())
|
||||||
|
Reference in New Issue
Block a user