From b47bed51d55f3a55801b3cb47a45b507ad14b964 Mon Sep 17 00:00:00 2001 From: Neal Richardson Date: Fri, 10 Oct 2025 08:12:10 -0400 Subject: [PATCH 01/11] Reformat some lines so that grep unversioned_url is more useful --- R/content.R | 18 +++++------------- R/variant.R | 8 ++------ 2 files changed, 7 insertions(+), 19 deletions(-) diff --git a/R/content.R b/R/content.R index f3a1eef6..bffb1eb6 100644 --- a/R/content.R +++ b/R/content.R @@ -161,18 +161,13 @@ Content <- R6::R6Class( #' @param key The job key. job = function(key) { warn_experimental("job") - url <- unversioned_url( - "applications", - self$content$guid, - "job", - key - ) + guid <- self$content$guid + url <- unversioned_url("applications", guid, "job", key) res <- self$connect$GET(url) - content_guid <- self$content$guid purrr::map( list(res), - ~ purrr::list_modify(.x, app_guid = content_guid) + ~ purrr::list_modify(.x, app_guid = guid) )[[1]] }, #' @description Terminate a single job for this content item. @@ -189,11 +184,8 @@ Content <- R6::R6Class( #' @description Return the variants for this content. variants = function() { warn_experimental("variants") - url <- unversioned_url( - "applications", - self$content$guid, - "variants" - ) + guid <- self$content$guid + url <- unversioned_url("applications", guid, "variants") self$connect$GET(url) }, #' @description Set a tag for this content. diff --git a/R/variant.R b/R/variant.R index a526f394..17cb55d1 100644 --- a/R/variant.R +++ b/R/variant.R @@ -87,12 +87,8 @@ Variant <- R6::R6Class( #' @param guid User GUID. remove_subscriber = function(guid) { warn_experimental("subscribers") - path <- unversioned_url( - "variants", - self$variant$id, - "subscribers", - guid - ) + id <- self$variant$id + path <- unversioned_url("variants", id, "subscribers", guid) self$connect$DELETE(path) }, #' @description Add named subscribers. From 97e639d1c8a6bb191c1bb2135a491a6819da7560 Mon Sep 17 00:00:00 2001 From: Neal Richardson Date: Fri, 10 Oct 2025 08:52:28 -0400 Subject: [PATCH 02/11] Use v1 APIs for managing content git repo settings --- R/content.R | 69 +++++++++++++++++++++++++++---------- R/git.R | 16 +-------- tests/integrated/test-git.R | 11 ++++-- tests/testthat/test-git.R | 7 ++++ 4 files changed, 66 insertions(+), 37 deletions(-) diff --git a/R/content.R b/R/content.R index bffb1eb6..7b6dcb5a 100644 --- a/R/content.R +++ b/R/content.R @@ -63,11 +63,6 @@ Content <- R6::R6Class( url <- v1_url("content", self$content$guid, "bundles", bundle_id) self$connect$DELETE(url) }, - #' @description Get this (remote) content item. - internal_content = function() { - url <- unversioned_url("applications", self$content$guid) - self$connect$GET(url) - }, #' @description Update this content item. #' @param ... Content fields. update = function(...) { @@ -322,15 +317,39 @@ Content <- R6::R6Class( body = body ) }, + #' @description Get Git repository details + repository = function() { + # NOTE: the v1 and v0 endpoints don't have identical fields + # notably, v0 has "enabled" and v1 has "polling" + GET <- self$connect$GET + guid <- self$content$guid + tryCatch( + # TODO: what does the API return if no repo is set? + v1_url("content", guid, "repository"), + error = function(e) { + GET(unversioned_fallback_url("applications", guid))$git + } + ) + }, #' @description Adjust Git polling. #' @param enabled Polling enabled. repo_enable = function(enabled = TRUE) { - warn_experimental("repo_enable") - self$connect$PUT( - unversioned_url("applications", self$content$guid, "repo"), - body = list( - enabled = enabled - ) + guid <- self$content$guid + tryCatch( + self$connect$PATCH( + v1_url("content", guid, "repository"), + body = list( + polling = enabled + ) + ), + error = function(e) { + self$connect$PUT( + unversioned_fallback_url("applications", guid, "repo"), + body = list( + enabled = enabled + ) + ) + } ) }, #' @description Adjust Git repository @@ -338,14 +357,26 @@ Content <- R6::R6Class( #' @param branch Git repository branch #' @param subdirectory Git repository directory repo_set = function(repository, branch, subdirectory) { - warn_experimental("repo_set") - self$connect$POST( - unversioned_url("applications", self$content$guid, "repo"), - body = list( - repository = repository, - branch = branch, - subdirectory = subdirectory - ) + guid <- self$content$guid + tryCatch( + self$connect$PUT( + v1_url("content", guid, "repository"), + body = list( + repository = repository, + branch = branch, + directory = subdirectory + ) + ), + error = function(e) { + self$connect$POST( + unversioned_fallback_url("applications", guid, "repo"), + body = list( + repository = repository, + branch = branch, + subdirectory = subdirectory + ) + ) + } ) }, #' @description Get package dependencies diff --git a/R/git.R b/R/git.R index 4837299c..e9ef65d2 100644 --- a/R/git.R +++ b/R/git.R @@ -158,21 +158,7 @@ deploy_repo_update <- function(content) { scoped_experimental_silence() con <- content$connect - internal_meta <- content$internal_content() - repo_data <- tryCatch( - { - internal_meta$git - }, - error = function(e) { - message(e) - return(NULL) - } - ) - if (is.null(repo_data)) { - stop(glue::glue( - "Content item '{internal_meta$guid}' is not git-backed content" - )) - } + internal_meta <- content$repository() branch_status <- repo_check_branches_ref(con, repo_data$repository_url) if (!repo_data$branch %in% names(branch_status)) { diff --git a/tests/integrated/test-git.R b/tests/integrated/test-git.R index 3a6cdb36..8e91667c 100644 --- a/tests/integrated/test-git.R +++ b/tests/integrated/test-git.R @@ -106,13 +106,18 @@ test_that("deploy_repo_enable works", { expect_true(validate_R6_class(cont1, "Content")) expect_true(validate_R6_class(cont1, "ContentTask")) + # helper to handle the difference between API versions + polling_enabled <- function(content) { + git <- content$repository() + git$enabled || git$polling + } # TODO: flaky... how to be safer? Sys.sleep(5) # sleep for deployment...? - expect_true(cont1$internal_content()$git$enabled) + expect_true(polling_enabled(cont1)) res <- deploy_repo_enable(cont1, FALSE) - expect_false(cont1$internal_content()$git$enabled) + expect_false(polling_enabled(cont1)) res <- deploy_repo_enable(cont1, TRUE) - expect_true(cont1$internal_content()$git$enabled) + expect_true(polling_enabled(cont1)) }) test_that("deploy_repo_update works", { diff --git a/tests/testthat/test-git.R b/tests/testthat/test-git.R index 2e3e0c25..cc95ffeb 100644 --- a/tests/testthat/test-git.R +++ b/tests/testthat/test-git.R @@ -37,3 +37,10 @@ without_internet({ ) }) }) + +with_mock_api({ + test_that("we can retrieve a content item", { + con <- Connect$new(server = "https://connect.example", api_key = "fake") + item <- content_item(con, "f2f37341-e21d-3d80-c698-a935ad614066") + }) +}) From 46eafa66022e26c5a51214ddb3624562228f87c7 Mon Sep 17 00:00:00 2001 From: Neal Richardson Date: Fri, 10 Oct 2025 11:54:51 -0400 Subject: [PATCH 03/11] Map field names --- R/content.R | 14 ++++++++++---- R/git.R | 6 +++--- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/R/content.R b/R/content.R index 7b6dcb5a..47e34b82 100644 --- a/R/content.R +++ b/R/content.R @@ -319,15 +319,21 @@ Content <- R6::R6Class( }, #' @description Get Git repository details repository = function() { - # NOTE: the v1 and v0 endpoints don't have identical fields - # notably, v0 has "enabled" and v1 has "polling" GET <- self$connect$GET guid <- self$content$guid tryCatch( - # TODO: what does the API return if no repo is set? + # TODO: what does the v1 API return if no repo is set? v1_url("content", guid, "repository"), error = function(e) { - GET(unversioned_fallback_url("applications", guid))$git + resp <- GET(unversioned_fallback_url("applications", guid))$git + if (!is.null(resp)) { + # NOTE: the v1 and v0 endpoints don't have identical fields + # Rename to match v1 naming + names(resp)[names(resp) == "repository_url"] <- "repository" + names(resp)[names(resp) == "subdirectory"] <- "directory" + names(resp)[names(resp) == "enabled"] <- "polling" + } + resp } ) }, diff --git a/R/git.R b/R/git.R index e9ef65d2..8b768adc 100644 --- a/R/git.R +++ b/R/git.R @@ -158,12 +158,12 @@ deploy_repo_update <- function(content) { scoped_experimental_silence() con <- content$connect - internal_meta <- content$repository() - branch_status <- repo_check_branches_ref(con, repo_data$repository_url) + repo_data <- content$repository() + branch_status <- repo_check_branches_ref(con, repo_data$repository) if (!repo_data$branch %in% names(branch_status)) { stop(glue::glue( - "Branch '{repo_data$branch}' was no longer found on repository '{repo_data$repository_url}'" + "Branch '{repo_data$branch}' was no longer found on repository '{repo_data$repository}'" )) } if ( From ffd74b31080d6bd45775a33d2eb157b3227fef75 Mon Sep 17 00:00:00 2001 From: Neal Richardson Date: Fri, 10 Oct 2025 16:42:24 -0400 Subject: [PATCH 04/11] Try to fix integration test --- R/content.R | 7 +++++-- tests/integrated/test-git.R | 3 +-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/R/content.R b/R/content.R index 47e34b82..ff638086 100644 --- a/R/content.R +++ b/R/content.R @@ -318,12 +318,15 @@ Content <- R6::R6Class( ) }, #' @description Get Git repository details + #' @return a list of repo details, or NULL if no repo is set repository = function() { GET <- self$connect$GET guid <- self$content$guid tryCatch( - # TODO: what does the v1 API return if no repo is set? - v1_url("content", guid, "repository"), + # TODO: the v1 API returns 404 if no repo is set, so that means we fall + # back to the other API. The new API was added in October 2022, so maybe + # we just don't fall back. + GET(v1_url("content", guid, "repository")), error = function(e) { resp <- GET(unversioned_fallback_url("applications", guid))$git if (!is.null(resp)) { diff --git a/tests/integrated/test-git.R b/tests/integrated/test-git.R index 8e91667c..2d335a19 100644 --- a/tests/integrated/test-git.R +++ b/tests/integrated/test-git.R @@ -106,10 +106,9 @@ test_that("deploy_repo_enable works", { expect_true(validate_R6_class(cont1, "Content")) expect_true(validate_R6_class(cont1, "ContentTask")) - # helper to handle the difference between API versions polling_enabled <- function(content) { git <- content$repository() - git$enabled || git$polling + isTRUE(git$polling) } # TODO: flaky... how to be safer? Sys.sleep(5) # sleep for deployment...? From c5be2b93825e5735c2188eeac70674ac945d48af Mon Sep 17 00:00:00 2001 From: Neal Richardson Date: Fri, 10 Oct 2025 17:04:07 -0400 Subject: [PATCH 05/11] Restore check in test --- R/git.R | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/R/git.R b/R/git.R index 8b768adc..f8f31f5c 100644 --- a/R/git.R +++ b/R/git.R @@ -159,6 +159,11 @@ deploy_repo_update <- function(content) { con <- content$connect repo_data <- content$repository() + if (is.null(repo_data)) { + stop(glue::glue( + "Content item '{content$get_content()$guid}' is not git-backed content" + )) + } branch_status <- repo_check_branches_ref(con, repo_data$repository) if (!repo_data$branch %in% names(branch_status)) { @@ -170,7 +175,7 @@ deploy_repo_update <- function(content) { identical(repo_data$last_known_commit, branch_status[[repo_data$branch]]) ) { message(glue::glue( - "No changes were found in the Git repository: {repo_data$repository_url}@{repo_data$branch}" + "No changes were found in the Git repository: {repo_data$repository}@{repo_data$branch}" )) return(content) } From 876a2b025ccb53ed906cf2f6473b8c2830d453de Mon Sep 17 00:00:00 2001 From: Neal Richardson Date: Sat, 11 Oct 2025 14:29:15 -0400 Subject: [PATCH 06/11] Remove v0 fallbacks --- R/content.R | 101 +++++++++++++++++++++++----------------------------- R/git.R | 10 ++---- 2 files changed, 48 insertions(+), 63 deletions(-) diff --git a/R/content.R b/R/content.R index ff638086..2dc0821d 100644 --- a/R/content.R +++ b/R/content.R @@ -318,74 +318,63 @@ Content <- R6::R6Class( ) }, #' @description Get Git repository details - #' @return a list of repo details, or NULL if no repo is set + #' @return NULL if no repo is set, otherwise a list with fields: + #' - repository + #' - branch + #' - directory + #' - polling + #' - last_error + #' - last_known_commit repository = function() { - GET <- self$connect$GET + con <- self$connect guid <- self$content$guid - tryCatch( - # TODO: the v1 API returns 404 if no repo is set, so that means we fall - # back to the other API. The new API was added in October 2022, so maybe - # we just don't fall back. - GET(v1_url("content", guid, "repository")), - error = function(e) { - resp <- GET(unversioned_fallback_url("applications", guid))$git - if (!is.null(resp)) { - # NOTE: the v1 and v0 endpoints don't have identical fields - # Rename to match v1 naming - names(resp)[names(resp) == "repository_url"] <- "repository" - names(resp)[names(resp) == "subdirectory"] <- "directory" - names(resp)[names(resp) == "enabled"] <- "polling" - } - resp - } + resp <- con$GET( + v1_url("content", guid, "repository"), + parser = NULL ) + if (httr::status_code(resp) == 404) { + resp <- NULL + } else { + con$raise_error(resp) + resp <- httr::content(resp, as = "parsed") + } + resp }, #' @description Adjust Git polling. - #' @param enabled Polling enabled. - repo_enable = function(enabled = TRUE) { + #' @param polling Polling enabled. + repo_enable = function(polling = TRUE) { + con <- self$connect guid <- self$content$guid - tryCatch( - self$connect$PATCH( - v1_url("content", guid, "repository"), - body = list( - polling = enabled - ) - ), - error = function(e) { - self$connect$PUT( - unversioned_fallback_url("applications", guid, "repo"), - body = list( - enabled = enabled - ) - ) - } + resp <- con$PATCH( + v1_url("content", guid, "repository"), + body = list(polling = polling) ) + if (httr::status_code(resp) == 404) { + stop("This content item is not git-backed") + } + con$raise_error(resp) + httr::content(resp, as = "parsed") }, #' @description Adjust Git repository #' @param repository Git repository URL #' @param branch Git repository branch - #' @param subdirectory Git repository directory - repo_set = function(repository, branch, subdirectory) { + #' @param directory Git repository directory + #' @param polling Whether to check for updates + repo_set = function( + repository, + branch = "main", + directory = ".", + polling = FALSE + ) { guid <- self$content$guid - tryCatch( - self$connect$PUT( - v1_url("content", guid, "repository"), - body = list( - repository = repository, - branch = branch, - directory = subdirectory - ) - ), - error = function(e) { - self$connect$POST( - unversioned_fallback_url("applications", guid, "repo"), - body = list( - repository = repository, - branch = branch, - subdirectory = subdirectory - ) - ) - } + self$connect$PUT( + v1_url("content", guid, "repository"), + body = list( + repository = repository, + branch = branch, + directory = subdirectory, + polling = polling + ) ) }, #' @description Get package dependencies diff --git a/R/git.R b/R/git.R index f8f31f5c..caa2268b 100644 --- a/R/git.R +++ b/R/git.R @@ -117,7 +117,6 @@ deploy_repo <- function( ... ) { validate_R6_class(client, "Connect") - warn_experimental("deploy_repo") content_metadata <- content_ensure( connect = client, @@ -143,19 +142,16 @@ deploy_repo <- function( #' @export deploy_repo_enable <- function(content, enabled = TRUE) { validate_R6_class(content, "Content") - warn_experimental("deploy_repo_enable") - invisible(content$repo_enable(enabled)) - invisible(content$get_content_remote()) - return(content) + content$repo_enable(enabled) + content$get_content_remote() + content } #' @rdname deploy_repo #' @export deploy_repo_update <- function(content) { validate_R6_class(content, "Content") - warn_experimental("deploy_repo_update") - scoped_experimental_silence() con <- content$connect repo_data <- content$repository() From 502a5df3df49b6147f8df0aa2aef52edcc808d35 Mon Sep 17 00:00:00 2001 From: Neal Richardson Date: Sat, 11 Oct 2025 14:51:15 -0400 Subject: [PATCH 07/11] Add mock tests --- R/content.R | 18 ++++------- .../__api__/v1/content/c3426b0b/README.md | 4 ++- .../__api__/v1/content/c3426b0b/repository.R | 10 +++++++ .../v1/content/f2f37341/repository.json | 8 +++++ tests/testthat/test-git.R | 30 ++++++++++++++++++- 5 files changed, 56 insertions(+), 14 deletions(-) create mode 100644 tests/testthat/2024.08.0/__api__/v1/content/c3426b0b/repository.R create mode 100644 tests/testthat/2024.08.0/__api__/v1/content/f2f37341/repository.json diff --git a/R/content.R b/R/content.R index 2dc0821d..71628928 100644 --- a/R/content.R +++ b/R/content.R @@ -333,27 +333,21 @@ Content <- R6::R6Class( parser = NULL ) if (httr::status_code(resp) == 404) { - resp <- NULL - } else { - con$raise_error(resp) - resp <- httr::content(resp, as = "parsed") + # 404 means there is no repository set + return(NULL) } - resp + con$raise_error(resp) + httr::content(resp, as = "parsed") }, #' @description Adjust Git polling. #' @param polling Polling enabled. repo_enable = function(polling = TRUE) { con <- self$connect guid <- self$content$guid - resp <- con$PATCH( + con$PATCH( v1_url("content", guid, "repository"), body = list(polling = polling) ) - if (httr::status_code(resp) == 404) { - stop("This content item is not git-backed") - } - con$raise_error(resp) - httr::content(resp, as = "parsed") }, #' @description Adjust Git repository #' @param repository Git repository URL @@ -372,7 +366,7 @@ Content <- R6::R6Class( body = list( repository = repository, branch = branch, - directory = subdirectory, + directory = directory, polling = polling ) ) diff --git a/tests/testthat/2024.08.0/__api__/v1/content/c3426b0b/README.md b/tests/testthat/2024.08.0/__api__/v1/content/c3426b0b/README.md index 7c6442bb..2082a799 100644 --- a/tests/testthat/2024.08.0/__api__/v1/content/c3426b0b/README.md +++ b/tests/testthat/2024.08.0/__api__/v1/content/c3426b0b/README.md @@ -1 +1,3 @@ -This content item returns 403 errors when setting and deleting vanity URLs. \ No newline at end of file +This content item returns 403 errors when setting and deleting vanity URLs. + +It is also not git-backed, so repository is a 404 diff --git a/tests/testthat/2024.08.0/__api__/v1/content/c3426b0b/repository.R b/tests/testthat/2024.08.0/__api__/v1/content/c3426b0b/repository.R new file mode 100644 index 00000000..d0dcf2fd --- /dev/null +++ b/tests/testthat/2024.08.0/__api__/v1/content/c3426b0b/repository.R @@ -0,0 +1,10 @@ +structure( + list( + url = "__api__/v1/content/c3426b0b/repository", + status_code = 404L, + content = charToRaw( + "{}" + ) + ), + class = "response" +) diff --git a/tests/testthat/2024.08.0/__api__/v1/content/f2f37341/repository.json b/tests/testthat/2024.08.0/__api__/v1/content/f2f37341/repository.json new file mode 100644 index 00000000..e3810031 --- /dev/null +++ b/tests/testthat/2024.08.0/__api__/v1/content/f2f37341/repository.json @@ -0,0 +1,8 @@ +{ + "repository": "https://github.com/dbkegley/rsc-sample-content", + "branch": "main", + "directory": "local/python-shiny", + "polling": true, + "last_error": "thread caused non-unwinding panic. aborting. (signal: aborted (core dumped))", + "last_known_commit": "5e69ff238376182fa7ed38b30497d457684c6e24" +} diff --git a/tests/testthat/test-git.R b/tests/testthat/test-git.R index cc95ffeb..d2f365eb 100644 --- a/tests/testthat/test-git.R +++ b/tests/testthat/test-git.R @@ -39,8 +39,36 @@ without_internet({ }) with_mock_api({ - test_that("we can retrieve a content item", { + test_that("we can retrieve a repository information if it exists", { con <- Connect$new(server = "https://connect.example", api_key = "fake") item <- content_item(con, "f2f37341-e21d-3d80-c698-a935ad614066") + expect_true(item$repository()$polling) + }) + + test_that("repository is null if it is not set", { + con <- Connect$new(server = "https://connect.example", api_key = "fake") + item <- content_item(con, "c3426b0b-e21d-3d80-c698-a935ad614066") + expect_null(item$repository()) + }) + + test_that("we can set a repository", { + con <- Connect$new(server = "https://connect.example", api_key = "fake") + item <- content_item(con, "c3426b0b-e21d-3d80-c698-a935ad614066") + expect_PUT( + item$repo_set(repository = "https://github.com/posit-dev/connectapi"), + "https://connect.example/__api__/v1/content/c3426b0b/repository", + '{"repository":"https://github.com/posit-dev/connectapi",', + '"branch":"main","directory":".","polling":false}' + ) + }) + + test_that("we can enable polling", { + con <- Connect$new(server = "https://connect.example", api_key = "fake") + item <- content_item(con, "f2f37341-e21d-3d80-c698-a935ad614066") + expect_PATCH( + item$repo_enable(TRUE), + "https://connect.example/__api__/v1/content/f2f37341-e21d-3d80-c698-a935ad614066/repository", + '{"polling":true}' + ) }) }) From 5122c9147ff3a192387831464dde81f2e1240935 Mon Sep 17 00:00:00 2001 From: Neal Richardson Date: Sat, 11 Oct 2025 15:02:35 -0400 Subject: [PATCH 08/11] some integration test fixes --- R/git.R | 2 +- tests/integrated/test-git.R | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/R/git.R b/R/git.R index caa2268b..344590e3 100644 --- a/R/git.R +++ b/R/git.R @@ -130,7 +130,7 @@ deploy_repo <- function( deployed_content$repo_set( repository = repository, branch = branch, - subdirectory = subdirectory + directory = subdirectory ) task <- deployed_content$deploy() diff --git a/tests/integrated/test-git.R b/tests/integrated/test-git.R index 2d335a19..db5f9877 100644 --- a/tests/integrated/test-git.R +++ b/tests/integrated/test-git.R @@ -1,3 +1,5 @@ +skip_if_connect_older_than(test_conn_1, "2022.10.0") + cont1_name <- uuid::UUIDgenerate() cont1_title <- "Test Content 1" cont1_guid <- NULL From 4ab72150b6ebe3713a23183f6d6ff21bd16a8720 Mon Sep 17 00:00:00 2001 From: Neal Richardson Date: Sat, 11 Oct 2025 15:03:51 -0400 Subject: [PATCH 09/11] doc --- NEWS.md | 1 + man/Content.Rd | 43 +++++++++++++++++++++++++++--------------- man/ContentTask.Rd | 2 +- man/EnvironmentR6.Rd | 2 +- man/Vanity.Rd | 2 +- man/VariantR6.Rd | 2 +- man/VariantSchedule.Rd | 2 +- man/VariantTask.Rd | 2 +- 8 files changed, 35 insertions(+), 21 deletions(-) diff --git a/NEWS.md b/NEWS.md index 73c12987..e4ebb378 100644 --- a/NEWS.md +++ b/NEWS.md @@ -14,6 +14,7 @@ on the Connect server. (#272, #447) - New `lock_content()` and `unlock_content()` functions for locking and unlocking content items. (#453) +- Updated git-backed deployment functions to use v1 APIs (#459) # connectapi 0.8.0 diff --git a/man/Content.Rd b/man/Content.Rd index b2d9656b..c10a910a 100644 --- a/man/Content.Rd +++ b/man/Content.Rd @@ -52,7 +52,6 @@ Other R6 classes: \item \href{#method-Content-get_bundles}{\code{Content$get_bundles()}} \item \href{#method-Content-bundle_download}{\code{Content$bundle_download()}} \item \href{#method-Content-bundle_delete}{\code{Content$bundle_delete()}} -\item \href{#method-Content-internal_content}{\code{Content$internal_content()}} \item \href{#method-Content-update}{\code{Content$update()}} \item \href{#method-Content-danger_delete}{\code{Content$danger_delete()}} \item \href{#method-Content-get_url}{\code{Content$get_url()}} @@ -72,6 +71,7 @@ Other R6 classes: \item \href{#method-Content-environment_set}{\code{Content$environment_set()}} \item \href{#method-Content-environment_all}{\code{Content$environment_all()}} \item \href{#method-Content-deploy}{\code{Content$deploy()}} +\item \href{#method-Content-repository}{\code{Content$repository()}} \item \href{#method-Content-repo_enable}{\code{Content$repo_enable()}} \item \href{#method-Content-repo_set}{\code{Content$repo_set()}} \item \href{#method-Content-packages}{\code{Content$packages()}} @@ -159,16 +159,6 @@ Delete a content bundle. } \if{html}{\out{}} } -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-Content-internal_content}{}}} -\subsection{Method \code{internal_content()}}{ -Get this (remote) content item. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{Content$internal_content()}\if{html}{\out{
}} -} - } \if{html}{\out{
}} \if{html}{\out{}} @@ -465,18 +455,39 @@ Deploy this content } } \if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-Content-repository}{}}} +\subsection{Method \code{repository()}}{ +Get Git repository details +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{Content$repository()}\if{html}{\out{
}} +} + +\subsection{Returns}{ +NULL if no repo is set, otherwise a list with fields: +\itemize{ +\item repository +\item branch +\item directory +\item polling +\item last_error +\item last_known_commit +} +} +} +\if{html}{\out{
}} \if{html}{\out{}} \if{latex}{\out{\hypertarget{method-Content-repo_enable}{}}} \subsection{Method \code{repo_enable()}}{ Adjust Git polling. \subsection{Usage}{ -\if{html}{\out{
}}\preformatted{Content$repo_enable(enabled = TRUE)}\if{html}{\out{
}} +\if{html}{\out{
}}\preformatted{Content$repo_enable(polling = TRUE)}\if{html}{\out{
}} } \subsection{Arguments}{ \if{html}{\out{
}} \describe{ -\item{\code{enabled}}{Polling enabled.} +\item{\code{polling}}{Polling enabled.} } \if{html}{\out{
}} } @@ -487,7 +498,7 @@ Adjust Git polling. \subsection{Method \code{repo_set()}}{ Adjust Git repository \subsection{Usage}{ -\if{html}{\out{
}}\preformatted{Content$repo_set(repository, branch, subdirectory)}\if{html}{\out{
}} +\if{html}{\out{
}}\preformatted{Content$repo_set(repository, branch = "main", directory = ".", polling = FALSE)}\if{html}{\out{
}} } \subsection{Arguments}{ @@ -497,7 +508,9 @@ Adjust Git repository \item{\code{branch}}{Git repository branch} -\item{\code{subdirectory}}{Git repository directory} +\item{\code{directory}}{Git repository directory} + +\item{\code{polling}}{Whether to check for updates} } \if{html}{\out{}} } diff --git a/man/ContentTask.Rd b/man/ContentTask.Rd index f83bff85..fa71fc34 100644 --- a/man/ContentTask.Rd +++ b/man/ContentTask.Rd @@ -61,7 +61,6 @@ Other R6 classes:
  • connectapi::Content$get_content_remote()
  • connectapi::Content$get_dashboard_url()
  • connectapi::Content$get_url()
  • -
  • connectapi::Content$internal_content()
  • connectapi::Content$job()
  • connectapi::Content$jobs()
  • connectapi::Content$packages()
  • @@ -72,6 +71,7 @@ Other R6 classes:
  • connectapi::Content$register_job_kill_order()
  • connectapi::Content$repo_enable()
  • connectapi::Content$repo_set()
  • +
  • connectapi::Content$repository()
  • connectapi::Content$tag_delete()
  • connectapi::Content$tag_set()
  • connectapi::Content$tags()
  • diff --git a/man/EnvironmentR6.Rd b/man/EnvironmentR6.Rd index f179e4da..5fb5ceed 100644 --- a/man/EnvironmentR6.Rd +++ b/man/EnvironmentR6.Rd @@ -59,7 +59,6 @@ Other R6 classes:
  • connectapi::Content$get_content_remote()
  • connectapi::Content$get_dashboard_url()
  • connectapi::Content$get_url()
  • -
  • connectapi::Content$internal_content()
  • connectapi::Content$job()
  • connectapi::Content$jobs()
  • connectapi::Content$packages()
  • @@ -70,6 +69,7 @@ Other R6 classes:
  • connectapi::Content$register_job_kill_order()
  • connectapi::Content$repo_enable()
  • connectapi::Content$repo_set()
  • +
  • connectapi::Content$repository()
  • connectapi::Content$tag_delete()
  • connectapi::Content$tag_set()
  • connectapi::Content$tags()
  • diff --git a/man/Vanity.Rd b/man/Vanity.Rd index 80a1cdc6..a4f87129 100644 --- a/man/Vanity.Rd +++ b/man/Vanity.Rd @@ -57,7 +57,6 @@ Other R6 classes:
  • connectapi::Content$get_content_remote()
  • connectapi::Content$get_dashboard_url()
  • connectapi::Content$get_url()
  • -
  • connectapi::Content$internal_content()
  • connectapi::Content$job()
  • connectapi::Content$jobs()
  • connectapi::Content$packages()
  • @@ -68,6 +67,7 @@ Other R6 classes:
  • connectapi::Content$register_job_kill_order()
  • connectapi::Content$repo_enable()
  • connectapi::Content$repo_set()
  • +
  • connectapi::Content$repository()
  • connectapi::Content$tag_delete()
  • connectapi::Content$tag_set()
  • connectapi::Content$tags()
  • diff --git a/man/VariantR6.Rd b/man/VariantR6.Rd index cdf922d6..b8ffe18a 100644 --- a/man/VariantR6.Rd +++ b/man/VariantR6.Rd @@ -71,7 +71,6 @@ Other R6 classes:
  • connectapi::Content$environment_set()
  • connectapi::Content$get_bundles()
  • connectapi::Content$get_content_remote()
  • -
  • connectapi::Content$internal_content()
  • connectapi::Content$packages()
  • connectapi::Content$permissions()
  • connectapi::Content$permissions_add()
  • @@ -80,6 +79,7 @@ Other R6 classes:
  • connectapi::Content$register_job_kill_order()
  • connectapi::Content$repo_enable()
  • connectapi::Content$repo_set()
  • +
  • connectapi::Content$repository()
  • connectapi::Content$tag_delete()
  • connectapi::Content$tag_set()
  • connectapi::Content$tags()
  • diff --git a/man/VariantSchedule.Rd b/man/VariantSchedule.Rd index d7c23e29..b813ab11 100644 --- a/man/VariantSchedule.Rd +++ b/man/VariantSchedule.Rd @@ -62,7 +62,6 @@ Other R6 classes:
  • connectapi::Content$environment_set()
  • connectapi::Content$get_bundles()
  • connectapi::Content$get_content_remote()
  • -
  • connectapi::Content$internal_content()
  • connectapi::Content$packages()
  • connectapi::Content$permissions()
  • connectapi::Content$permissions_add()
  • @@ -71,6 +70,7 @@ Other R6 classes:
  • connectapi::Content$register_job_kill_order()
  • connectapi::Content$repo_enable()
  • connectapi::Content$repo_set()
  • +
  • connectapi::Content$repository()
  • connectapi::Content$tag_delete()
  • connectapi::Content$tag_set()
  • connectapi::Content$tags()
  • diff --git a/man/VariantTask.Rd b/man/VariantTask.Rd index 316a53a1..13d26485 100644 --- a/man/VariantTask.Rd +++ b/man/VariantTask.Rd @@ -59,7 +59,6 @@ Other R6 classes:
  • connectapi::Content$environment_set()
  • connectapi::Content$get_bundles()
  • connectapi::Content$get_content_remote()
  • -
  • connectapi::Content$internal_content()
  • connectapi::Content$packages()
  • connectapi::Content$permissions()
  • connectapi::Content$permissions_add()
  • @@ -68,6 +67,7 @@ Other R6 classes:
  • connectapi::Content$register_job_kill_order()
  • connectapi::Content$repo_enable()
  • connectapi::Content$repo_set()
  • +
  • connectapi::Content$repository()
  • connectapi::Content$tag_delete()
  • connectapi::Content$tag_set()
  • connectapi::Content$tags()
  • From 45784c5811e425f7c55a24532258c9d365c22d7e Mon Sep 17 00:00:00 2001 From: Neal Richardson Date: Wed, 15 Oct 2025 14:27:30 -0400 Subject: [PATCH 10/11] Update R/git.R --- R/git.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/git.R b/R/git.R index 344590e3..6c8af65c 100644 --- a/R/git.R +++ b/R/git.R @@ -157,7 +157,7 @@ deploy_repo_update <- function(content) { repo_data <- content$repository() if (is.null(repo_data)) { stop(glue::glue( - "Content item '{content$get_content()$guid}' is not git-backed content" + "Content item '{content$content$guid}' is not git-backed content" )) } branch_status <- repo_check_branches_ref(con, repo_data$repository) From 5df0b30d192c3e0d5496c93218a983b10caf24ef Mon Sep 17 00:00:00 2001 From: Neal Richardson Date: Fri, 17 Oct 2025 16:42:11 -0400 Subject: [PATCH 11/11] Add error_if_less_than --- R/content.R | 3 +++ 1 file changed, 3 insertions(+) diff --git a/R/content.R b/R/content.R index 71628928..794506c2 100644 --- a/R/content.R +++ b/R/content.R @@ -327,6 +327,7 @@ Content <- R6::R6Class( #' - last_known_commit repository = function() { con <- self$connect + error_if_less_than(con$version, "2022.10.0") guid <- self$content$guid resp <- con$GET( v1_url("content", guid, "repository"), @@ -343,6 +344,7 @@ Content <- R6::R6Class( #' @param polling Polling enabled. repo_enable = function(polling = TRUE) { con <- self$connect + error_if_less_than(con$version, "2022.10.0") guid <- self$content$guid con$PATCH( v1_url("content", guid, "repository"), @@ -361,6 +363,7 @@ Content <- R6::R6Class( polling = FALSE ) { guid <- self$content$guid + error_if_less_than(self$connect$version, "2022.10.0") self$connect$PUT( v1_url("content", guid, "repository"), body = list(