Skip to content

Commit caba124

Browse files
committed
Initial commit
0 parents  commit caba124

File tree

6 files changed

+276
-0
lines changed

6 files changed

+276
-0
lines changed

.github/workflows/deploy-app.yml

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
# Basic example of a GitHub Actions workflow that builds a Shiny app and deploys
2+
# it to GitHub Pages.
3+
#
4+
# The agreed upon contract is:
5+
#
6+
# - Inspect the root directory for package dependencies
7+
# - Install R and the found packages
8+
# - Export the Shiny app directory to `./site`
9+
# - On push events, deploy the exported app to GitHub Pages
10+
#
11+
# If this contract is not met or could be easily improved for others,
12+
# please open a new Issue https://github.com/posit-dev/r-shinylive/
13+
#
14+
# The _magic_ of this workflow is in the `shinylive::export()` function, which
15+
# creates a static version of the Shiny app into the folder `./site`.
16+
# The exported app folder is then uploaded and deployed to GitHub Pages.
17+
#
18+
# When deploying to GitHub Pages, be sure to have the appropriate write
19+
# permissions for your token (`pages` and `id-token`).
20+
21+
name: Deploy app
22+
23+
on:
24+
push:
25+
branches: [main]
26+
workflow_call:
27+
inputs:
28+
cache-version:
29+
type: string
30+
default: "1"
31+
required: false
32+
33+
jobs:
34+
build:
35+
runs-on: ubuntu-latest
36+
37+
steps:
38+
- uses: actions/checkout@v4
39+
40+
- uses: rstudio/shiny-workflows/setup-r-package@v1
41+
with:
42+
packages: |
43+
renv
44+
shinylive
45+
sessioninfo
46+
cache-version: ${{ github.event.inputs.cache-version }}
47+
48+
- name: Find package dependencies
49+
shell: Rscript {0}
50+
id: packages
51+
run: |
52+
# Find package dependencies using {renv} and install with {pak}
53+
pak::pak(
54+
unique(renv::dependencies(".")$Package)
55+
)
56+
57+
- name: Build site
58+
shell: Rscript {0}
59+
run: |
60+
shinylive::export(".", "site")
61+
62+
- name: Upload site artifact
63+
if: github.ref == 'refs/heads/main'
64+
uses: actions/upload-pages-artifact@v3
65+
with:
66+
path: "site"
67+
68+
deploy:
69+
if: github.ref == 'refs/heads/main'
70+
needs: build
71+
72+
# Grant GITHUB_TOKEN the permissions required to make a Pages deployment
73+
permissions:
74+
pages: write # to deploy to Pages
75+
id-token: write # to verify the deployment originates from an appropriate source
76+
77+
# Deploy to the github-pages environment
78+
environment:
79+
name: github-pages
80+
url: ${{ steps.deployment.outputs.page_url }}
81+
82+
# Specify runner + deployment step
83+
runs-on: ubuntu-latest
84+
steps:
85+
- name: Deploy to GitHub Pages
86+
id: deployment
87+
uses: actions/deploy-pages@v4

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
site
2+
.Rproj.user

DESCRIPTION

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
Title: WebR binary R package repository
2+
Author: George Stagg <[email protected]>
3+
AuthorUrl: https://docs.r-wasm.org/
4+
License: MIT
5+
DisplayMode: Normal
6+
Tags: webr
7+
Type: Shiny

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# MIT License
2+
3+
Copyright (c) 2023 George Stagg
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# WebR binary R package repository dashboard
2+
3+
This repository hosts the source code for the Shinylive app running at https://repo.r-wasm.org/.
4+
5+
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.
6+
7+
The app is also available at https://r-wasm.github.io/webr-repo-dashboard/.

