diff --git a/.github/workflows/build-deploy.yaml b/.github/workflows/build-deploy.yaml new file mode 100644 index 0000000..30ffecc --- /dev/null +++ b/.github/workflows/build-deploy.yaml @@ -0,0 +1,92 @@ +name: Build & Deploy Docker Containers +on: + # We'll trigger this workflow when a PR is submitted to make sure + # your application still builds successfully with the new commits. + pull_request: [] + # We'll also trigger this workflow when you want to deploy your container. + # This means any push to main. You might want to do a release trigger. + push: + branches: + - main + - master + # Let's also trigger a build and publish of your container when + # you release a new version. You can use "created" here instead of published. + release: + types: [published] + +jobs: + deploy-images: + runs-on: ubuntu-latest + + # Define your registry and repository here. + # These are for the GitHub Container registry, you can also use + # Quay.io or another OCI registry + env: + registry: ghcr.io + username: degauss-org + repository: census_block_group + + strategy: + # Even if one docker container build fails we want the others to continue. + fail-fast: false + # A matrix of Dockerfile paths and associated tags + # Dockerfile in root builds to tag latest + matrix: + dockerfile: [[Dockerfile, latest]] + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Set Container Tag Normal + run: | + container="${{ env.registry }}/${{ env.username}}/${{ env.repository }}:${{ matrix.dockerfile[1] }}" + echo "container=${container}" >> $GITHUB_ENV + # On a new release create a container with the same tag as the release. + - name: Set Container Tag Release + if: github.event_name == 'release' + run: | + versioned="${{ env.registry }}/${{ env.username}}/${{ env.repository }}:${GITHUB_REF##*/}" + echo "versioned=${versioned}" >> $GITHUB_ENV + # On a PR create a "test" container with the same tag as the branch name. + - name: Set Branch Tag Release + if: github.event_name == 'pull_request' + run: | + versioned="${{ env.registry }}/${{ env.username}}/${{ env.repository }}:${GITHUB_HEAD_REF}" + echo "versioned=${versioned}" >> $GITHUB_ENV + - name: Build ${{ matrix.dockerfile[1] }} + run: | + printf "Preparing to build ${{ env.container }} from ${{ matrix.dockerfile[0] }}" + if [ ! -f "${{ matrix.dockerfile[0]}}" ]; then + printf "Dockerfile ${{ matrix.dockerfile[0] }} does not exist" + exit 1; + fi + docker build -f ${{ matrix.dockerfile[0] }} -t ${{ env.container }} . + docker images + - name: Test ${{ matrix.dockerfile[1] }} + run: | + printf "Testing ${{ env.container }}" + docker run --rm -v "${PWD}/test":/tmp ${{ env.container }} my_address_file_geocoded.csv 2010 + - name: Log in to GitHub Container Registry + uses: docker/login-action@v1 + with: + registry: ${{ env.registry }} + username: ${{ env.username }} + password: ${{ secrets.GITHUB_TOKEN }} + + # Example variables for a non GitHub registry like Quay or Docker Hub + # username: ${{ secrets.DOCKERHUB_USERNAME }} + # password: ${{ secrets.DOCKERHUB_TOKEN }} + + # Deploy branch container on pull request + - name: Test Deploy ${{ env.versioned }} + if: github.event_name == 'pull_request' + run: | + docker tag ${{ env.container }} ${{ env.versioned }} + docker push ${{ env.versioned }} + # Deploy release container on release + - name: Deploy ${{ env.versioned }} + if: github.event_name == 'release' + run: | + docker tag ${{ env.container }} ${{ env.versioned }} + docker push ${{ env.versioned }} + docker push ${{ env.container }} diff --git a/Dockerfile b/Dockerfile index 34844d5..04495e6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,7 +2,7 @@ FROM rocker/r-ver:4.0.0 RUN R --quiet -e "install.packages('remotes', repos = 'https://packagemanager.rstudio.com/all/__linux__/focal/latest')" # make sure version matches what is used in the project: packageVersion('renv') -ENV RENV_VERSION 0.13.2 +ENV RENV_VERSION 0.14.0 RUN R --quiet -e "remotes::install_github('rstudio/renv@${RENV_VERSION}')" WORKDIR /app @@ -19,12 +19,12 @@ RUN apt-get update \ COPY renv.lock . RUN R --quiet -e "renv::restore(repos = c(CRAN = 'https://packagemanager.rstudio.com/all/__linux__/focal/latest'))" -COPY block_groups_2020_5072.rds . -COPY block_groups_2010_5072.rds . -COPY block_groups_2000_5072.rds . -COPY block_groups_1990_5072.rds . -COPY tracts_1980_5072.rds . -COPY tracts_1970_5072.rds . +ADD https://geomarker.s3.us-east-2.amazonaws.com/geometries/block_groups_2020_5072.rds . +ADD https://geomarker.s3.us-east-2.amazonaws.com/geometries/block_groups_2010_5072.rds . +ADD https://geomarker.s3.us-east-2.amazonaws.com/geometries/block_groups_2000_5072.rds . +ADD https://geomarker.s3.us-east-2.amazonaws.com/geometries/block_groups_1990_5072.rds . +ADD https://geomarker.s3.us-east-2.amazonaws.com/geometries/tracts_1980_5072.rds . +ADD https://geomarker.s3.us-east-2.amazonaws.com/geometries/tracts_1970_5072.rds . COPY census_block_group.R . WORKDIR /tmp diff --git a/README.md b/README.md index 51af17f..c3f3043 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ ## DeGAUSS example call ```sh -docker run --rm -v $PWD:/tmp degauss/census_block_group:0.4.0 my_address_file_geocoded.csv 2010 +docker run --rm -v $PWD:/tmp degauss/census_block_group:0.4.1 my_address_file_geocoded.csv 2010 ``` * The first argument (`my_address_file_geocoded.csv`) is the name of your geocoded csv file. diff --git a/census_block_group.R b/census_block_group.R index 9c15eb9..91cf58a 100755 --- a/census_block_group.R +++ b/census_block_group.R @@ -1,7 +1,7 @@ #!/usr/local/bin/Rscript dht::greeting(geomarker_name = 'census_block_group', - version = '0.4.0', + version = '0.4.1', description = 'adds census block group or tract identifiers to geocoded addresses') dht::qlibrary(dplyr) @@ -51,7 +51,7 @@ if (opt$census_year %in% c('1980', '1970')) { } message('\nfinding containing geography for each point...') -d <- sf::st_join(d, geography, left = FALSE) +d <- sf::st_join(d, geography, left = FALSE, largest = TRUE) if(! opt$census_year %in% c('1980', '1970')) { d <- d %>% diff --git a/renv.lock b/renv.lock index 2236b4b..7772f3d 100644 --- a/renv.lock +++ b/renv.lock @@ -46,10 +46,10 @@ }, "R6": { "Package": "R6", - "Version": "2.5.0", + "Version": "2.5.1", "Source": "Repository", - "Repository": "CRAN", - "Hash": "b203113193e70978a696b2809525649d" + "Repository": "RSPM", + "Hash": "470851b6d5d0ac559e9d01bb352b4021" }, "RColorBrewer": { "Package": "RColorBrewer", @@ -130,10 +130,10 @@ }, "cli": { "Package": "cli", - "Version": "2.3.1", + "Version": "3.1.0", "Source": "Repository", "Repository": "CRAN", - "Hash": "3e3f28efcadfda442cd18651fbcbbecf" + "Hash": "66a3834e54593c89d8beefb312347e58" }, "clipr": { "Package": "clipr", @@ -151,24 +151,24 @@ }, "cpp11": { "Package": "cpp11", - "Version": "0.2.6", + "Version": "0.4.2", "Source": "Repository", - "Repository": "CRAN", - "Hash": "f08909ebdad90b19d8d3930da4220564" + "Repository": "RSPM", + "Hash": "fa53ce256cd280f468c080a58ea5ba8c" }, "crayon": { "Package": "crayon", - "Version": "1.4.1", + "Version": "1.4.2", "Source": "Repository", - "Repository": "CRAN", - "Hash": "e75525c55c70e5f4f78c9960a4b402e9" + "Repository": "RSPM", + "Hash": "0a6a65d92bd45b47b94b84244b528d17" }, "credentials": { "Package": "credentials", - "Version": "1.3.0", + "Version": "1.3.2", "Source": "Repository", - "Repository": "CRAN", - "Hash": "a96728288c75a814c900af9da84387be" + "Repository": "RSPM", + "Hash": "93762d0a34d78e6a025efdbfb5c6bb41" }, "curl": { "Package": "curl", @@ -186,22 +186,22 @@ }, "desc": { "Package": "desc", - "Version": "1.2.0", + "Version": "1.4.0", "Source": "Repository", - "Repository": "CRAN", - "Hash": "6c8fe8fa26a23b79949375d372c7b395" + "Repository": "RSPM", + "Hash": "28763d08fadd0b733e3cee9dab4e12fe" }, "dht": { "Package": "dht", - "Version": "0.0.0.9000", + "Version": "0.3.0", "Source": "GitHub", "RemoteType": "github", "RemoteHost": "api.github.com", "RemoteRepo": "dht", "RemoteUsername": "degauss-org", "RemoteRef": "HEAD", - "RemoteSha": "213b313a13c9a089c2ebbab8ca24a32e5d65975d", - "Hash": "175011676ad4df8d0a66331e3d89c6c1" + "RemoteSha": "aaf71e0c0c7f29b69d0de2f6865a83bd95156a00", + "Hash": "b3cc8e7666d85913c45d76ae58acbc57" }, "digest": { "Package": "digest", @@ -282,10 +282,10 @@ }, "generics": { "Package": "generics", - "Version": "0.1.0", + "Version": "0.1.1", "Source": "Repository", - "Repository": "CRAN", - "Hash": "4d243a9c10b00589889fe32314ffd902" + "Repository": "RSPM", + "Hash": "3f6bcfb0ee5d671d9fd1893d2faa79cb" }, "gert": { "Package": "gert", @@ -303,10 +303,10 @@ }, "gh": { "Package": "gh", - "Version": "1.2.0", + "Version": "1.3.0", "Source": "Repository", - "Repository": "CRAN", - "Hash": "05129b4387282404780d2f8593636388" + "Repository": "RSPM", + "Hash": "38c2580abbda249bd6afeec00d14f531" }, "gitcreds": { "Package": "gitcreds", @@ -408,10 +408,10 @@ }, "lifecycle": { "Package": "lifecycle", - "Version": "1.0.0", + "Version": "1.0.1", "Source": "Repository", - "Repository": "CRAN", - "Hash": "3471fb65971f1a7b2d4ae7848cf2db8d" + "Repository": "RSPM", + "Hash": "a6b6d352e3ed897373ab19d8395c98d0" }, "lubridate": { "Package": "lubridate", @@ -548,10 +548,10 @@ }, "ps": { "Package": "ps", - "Version": "1.3.2", + "Version": "1.6.0", "Source": "Repository", "Repository": "CRAN", - "Hash": "98777535b61c57d1749344345e2a4ccd" + "Hash": "32620e2001c1dce1af49c49dccbb9420" }, "purrr": { "Package": "purrr", @@ -590,10 +590,10 @@ }, "renv": { "Package": "renv", - "Version": "0.12.5", + "Version": "0.14.0", "Source": "Repository", "Repository": "CRAN", - "Hash": "5c0cdb37f063c58cdab3c7e9fbb8bd2c" + "Hash": "30e5eba91b67f7f4d75d31de14bbfbdc" }, "reprex": { "Package": "reprex", @@ -758,10 +758,10 @@ }, "usethis": { "Package": "usethis", - "Version": "2.0.1", + "Version": "2.1.5", "Source": "Repository", - "Repository": "CRAN", - "Hash": "360e904f9e623286e1a0c6ca0a98c5f6" + "Repository": "RSPM", + "Hash": "c499f488e6dd7718accffaee5bc5a79b" }, "utf8": { "Package": "utf8", @@ -800,10 +800,10 @@ }, "withr": { "Package": "withr", - "Version": "2.4.1", + "Version": "2.4.3", "Source": "Repository", - "Repository": "CRAN", - "Hash": "caf4781c674ffa549a4676d2d77b13cc" + "Repository": "RSPM", + "Hash": "a376b424c4817cda4920bbbeb3364e85" }, "xfun": { "Package": "xfun", diff --git a/renv/.gitignore b/renv/.gitignore index 574c256..993aebf 100644 --- a/renv/.gitignore +++ b/renv/.gitignore @@ -1,3 +1,4 @@ +local/ lock/ library/ python/ diff --git a/renv/activate.R b/renv/activate.R index 5be4bbd..304fd90 100644 --- a/renv/activate.R +++ b/renv/activate.R @@ -2,13 +2,27 @@ local({ # the requested version of renv - version <- "0.12.5" + version <- "0.14.0" # the project directory project <- getwd() + # allow environment variable to control activation + activate <- Sys.getenv("RENV_ACTIVATE_PROJECT") + if (!nzchar(activate)) { + + # don't auto-activate when R CMD INSTALL is running + if (nzchar(Sys.getenv("R_INSTALL_PKG"))) + return(FALSE) + + } + + # bail if activation was explicitly disabled + if (tolower(activate) %in% c("false", "f", "0")) + return(FALSE) + # avoid recursion - if (!is.na(Sys.getenv("RENV_R_INITIALIZING", unset = NA))) + if (nzchar(Sys.getenv("RENV_R_INITIALIZING"))) return(invisible(TRUE)) # signal that we're loading renv during R startup @@ -70,10 +84,13 @@ local({ repos <- getOption("repos") # ensure @CRAN@ entries are resolved - repos[repos == "@CRAN@"] <- "https://cloud.r-project.org" + repos[repos == "@CRAN@"] <- getOption( + "renv.repos.cran", + "https://cloud.r-project.org" + ) # add in renv.bootstrap.repos if set - default <- c(CRAN = "https://cloud.r-project.org") + default <- c(FALLBACK = "https://cloud.r-project.org") extra <- getOption("renv.bootstrap.repos", default = default) repos <- c(repos, extra) @@ -134,16 +151,20 @@ local({ renv_bootstrap_download_cran_latest <- function(version) { - repos <- renv_bootstrap_download_cran_latest_find(version) + spec <- renv_bootstrap_download_cran_latest_find(version) + + message("* Downloading renv ", version, " ... ", appendLF = FALSE) - message("* Downloading renv ", version, " from CRAN ... ", appendLF = FALSE) + type <- spec$type + repos <- spec$repos info <- tryCatch( utils::download.packages( - pkgs = "renv", - repos = repos, + pkgs = "renv", destdir = tempdir(), - quiet = TRUE + repos = repos, + type = type, + quiet = TRUE ), condition = identity ) @@ -153,36 +174,52 @@ local({ return(FALSE) } - message("OK") + # report success and return + message("OK (downloaded ", type, ")") info[1, 2] } renv_bootstrap_download_cran_latest_find <- function(version) { - all <- renv_bootstrap_repos() + # check whether binaries are supported on this system + binary <- + getOption("renv.bootstrap.binary", default = TRUE) && + !identical(.Platform$pkgType, "source") && + !identical(getOption("pkgType"), "source") && + Sys.info()[["sysname"]] %in% c("Darwin", "Windows") - for (repos in all) { + types <- c(if (binary) "binary", "source") - db <- tryCatch( - as.data.frame( - x = utils::available.packages(repos = repos), - stringsAsFactors = FALSE - ), - error = identity - ) + # iterate over types + repositories + for (type in types) { + for (repos in renv_bootstrap_repos()) { - if (inherits(db, "error")) - next + # retrieve package database + db <- tryCatch( + as.data.frame( + utils::available.packages(type = type, repos = repos), + stringsAsFactors = FALSE + ), + error = identity + ) - entry <- db[db$Package %in% "renv" & db$Version %in% version, ] - if (nrow(entry) == 0) - next + if (inherits(db, "error")) + next - return(repos) + # check for compatible entry + entry <- db[db$Package %in% "renv" & db$Version %in% version, ] + if (nrow(entry) == 0) + next + + # found it; return spec to caller + spec <- list(entry = entry, type = type, repos = repos) + return(spec) + } } + # if we got here, we failed to find renv fmt <- "renv %s is not available from your declared package repositories" stop(sprintf(fmt, version)) @@ -195,7 +232,7 @@ local({ urls <- file.path(repos, "src/contrib/Archive/renv", name) destfile <- file.path(tempdir(), name) - message("* Downloading renv ", version, " from CRAN archive ... ", appendLF = FALSE) + message("* Downloading renv ", version, " ... ", appendLF = FALSE) for (url in urls) { @@ -286,7 +323,7 @@ local({ } - renv_bootstrap_prefix <- function() { + renv_bootstrap_platform_prefix <- function() { # construct version prefix version <- paste(R.version$major, R.version$minor, sep = ".") @@ -305,8 +342,8 @@ local({ components <- c(prefix, R.version$platform) # include prefix if provided by user - prefix <- Sys.getenv("RENV_PATHS_PREFIX") - if (nzchar(prefix)) + prefix <- renv_bootstrap_platform_prefix_impl() + if (!is.na(prefix) && nzchar(prefix)) components <- c(prefix, components) # build prefix @@ -314,6 +351,139 @@ local({ } + renv_bootstrap_platform_prefix_impl <- function() { + + # if an explicit prefix has been supplied, use it + prefix <- Sys.getenv("RENV_PATHS_PREFIX", unset = NA) + if (!is.na(prefix)) + return(prefix) + + # if the user has requested an automatic prefix, generate it + auto <- Sys.getenv("RENV_PATHS_PREFIX_AUTO", unset = NA) + if (auto %in% c("TRUE", "True", "true", "1")) + return(renv_bootstrap_platform_prefix_auto()) + + # empty string on failure + "" + + } + + renv_bootstrap_platform_prefix_auto <- function() { + + prefix <- tryCatch(renv_bootstrap_platform_os(), error = identity) + if (inherits(prefix, "error") || prefix %in% "unknown") { + + msg <- paste( + "failed to infer current operating system", + "please file a bug report at https://github.com/rstudio/renv/issues", + sep = "; " + ) + + warning(msg) + + } + + prefix + + } + + renv_bootstrap_platform_os <- function() { + + sysinfo <- Sys.info() + sysname <- sysinfo[["sysname"]] + + # handle Windows + macOS up front + if (sysname == "Windows") + return("windows") + else if (sysname == "Darwin") + return("macos") + + # check for os-release files + for (file in c("/etc/os-release", "/usr/lib/os-release")) + if (file.exists(file)) + return(renv_bootstrap_platform_os_via_os_release(file, sysinfo)) + + # check for redhat-release files + if (file.exists("/etc/redhat-release")) + return(renv_bootstrap_platform_os_via_redhat_release()) + + "unknown" + + } + + renv_bootstrap_platform_os_via_os_release <- function(file, sysinfo) { + + # read /etc/os-release + release <- utils::read.table( + file = file, + sep = "=", + quote = c("\"", "'"), + col.names = c("Key", "Value"), + comment.char = "#", + stringsAsFactors = FALSE + ) + + vars <- as.list(release$Value) + names(vars) <- release$Key + + # get os name + os <- tolower(sysinfo[["sysname"]]) + + # read id + id <- "unknown" + for (field in c("ID", "ID_LIKE")) { + if (field %in% names(vars) && nzchar(vars[[field]])) { + id <- vars[[field]] + break + } + } + + # read version + version <- "unknown" + for (field in c("UBUNTU_CODENAME", "VERSION_CODENAME", "VERSION_ID", "BUILD_ID")) { + if (field %in% names(vars) && nzchar(vars[[field]])) { + version <- vars[[field]] + break + } + } + + # join together + paste(c(os, id, version), collapse = "-") + + } + + renv_bootstrap_platform_os_via_redhat_release <- function() { + + # read /etc/redhat-release + contents <- readLines("/etc/redhat-release", warn = FALSE) + + # infer id + id <- if (grepl("centos", contents, ignore.case = TRUE)) + "centos" + else if (grepl("redhat", contents, ignore.case = TRUE)) + "redhat" + else + "unknown" + + # try to find a version component (very hacky) + version <- "unknown" + + parts <- strsplit(contents, "[[:space:]]")[[1L]] + for (part in parts) { + + nv <- tryCatch(numeric_version(part), error = identity) + if (inherits(nv, "error")) + next + + version <- nv[1, 1] + break + + } + + paste(c("linux", id, version), collapse = "-") + + } + renv_bootstrap_library_root_name <- function(project) { # use project name as-is if requested @@ -339,7 +509,8 @@ local({ return(file.path(path, name)) } - file.path(project, "renv/library") + prefix <- renv_bootstrap_profile_prefix() + paste(c(project, prefix, "renv/library"), collapse = "/") } @@ -396,12 +567,69 @@ local({ TRUE } + + renv_bootstrap_profile_load <- function(project) { + + # if RENV_PROFILE is already set, just use that + profile <- Sys.getenv("RENV_PROFILE", unset = NA) + if (!is.na(profile) && nzchar(profile)) + return(profile) + + # check for a profile file (nothing to do if it doesn't exist) + path <- file.path(project, "renv/local/profile") + if (!file.exists(path)) + return(NULL) + + # read the profile, and set it if it exists + contents <- readLines(path, warn = FALSE) + if (length(contents) == 0L) + return(NULL) + + # set RENV_PROFILE + profile <- contents[[1L]] + if (nzchar(profile)) + Sys.setenv(RENV_PROFILE = profile) + + profile + + } + + renv_bootstrap_profile_prefix <- function() { + profile <- renv_bootstrap_profile_get() + if (!is.null(profile)) + return(file.path("renv/profiles", profile)) + } + + renv_bootstrap_profile_get <- function() { + profile <- Sys.getenv("RENV_PROFILE", unset = "") + renv_bootstrap_profile_normalize(profile) + } + + renv_bootstrap_profile_set <- function(profile) { + profile <- renv_bootstrap_profile_normalize(profile) + if (is.null(profile)) + Sys.unsetenv("RENV_PROFILE") + else + Sys.setenv(RENV_PROFILE = profile) + } + + renv_bootstrap_profile_normalize <- function(profile) { + + if (is.null(profile) || profile %in% c("", "default")) + return(NULL) + + profile + + } + + # load the renv profile, if any + renv_bootstrap_profile_load(project) # construct path to library root root <- renv_bootstrap_library_root(project) # construct library prefix for platform - prefix <- renv_bootstrap_prefix() + prefix <- renv_bootstrap_platform_prefix() # construct full libpath libpath <- file.path(root, prefix)