Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
georgestagg committed May 3, 2024
0 parents commit caba124
Show file tree
Hide file tree
Showing 6 changed files with 276 additions and 0 deletions.
87 changes: 87 additions & 0 deletions .github/workflows/deploy-app.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# Basic example of a GitHub Actions workflow that builds a Shiny app and deploys
# it to GitHub Pages.
#
# The agreed upon contract is:
#
# - Inspect the root directory for package dependencies
# - Install R and the found packages
# - Export the Shiny app directory to `./site`
# - On push events, deploy the exported app to GitHub Pages
#
# If this contract is not met or could be easily improved for others,
# please open a new Issue https://github.com/posit-dev/r-shinylive/
#
# The _magic_ of this workflow is in the `shinylive::export()` function, which
# creates a static version of the Shiny app into the folder `./site`.
# The exported app folder is then uploaded and deployed to GitHub Pages.
#
# When deploying to GitHub Pages, be sure to have the appropriate write
# permissions for your token (`pages` and `id-token`).

name: Deploy app

on:
push:
branches: [main]
workflow_call:
inputs:
cache-version:
type: string
default: "1"
required: false

jobs:
build:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

- uses: rstudio/shiny-workflows/setup-r-package@v1
with:
packages: |
renv
shinylive
sessioninfo
cache-version: ${{ github.event.inputs.cache-version }}

- name: Find package dependencies
shell: Rscript {0}
id: packages
run: |
# Find package dependencies using {renv} and install with {pak}
pak::pak(
unique(renv::dependencies(".")$Package)
)
- name: Build site
shell: Rscript {0}
run: |
shinylive::export(".", "site")
- name: Upload site artifact
if: github.ref == 'refs/heads/main'
uses: actions/upload-pages-artifact@v3
with:
path: "site"

deploy:
if: github.ref == 'refs/heads/main'
needs: build

# Grant GITHUB_TOKEN the permissions required to make a Pages deployment
permissions:
pages: write # to deploy to Pages
id-token: write # to verify the deployment originates from an appropriate source

# Deploy to the github-pages environment
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}

# Specify runner + deployment step
runs-on: ubuntu-latest
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
site
.Rproj.user
7 changes: 7 additions & 0 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Title: WebR binary R package repository
Author: George Stagg <[email protected]>
AuthorUrl: https://docs.r-wasm.org/
License: MIT
DisplayMode: Normal
Tags: webr
Type: Shiny
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# MIT License

Copyright (c) 2023 George Stagg

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# WebR binary R package repository dashboard

This repository hosts the source code for the Shinylive app running at https://repo.r-wasm.org/.

The app provides a front page view of the WebR binary R package repository, showing the number of available packages, the number of packages with all dependencies available, and a searchable list of R packages compiled for WebAssembly.

The app is also available at https://r-wasm.github.io/webr-repo-dashboard/.
152 changes: 152 additions & 0 deletions app.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
library(shiny)
library(bslib)
library(dplyr)
library(DT)

source_base <- "https://cran.r-project.org/web/packages/"
contrib_base <- "https://repo.r-wasm.org/bin/emscripten/contrib/"
versions <- c("4.2.x" = "4.2", "4.3.x" = "4.3", "4.3.3" = "4.3.3", "4.4.x" = "4.4")

ui <- page_sidebar(
title = h1("WebR binary R package repository"),
sidebar = sidebar(
title = "Options",
open = FALSE,
selectInput("version", "Select R version",
choices = versions,
selected = versions[[length(versions)]]
),
),
p(
class = "lead",
"This CRAN-like repository contains R packages compiled to WebAssembly for use with webR. Set this page's URL as the named",
code("repos"), "argument when using the", code("webr::install()"),
"command to use this repository as the source for downloading binary R packages."
),
p(
"By default, ", code("webr::install()"), "will use the public repository hosted at",
a(href = "https://repo.r-wasm.org/", "https://repo.r-wasm.org/"),
". See the", a(href = "https://docs.r-wasm.org/webr/latest/packages.html", "webR documentation"),
"for further information about webR."
),
h2("Repository statistics"),
layout_columns(
fill = FALSE,
value_box(
title = h2("Built R packages"),
value = textOutput("built"),
showcase = bsicons::bs_icon("hammer"),
"Packages that have been built for WebAssembly and are available for download from this repository."
),
value_box(
title = "Available R packages",
value = textOutput("available"),
showcase = bsicons::bs_icon("check-circle"),
"Packages for which all of the package dependencies have also been built for WebAssembly and are available for download from this repo."
),
),
h2("Packages"),
DTOutput("webr_pkgs")
)

server <- function(input, output) {
res <- reactive({
withProgress(
{
repo_info <- as.data.frame(available.packages(
contriburl = paste0(contrib_base, input$version),
filters = c("OS_type", "subarch", "duplicates")
))
avail_pkgs <- c(
rownames(repo_info),
c(
"base", "compiler", "datasets", "graphics", "grDevices",
"grid", "methods", "splines", "stats", "stats4",
"tools", "utils", "parallel", "webr"
)
)
incProgress(2 / 5)

deps <- tools::package_dependencies(
packages = rownames(repo_info),
db = repo_info, recursive = TRUE
)
incProgress(2 / 5)

deps <- tibble(
Package = names(deps),
Available = deps |> purrr::map(\(x) all(x %in% avail_pkgs)),
Depends = deps,
Missing = deps |> purrr::map(\(x) x[!(x %in% avail_pkgs)]),
)
incProgress(1 / 5)

package_table <- repo_info |>
select(c("Package", "Version", "Repository")) |>
left_join(deps, by = "Package") |>
arrange(Package)

list(
table = package_table,
n_built = dim(package_table)[1],
n_avail = sum(as.numeric(deps$Available))
)
},
message = "Loading package lists and crunching dependencies",
detail = "This may take a little while...",
value = 0
)
})

output$built <- renderText(res()$n_built)
output$available <- renderText(res()$n_avail)
output$webr_pkgs <- renderDT(
datatable(
res()$table,
rownames = FALSE,
selection = "none",
options = list(
ordering = FALSE,
search = list(regex = TRUE),
columns = JS("[
null,
null,
{ searchable: false, visible: false },
{ title: 'All depends available?' },
{
searchable: false,
title: 'Depends<br><small>Missing dependencies are shown in bold.</small>',
},
{ searchable: false, visible: false },
]"),
rowCallback = JS(paste0(
"
function(row, data) {
if (data[3][0]) {
$('td:eq(2)', row).html('Yes');
} else {
$('td:eq(2)', row).html('<b>No</b>');
}
$('td:eq(0)', row).html(
",
if (is.null(source_base)) {
"data[0]"
} else {
paste0("`<a target=\"_blank\" href=\"", source_base, "${data[0]}/\">${data[0]}</a>`")
},
"
);
$('td:eq(3)', row).html(data[4].map((v) => {
if (data[5].includes(v))
return '<b>' + v + '</b>';
return v;
}).join(', '));
}
"
))
)
)
)
}

shinyApp(ui = ui, server = server)

0 comments on commit caba124

Please sign in to comment.