app.R

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
library(shiny)
2+
library(bslib)
3+
library(dplyr)
4+
library(DT)
5+
6+
source_base <- "https://cran.r-project.org/web/packages/"
7+
contrib_base <- "https://repo.r-wasm.org/bin/emscripten/contrib/"
8+
versions <- c("4.2.x" = "4.2", "4.3.x" = "4.3", "4.3.3" = "4.3.3", "4.4.x" = "4.4")
9+
10+
ui <- page_sidebar(
11+
title = h1("WebR binary R package repository"),
12+
sidebar = sidebar(
13+
title = "Options",
14+
open = FALSE,
15+
selectInput("version", "Select R version",
16+
choices = versions,
17+
selected = versions[[length(versions)]]
18+
),
19+
),
20+
p(
21+
class = "lead",
22+
"This CRAN-like repository contains R packages compiled to WebAssembly for use with webR. Set this page's URL as the named",
23+
code("repos"), "argument when using the", code("webr::install()"),
24+
"command to use this repository as the source for downloading binary R packages."
25+
),
26+
p(
27+
"By default, ", code("webr::install()"), "will use the public repository hosted at",
28+
a(href = "https://repo.r-wasm.org/", "https://repo.r-wasm.org/"),
29+
". See the", a(href = "https://docs.r-wasm.org/webr/latest/packages.html", "webR documentation"),
30+
"for further information about webR."
31+
),
32+
h2("Repository statistics"),
33+
layout_columns(
34+
fill = FALSE,
35+
value_box(
36+
title = h2("Built R packages"),
37+
value = textOutput("built"),
38+
showcase = bsicons::bs_icon("hammer"),
39+
"Packages that have been built for WebAssembly and are available for download from this repository."
40+
),
41+
value_box(
42+
title = "Available R packages",
43+
value = textOutput("available"),
44+
showcase = bsicons::bs_icon("check-circle"),
45+
"Packages for which all of the package dependencies have also been built for WebAssembly and are available for download from this repo."
46+
),
47+
),
48+
h2("Packages"),
49+
DTOutput("webr_pkgs")
50+
)
51+
52+
server <- function(input, output) {
53+
res <- reactive({
54+
withProgress(
55+
{
56+
repo_info <- as.data.frame(available.packages(
57+
contriburl = paste0(contrib_base, input$version),
58+
filters = c("OS_type", "subarch", "duplicates")
59+
))
60+
avail_pkgs <- c(
61+
rownames(repo_info),
62+
c(
63+
"base", "compiler", "datasets", "graphics", "grDevices",
64+
"grid", "methods", "splines", "stats", "stats4",
65+
"tools", "utils", "parallel", "webr"
66+
)
67+
)
68+
incProgress(2 / 5)
69+
70+
deps <- tools::package_dependencies(
71+
packages = rownames(repo_info),
72+
db = repo_info, recursive = TRUE
73+
)
74+
incProgress(2 / 5)
75+
76+
deps <- tibble(
77+
Package = names(deps),
78+
Available = deps |> purrr::map(\(x) all(x %in% avail_pkgs)),
79+
Depends = deps,
80+
Missing = deps |> purrr::map(\(x) x[!(x %in% avail_pkgs)]),
81+
)
82+
incProgress(1 / 5)
83+
84+
package_table <- repo_info |>
85+
select(c("Package", "Version", "Repository")) |>
86+
left_join(deps, by = "Package") |>
87+
arrange(Package)
88+
89+
list(
90+
table = package_table,
91+
n_built = dim(package_table)[1],
92+
n_avail = sum(as.numeric(deps$Available))
93+
)
94+
},
95+
message = "Loading package lists and crunching dependencies",
96+
detail = "This may take a little while...",
97+
value = 0
98+
)
99+
})
100+
101+
output$built <- renderText(res()$n_built)
102+
output$available <- renderText(res()$n_avail)
103+
output$webr_pkgs <- renderDT(
104+
datatable(
105+
res()$table,
106+
rownames = FALSE,
107+
selection = "none",
108+
options = list(
109+
ordering = FALSE,
110+
search = list(regex = TRUE),
111+
columns = JS("[
112+
null,
113+
null,
114+
{ searchable: false, visible: false },
115+
{ title: 'All depends available?' },
116+
{
117+
searchable: false,
118+
title: 'Depends<br><small>Missing dependencies are shown in bold.</small>',
119+
},
120+
{ searchable: false, visible: false },
121+
]"),
122+
rowCallback = JS(paste0(
123+
"
124+
function(row, data) {
125+
if (data[3][0]) {
126+
$('td:eq(2)', row).html('Yes');
127+
} else {
128+
$('td:eq(2)', row).html('<b>No</b>');
129+
}
130+
$('td:eq(0)', row).html(
131+
",
132+
if (is.null(source_base)) {
133+
"data[0]"
134+
} else {
135+
paste0("`<a target=\"_blank\" href=\"", source_base, "${data[0]}/\">${data[0]}</a>`")
136+
},
137+
"
138+
);
139+
$('td:eq(3)', row).html(data[4].map((v) => {
140+
if (data[5].includes(v))
141+
return '<b>' + v + '</b>';
142+
return v;
143+
}).join(', '));
144+
}
145+
"
146+
))
147+
)
148+
)
149+
)
150+
}
151+
152+
shinyApp(ui = ui, server = server)

0 commit comments

Comments
 (0)