Skip to content

Commit 28632ba

Browse files
authored
Merge pull request #3 from rstudio/update-paging
Misc. Cleanup
2 parents ecb9916 + de87df2 commit 28632ba

18 files changed

+280
-84
lines changed

.Rbuildignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
^.*\.Rproj$
22
^\.Rproj\.user$
3+
^\.Renviron$

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@
22
.Rhistory
33
.RData
44
.Ruserdata
5+
.Renviron

DESCRIPTION

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ Imports:
1616
rlang,
1717
glue,
1818
fs,
19-
config
19+
config,
20+
yaml
2021
RoxygenNote: 6.1.1
2122
Suggests:
2223
rmarkdown,

NAMESPACE

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,7 @@ export(audit_r_versions)
66
export(audit_runas)
77
export(audit_vanity_urls)
88
export(cache_apps)
9-
export(content_ensure)
10-
export(deploy_bundle)
11-
export(deploy_github)
12-
export(dir_bundle)
13-
export(download_github)
14-
export(poll_task)
159
export(promote)
1610
export(tag_page)
11+
importFrom(utils,compareVersion)
12+
importFrom(utils,untar)

NEWS.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,12 @@ BREAKING:
55
- `connect$activate_bundle` to `connect$content_deploy`
66
- `connect$create_app` to `connect$content_create`
77
- `connect$upload_bundle` to `connect$content_upload`
8+
* Change some return types to be consistent with the API
9+
- `connect$content_upload` returns the response instead of `bundle_id`
10+
- `connect$content_deploy` returns the response instead of `task_id`
811
* Switch endpoints from using `app_id` to `guid`
912
* `get_task$start` renamed to `get_task$first`
13+
* `promote$app_name` renamed to `promote$name`
1014
* rename the package to `connectapi`
1115

1216
OTHER:

R/connect.R

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ Connect <- R6::R6Class(
2929
tags = NULL,
3030
tag_map = NULL,
3131

32-
initialize = function(host = NA, api_key = NA) {
32+
initialize = function(host = Sys.getenv("RSTUDIO_CONNECT_SERVER", NA), api_key = Sys.getenv("RSTUDIO_CONNECT_API_KEY", NA)) {
33+
message(glue::glue("Defining Connect with host: {host}"))
3334
self$host = host
3435
self$api_key = api_key
3536
},
@@ -142,14 +143,14 @@ Connect <- R6::R6Class(
142143
self$POST(
143144
path,
144145
c(
145-
list(name = tolower(gsub("\\s","",name)), title = title ),
146+
list(name = tolower(gsub("\\s","",name)), title = title),
146147
other_params
147148
)
148149
)
149150
},
150151

151152
download_bundle = function(bundle_id, to_path = tempfile()) {
152-
path <- sprintf('bundles/%d/download', bundle_id)
153+
path <- glue::glue('bundles/{bundle_id}/download')
153154
self$GET(path, httr::write_disk(to_path), "raw")
154155
to_path
155156
},
@@ -158,15 +159,13 @@ Connect <- R6::R6Class(
158159
# todo : add X-Content-Checksum
159160
path <- glue::glue('v1/experimental/content/{guid}/upload')
160161
res <- self$POST(path, httr::upload_file(bundle_path), 'raw')
161-
new_bundle_id <- res[["task_id"]]
162-
new_bundle_id
162+
return(res)
163163
},
164164

165165
content_deploy = function(guid, bundle_id) {
166166
path <- sprintf('v1/experimental/content/%s/deploy', guid)
167167
res <- self$POST(path, list(bundle_id = as.character(bundle_id)))
168-
task_id <- res[["task_id"]]
169-
task_id
168+
return(res)
170169
},
171170

172171
get_content = function(guid) {
@@ -338,13 +337,3 @@ check_debug <- function(req, res) {
338337
}
339338
}
340339

341-
connect_input <- function(connect) {
342-
if (R6::is.R6(connect)) {
343-
# is an R6 object... we presume the right type
344-
return(connect)
345-
} else if (is.list(connect) && c("host","api_key") %in% names(connect)) {
346-
return(Connect$new(host = connect[["host"]], api_key = connect[["api_key"]]))
347-
} else {
348-
stop("Input 'connect' is not an R6 object or a named list")
349-
}
350-
}

R/connectapi.R

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#' @importFrom utils compareVersion
2+
#' @importFrom utils untar
3+
"_PACKAGE"
4+
5+
utils::globalVariables(
6+
c(
7+
"r_version"
8+
)
9+
)

R/github.R

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
#' @export
21
download_github <- function(repo, ref = "master") {
32
current_wd <- getwd()
43
on.exit(setwd(current_wd), add = TRUE)
@@ -23,7 +22,6 @@ download_github <- function(repo, ref = "master") {
2322
return(final_loc)
2423
}
2524

26-
#' @export
2725
deploy_github <- function(connect, repo, ref = "master", filename = ".connect.yml") {
2826
download_dir <- download_github(repo = repo, ref = ref)
2927
current_wd <- getwd()

R/promote.R

Lines changed: 48 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
#' publisher priviliges.
1212
#' @param from_key An API key on the originating "from" server. The API key must
1313
#' belong to a user with collaborator access to the content to be promoted.
14-
#' @param app_name The name of the content on the originating "from" server.
14+
#' @param name The name of the content on the originating "from" server.
1515
#' If content with the same name is found on the destination server,
1616
#' the content will be updated. If no content on the destination server
1717
#' has a matching name, a new endpoint will be created.
@@ -21,7 +21,7 @@ promote <- function(from,
2121
to,
2222
to_key,
2323
from_key,
24-
app_name) {
24+
name) {
2525

2626
# TODO Validate Inputs
2727

@@ -30,70 +30,73 @@ promote <- function(from,
3030
to_client <- Connect$new(host = to, api_key = to_key)
3131

3232
# find app on "from" server
33-
from_app <- from_client$get_apps(list(name = app_name))
33+
from_app <- from_client$get_apps(list(name = name))
3434
if (length(from_app) != 1) {
35-
stop(sprintf('Found %d apps matching app name %s on %s. Content must have a unique name.', length(from_app), app_name, from))
35+
stop(sprintf('Found %d apps matching app name %s on %s. Content must have a unique name.', length(from_app), name, from))
3636
}
3737

3838
# download bundle
3939
bundle <- from_client$download_bundle(from_app[[1]]$bundle_id)
4040

4141
# find or create app to update
42-
to_app <- to_client$get_apps(list(name = app_name))
43-
if (length(to_app) > 1) {
44-
stop(sprintf('Found %d apps matching %s on %s, content must have a unique name.', length(to_app), app_name, to))
45-
} else if (length(to_app) == 0) {
46-
# create app
47-
to_app <- to_client$create_app(app_name)
48-
warning(sprintf('Creating NEW app %d with name %s on %s', to_app$id, app_name, to))
49-
} else {
50-
to_app <- to_app[[1]]
51-
warning(sprintf('Updating EXISTING app %d with name %s on %s', to_app$id, app_name, to))
52-
}
42+
to_app <- content_ensure(connect = to_client, name = name)
5343

54-
task_id <- deploy_bundle(
55-
connect = to_client,
56-
bundle = bundle,
57-
app_id = to_app$id
58-
)
44+
bundle_id <- to_client$content_upload(bundle_path = bundle, guid = to_app[["guid"]])[["bundle_id"]]
45+
task_id <- to_client$content_deploy(guid = to_app[["guid"]], bundle_id = bundle_id)[["task_id"]]
5946

6047
poll_task(connect = to_client, task_id = task_id)
6148

62-
to_app_url <- app$url
49+
to_app_url <- to_app$url
6350

6451
return(to_app_url)
6552
}
6653

67-
#' @export
68-
content_ensure <- function(connect, name = random_name(), title = name, ...) {
54+
content_ensure <- function(connect, name = random_name(), title = name, guid = NULL, ...) {
6955

70-
content <- connect$get_apps(list(name = name))
71-
if (length(content) > 1) {
72-
stop(glue::glue("Found {length(to_content)} content items ",
73-
"matching {content_name} on {connect$host}",
74-
", content must have a unique name."))
75-
} else if (length(content) == 0) {
76-
# create app
77-
content <- connect$content_create(
78-
name = name,
79-
title = title,
80-
...
81-
)
82-
message(glue::glue("Creating NEW content {content$guid} ",
83-
"with name {name} on {connect$host}"))
56+
if (!is.null(guid)) {
57+
# guid-based deployment
58+
# just in case we get a 404 back...
59+
content <- tryCatch(connect$get_content(guid = guid), error = function(e){return(NULL)})
60+
if (is.null(content)) {
61+
warning(glue::glue(
62+
"guid {guid} was not found on {connect$host}.",
63+
"Creating new content with name {name}"))
64+
content <- connect$content_create(
65+
name = name,
66+
title = title,
67+
...
68+
)
69+
}
8470
} else {
85-
content <- content[[1]]
86-
message(glue::glue("Found EXISTING content {content$guid} with ",
87-
"name {name} on {connect$host}"))
71+
# name-based deployment
72+
content <- connect$get_apps(list(name = name))
73+
if (length(content) > 1) {
74+
stop(glue::glue("Found {length(to_content)} content items ",
75+
"matching {name} on {connect$host}",
76+
", content must have a unique name."))
77+
} else if (length(content) == 0) {
78+
# create app
79+
content <- connect$content_create(
80+
name = name,
81+
title = title,
82+
...
83+
)
84+
message(glue::glue("Creating NEW content {content$guid} ",
85+
"with name {name} on {connect$host}"))
86+
} else {
87+
content <- content[[1]]
88+
message(glue::glue("Found EXISTING content {content$guid} with ",
89+
"name {name} on {connect$host}"))
90+
# update values...? need a PUT endpoint
91+
}
8892
}
8993
return(content)
9094
}
9195

92-
random_name <- function(length = 13) {
96+
random_name <- function(length = 25) {
9397
tolower(paste(sample(LETTERS, length, replace = TRUE), collapse = ""))
9498
}
9599

96-
#' @export
97100
dir_bundle <- function(path = ".", filename = "bundle.tar.gz") {
98101
before_wd <- getwd()
99102
setwd(path)
@@ -104,18 +107,16 @@ dir_bundle <- function(path = ".", filename = "bundle.tar.gz") {
104107
return(fs::path_abs(filename))
105108
}
106109

107-
#' @export
108-
deploy_bundle <- function(connect, bundle, app_id){
110+
deploy_bundle <- function(connect, bundle_path, guid){
109111
#upload bundle
110-
new_bundle_id <- connect$upload_bundle(bundle, app_id)
112+
new_bundle_id <- connect$content_upload(bundle_path = bundle_path, guid = guid)[["bundle_id"]]
111113

112114
#activate bundle
113-
task_id <- connect$activate_bundle(app_id, new_bundle_id)
115+
task_id <- connect$content_deploy(guid = guid, bundle_id = new_bundle_id)[["task_id"]]
114116

115117
return(task_id)
116118
}
117119

118-
#' @export
119120
poll_task <- function(connect, task_id, wait = 1) {
120121
finished <- FALSE
121122
code <- -1

R/utils.R

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
# this function helps creating query parameters
12
safe_query <- function(expr, prefix = "", collapse = "|") {
23
if (is.null(expr)) {
34
return("")
@@ -6,6 +7,9 @@ safe_query <- function(expr, prefix = "", collapse = "|") {
67
}
78
}
89

10+
11+
# experimental functions
12+
913
check_connect_version <- function(connect) {
1014
settings <- connect$get_server_settings()
1115
using_version <- settings[["version"]]
@@ -30,3 +34,14 @@ check_connect_version <- function(connect) {
3034
}
3135

3236
tested_version <- "1.7.0-11"
37+
38+
connect_input <- function(connect) {
39+
if (R6::is.R6(connect)) {
40+
# is an R6 object... we presume the right type
41+
return(connect)
42+
} else if (is.list(connect) && c("host","api_key") %in% names(connect)) {
43+
return(Connect$new(host = connect[["host"]], api_key = connect[["api_key"]]))
44+
} else {
45+
stop("Input 'connect' is not an R6 object or a named list")
46+
}
47+
}

R/yaml.R

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,23 @@
1+
yaml_template <- function(file = NULL){
2+
obj <- list(
3+
"default" = list(
4+
"content" = list(
5+
list(
6+
"title" = "Title of the Content",
7+
"path" = "./",
8+
"description" = "Content description"
9+
)
10+
)
11+
)
12+
)
13+
14+
if (!is.null(file)) {
15+
yaml::write_yaml(x = obj, file = file)
16+
} else {
17+
return(cat(yaml::as.yaml(obj)))
18+
}
19+
}
20+
121
yaml_content <- function(connect, filename = ".connect.yml") {
222
cfg <- config::get(value = "content", file = filename)
323

@@ -9,7 +29,7 @@ yaml_content <- function(connect, filename = ".connect.yml") {
929
connect = connect
1030
)
1131

12-
return(cfg)
32+
return(res)
1333
}
1434

1535
yaml_content_deploy <- function(
@@ -20,10 +40,11 @@ yaml_content_deploy <- function(
2040
tag = NULL,
2141
url = NULL,
2242
image = NULL,
43+
wait = TRUE,
2344
...
2445
) {
25-
orig_connect <- connect
26-
connect <- connect_input(connect)
46+
#orig_connect <- connect
47+
#connect <- connect_input(connect)
2748
bundle_path <- dir_bundle(path = path)
2849

2950
c_obj <- rlang::exec(
@@ -43,14 +64,16 @@ yaml_content_deploy <- function(
4364

4465
c_task <- connect$content_deploy(
4566
guid = c_guid,
46-
bundle_id = c_upload
67+
bundle_id = c_upload[["bundle_id"]]
4768
)
4869

49-
# wait for task to complete
50-
poll_task(
51-
connect,
52-
c_task
53-
)
70+
if (wait) {
71+
# wait for task to complete
72+
poll_task(
73+
connect,
74+
c_task[["task_id"]]
75+
)
76+
}
5477

5578
# tag helper
5679
if (!is.null(tag)) {
@@ -66,4 +89,7 @@ yaml_content_deploy <- function(
6689
if (!is.null(image)) {
6790
# need public APIs
6891
}
92+
93+
# return the content info _and_ the task info
94+
return(list(content = c_obj, task = c_task))
6995
}

0 commit comments

Comments
 (0)