Created
October 28, 2020 23:34
-
-
Save bronumski/4dc5b8d668c1dbdf007bc4b389c83437 to your computer and use it in GitHub Desktop.
Trawls bitbucket repositories looking for stale branches and pull requests.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
open System | |
open System.Text | |
open FSharp.Data | |
open FSharp.Json | |
let (username, password) = ("username", "password") | |
let repositoryRootUrl = "https://api.bitbucket.org/2.0/repositories/team_workspace" | |
let repositories = [ "RepoA"; "RepoB" ] | |
let lookBack = DateTime.Now.AddDays(-1.0) | |
let maxOutdatedToTake = 10 | |
type Author = { display_name : string } | |
and Link = { href : string } | |
type Repository = { name : string; links : RepositoryLinks } | |
and RepositoryLinks = { branches : Link ; pullrequests : Link } | |
type PullRequest = { title : string; updated_on : DateTime; author : Author; links : PullRequestLinks } | |
and PullRequestLinks = { html : Link } | |
and PullRequests = { values : PullRequest[] } | |
type Branch = { name : string; links : BranchLinks; target : BranchTarget } | |
and BranchTarget = { author : BranchAuthor } | |
and Branches = { values : Branch[] } | |
and BranchLinks = { commits : Link; html: Link } | |
and BranchAuthor = { user : Author } | |
type Commit = { date : DateTime } | |
and Commits = { values : Commit[] } | |
let CreateBasicAuth = | |
sprintf "%s:%s" username password | |
|> Encoding.UTF8.GetBytes | |
|> Convert.ToBase64String | |
|> sprintf "Basic %s" | |
let authHeader = CreateBasicAuth | |
let GenerateRepositoryUrl repository = | |
Uri(sprintf "%s/%s" repositoryRootUrl repository) | |
type Endpoint = | |
| Link of Link | |
| Uri of Uri | |
let GetResource<'T>(address, query:Option<string>) = | |
let endpoint = match address with | Link(a) -> a.href | Uri(a) -> a.ToString() | |
let url = match query with | Some query -> sprintf "%s?%s" endpoint query | None -> endpoint | |
Json.deserialize<'T> (Http.RequestString( url, httpMethod = "GET", headers = [ "Authorization", authHeader ] )) | |
let GetRepositoryOutdatedPullRequests(repository:Repository) = | |
GetResource<PullRequests>(Link repository.links.pullrequests, Some "state=OPEN").values | |
|> Seq.filter(fun pr -> pr.updated_on < lookBack) | |
|> Seq.truncate maxOutdatedToTake | |
let GetBranchLatestCommit(branch:Branch) = | |
GetResource<Commits>(Link branch.links.commits, None).values |> Seq.head | |
let GetRepositoryOutdatedBranches (repository:Repository) = | |
GetResource<Branches>(Link repository.links.branches, None).values | |
|> Seq.filter(fun branch -> branch.name <> "master") | |
|> Seq.map(fun branch -> (branch, GetBranchLatestCommit branch)) | |
|> Seq.filter(fun (_, commit) -> commit.date < lookBack) | |
|> Seq.truncate maxOutdatedToTake | |
let GetRepositoryData repositoryUrl = | |
let repository = GetResource<Repository>(repositoryUrl, None) | |
(repository, GetRepositoryOutdatedPullRequests(repository), GetRepositoryOutdatedBranches(repository)) | |
[<EntryPoint>] | |
let main argv = | |
repositories | |
|> Seq.map(GenerateRepositoryUrl) | |
|> Seq.map(fun url -> GetRepositoryData(Uri url)) | |
|> Seq.iter(fun (repo, outdatedPrs, outdatedBranch) -> | |
printfn "Repository: %s" repo.name | |
printfn "Outdated pull requests:" | |
outdatedPrs |> Seq.iter(fun pr -> printfn "\t%s - %s - %s" pr.title pr.author.display_name (pr.updated_on.ToString "yyyy-MM-dd")) | |
printfn "Outdated branches:" | |
outdatedBranch |> Seq.iter(fun (branch, commit) -> printfn "\t%s - %s - %s" branch.name branch.target.author.user.display_name (commit.date.ToString "yyyy-MM-dd")) | |
) | |
0 // return an integer exit code |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment