qry$query('flds', '{ node(id: "PVT_kwDOCLQwZM4AW8mq") { ... on ProjectV2 { fields(first: 20) { nodes { ... on ProjectV2Field { id name } ... on ProjectV2IterationField { id name configuration { iterations { startDate id }}} ... on ProjectV2SingleSelectField { id name options { id name }}}}}}}')(x <- con$exec(qry$queries$flds))jsonlite::fromJSON(x)qry <- Query$new()qry$query('flds_common', '{ node(id: "PVT_kwDOCLQwZM4AW8mq") { ... on ProjectV2 { fields(first: 20) { nodes { ... on ProjectV2FieldCommon { id name __typename }}}}}}')(x <- con$exec(qry$queries$flds_common))jsonlite::fromJSON(x)qry <- Query$new()qry$query('itms', '{ node(id: "PVT_kwDOCLQwZM4AW8mq") { ... on ProjectV2 { items(first: 20) { nodes{ id fieldValues(first: 8) { nodes{ ... on ProjectV2ItemFieldTextValue { text field { ... on ProjectV2FieldCommon { name }}} ... on ProjectV2ItemFieldDateValue { date field { ... on ProjectV2FieldCommon { name }}} ... on ProjectV2ItemFieldSingleSelectValue { name field { ... on ProjectV2FieldCommon { name }}} } } content{ ... on DraftIssue { title body } ...on Issue { id title assignees(first: 10) { nodes{ login }} } ...on PullRequest { title assignees(first: 10) { nodes{ login }}} }}}}}}')(x <- con$exec(qry$queries$itms))jsonlite::fromJSON(x)issueid <-"I_kwDOKemkec50y7V4"prjid <-"PVT_kwDOCLQwZM4AW8mq"qry <- Query$new()qry$query('addissue2prj', glue('mutation { addProjectV2ItemById( input: { projectId: "[prjid]" contentId: "[issueid]" } ) {item {id}} }',.open ="[",.close ="]"))(x <- con$exec(qry$queries$addissue2prj))id <- jsonlite::fromJSON(x) %>% .$data %>% .$addProjectV2ItemById %>% .$item %>% .$id# PVTI_lADOCLQwZM4AW8mqzgKL5mU# TODO:# - loop through issues and add to Project# - add to specific column (e.g. "To do")\# [Using the API to manage Projects - GitHub Enterprise Cloud Docs](https://docs.github.com/en/enterprise-cloud@latest/issues/planning-and-tracking-with-projects/automating-your-project/using-the-api-to-manage-projects#updating-a-custom-text-number-or-date-field)# - add to specific iteration (e.g. "2021-01-01")# - add to specific assignee (e.g. "bbest")# - add to specific label (e.g. "type/status")# - add to specific milestone (e.g. "v1.0.0")# - add to specific project (e.g. "MarineSensitivity.github.io")# - add to specific repository (e.g. "MarineSensitivity.github.io")# - add to specific column (e.g. "To do")
Source Code
---title: "manage_github"editor_options: chunk_output_type: console---## Apply label across repositories* [gh](https://gh.r-lib.org/#post-patch-put-and-delete-requests) R package for interacting with Github API* [Github API: Issues / Labels](https://docs.github.com/en/rest/issues/labels?apiVersion=2022-11-28)```{r}librarian::shelf( dplyr, fs, gitcreds, gh, glue, knitr, listviewer, tidyjson,quiet = T)org <-"MarineSensitivity"lbls_custom <-list(list(name ="spatial-units",description ="spatial units for analysis and comparison, e.g. regions, planning areas, aliquots, etc.",color ="89E836"))# get repositoriesrepos_lst <-gh(glue("GET /orgs/{org}/repos"))listviewer::jsonedit(repos_lst)(repos <-vapply(repos_lst, "[[", "", "name"))# add label (if missing)if (F){for (lbl in lbls_custom){ # lbl = lbls_custom[[1]]print(glue("adding label {lbl$name} to {length(repos)} repositories"))for (repo in repos){ repo_lbls <-gh(glue("GET /repos/{org}/{repo}/labels")) |>vapply("[[", "", "name")if (lbl$name %in% repo_lbls){print(glue(" {repo}: exists")) } else {print(glue(" {repo}: adding"))gh(glue("POST /repos/{org}/{repo}/labels"),name = lbl$name,description = lbl$description,color = lbl$color) } } }}# TODO: move to functions in new ecoquants/ghmgt R package```## Clone all repos locally```{r}for (repo in repos){ # repo = repos[1] dir_repo <-glue("~/Github/{org}/{repo}")if (!dir_exists(dir_repo)){message("cloning {repo}") cmd <-glue("git clone https://github.com/{org}/{repo}.git {dir_repo}")print(cmd)system(cmd) }}```## Get repo descriptions```{r}gh(glue("GET /orgs/{org}/repos")) |>spread_all() |>as_tibble() |>select(name, description) |>arrange(name) |>kable()```## Add issues to projectNeed to use:```{r}#| eval: falselibrarian::shelf( dplyr, ropensci/ghql, jsonlite)token <-Sys.getenv("GITHUB_TOKEN") # vi ~/.Renviron # /Users/bbest/My Drive/private/pat4rstudio.txtgq <-get_gq(token)prj_id <-get_prj_id(gq, "MarineSensitivity", 1)devtools::load_all("~/Github/ecoquants/ghmgt")get_prj_issues <-function(prj_id){# return IDs of issues in project qry <- Query$new() qry$query('q', glueb( '{ node(id: "[prj_id]") { ... on ProjectV2 { items(first: 20) { nodes{ id content{ ...on Issue { id title } }}}}}}') ) con$exec(qry$queries$q) |>fromJSON() |> (\(x){ x$data$node$items$nodes$content$id })()}prj_issues <-get_prj_issues(prj_id)get_owner_repos <-function(owner ="MarineSensitivity"){gh(glue("GET /orgs/{owner}/repos")) |>vapply("[[", "", "name") |>sort()}repos <-get_owner_repos(org)add_prj_issue <-function(prj_id, issue_id, verbose = T){# add issue to project, return id of new item in project# issue_id = repo_issue qry <- Query$new() q <-glueb('mutation { addProjectV2ItemById( input: { projectId: "[prj_id]" contentId: "[issue_id]" } ) {item {id}} }')if (verbose) message(q) qry$query('q', q ) con$exec(qry$queries$q) |>fromJSON() |> (\(x){ x$data$addProjectV2ItemById$item$id })() # PVTI_lADOCLQwZM4AW8mqzgKL5mU}for (repo in repos){ # repo = repos[1] # repo = "msens" repo_issues <-get_repo_issues(repo = repo)message(glue("{repo} issues -> project '{prj_id}'"))for (issue_id in repo_issues){ # repo_issue = repo_issues[1]if (issue_id %in% prj_issues){message(glue(" issue '{issue_id}' already in project")) } else {message(glue(" adding issue '{issue_id}' to project")) id_new <-add_prj_issue(prj_id, issue_id) } }}``````{r OLD manual, eval = F}qry$query('flds', '{ node(id: "PVT_kwDOCLQwZM4AW8mq") { ... on ProjectV2 { fields(first: 20) { nodes { ... on ProjectV2Field { id name } ... on ProjectV2IterationField { id name configuration { iterations { startDate id }}} ... on ProjectV2SingleSelectField { id name options { id name }}}}}}}')(x <- con$exec(qry$queries$flds))jsonlite::fromJSON(x)qry <- Query$new()qry$query('flds_common', '{ node(id: "PVT_kwDOCLQwZM4AW8mq") { ... on ProjectV2 { fields(first: 20) { nodes { ... on ProjectV2FieldCommon { id name __typename }}}}}}')(x <- con$exec(qry$queries$flds_common))jsonlite::fromJSON(x)qry <- Query$new()qry$query('itms', '{ node(id: "PVT_kwDOCLQwZM4AW8mq") { ... on ProjectV2 { items(first: 20) { nodes{ id fieldValues(first: 8) { nodes{ ... on ProjectV2ItemFieldTextValue { text field { ... on ProjectV2FieldCommon { name }}} ... on ProjectV2ItemFieldDateValue { date field { ... on ProjectV2FieldCommon { name }}} ... on ProjectV2ItemFieldSingleSelectValue { name field { ... on ProjectV2FieldCommon { name }}} } } content{ ... on DraftIssue { title body } ...on Issue { id title assignees(first: 10) { nodes{ login }} } ...on PullRequest { title assignees(first: 10) { nodes{ login }}} }}}}}}')(x <- con$exec(qry$queries$itms))jsonlite::fromJSON(x)issueid <-"I_kwDOKemkec50y7V4"prjid <-"PVT_kwDOCLQwZM4AW8mq"qry <- Query$new()qry$query('addissue2prj', glue('mutation { addProjectV2ItemById( input: { projectId: "[prjid]" contentId: "[issueid]" } ) {item {id}} }',.open ="[",.close ="]"))(x <- con$exec(qry$queries$addissue2prj))id <- jsonlite::fromJSON(x) %>% .$data %>% .$addProjectV2ItemById %>% .$item %>% .$id# PVTI_lADOCLQwZM4AW8mqzgKL5mU# TODO:# - loop through issues and add to Project# - add to specific column (e.g. "To do")\# [Using the API to manage Projects - GitHub Enterprise Cloud Docs](https://docs.github.com/en/enterprise-cloud@latest/issues/planning-and-tracking-with-projects/automating-your-project/using-the-api-to-manage-projects#updating-a-custom-text-number-or-date-field)# - add to specific iteration (e.g. "2021-01-01")# - add to specific assignee (e.g. "bbest")# - add to specific label (e.g. "type/status")# - add to specific milestone (e.g. "v1.0.0")# - add to specific project (e.g. "MarineSensitivity.github.io")# - add to specific repository (e.g. "MarineSensitivity.github.io")# - add to specific column (e.g. "To do")```