# Find the template location
template_path <- system.file(
"templates",
"github-actions-build.yml",
package = "shinyelectron"
)
# View the template
file.show(template_path)
# Copy to your project (run from your project root)
dir.create(".github/workflows", recursive = TRUE, showWarnings = FALSE)
file.copy(
template_path,
".github/workflows/build-electron.yml"
)GitHub Actions provides a powerful way to automatically build your Shiny application as an Electron desktop app for Windows, macOS, and Linux. This guide explains how to set up CI/CD for your shinyelectron project.
Why Use GitHub Actions?
Building desktop applications manually for multiple platforms is time-consuming:
| Challenge | GitHub Actions Solution |
|---|---|
| Need access to Windows, macOS, and Linux | Runners available for all platforms |
| Manual builds are error-prone | Automated, reproducible builds |
| Distributing builds is tedious | Automatic artifact upload and releases |
| Testing across platforms | Matrix builds run in parallel |
Prerequisites
Before setting up GitHub Actions, ensure you have:
- A GitHub repository containing your Shiny app
- Your Shiny app in a subdirectory (default:
app/) - (Optional) A
_shinyelectron.ymlconfiguration file
Example repository structure:
my-shiny-project/
├── .github/
│ └── workflows/
│ └── build-electron.yml # Workflow file
├── app/
│ ├── app.R # Your Shiny app
│ └── ...
├── _shinyelectron.yml # Optional config
└── README.md
Quick Start
Step 1: Copy the Template
shinyelectron includes a ready-to-use workflow template. Copy it to your repository:
Or download directly from: https://github.com/coatless-rpkg/shinyelectron/blob/main/inst/templates/github-actions-build.yml
Step 2: Configure the Workflow
Edit .github/workflows/build-electron.yml and update the environment variables at the top:
env:
APP_DIR: 'app' # Directory containing your Shiny app
APP_NAME: 'MyApp' # Name of your application
NODE_VERSION: '22' # Node.js version
R_VERSION: 'release' # R versionStep 3: Push and Build
Commit and push your changes:
git add .github/workflows/build-electron.yml
git commit -m "Add Electron build workflow"
git pushThe workflow triggers automatically on push to main/master branches.
Workflow Structure
The template workflow has three jobs:
Build Job
Runs on each platform in parallel:
| Runner | Platform | Architecture | CPU / RAM | Output |
|---|---|---|---|---|
macos-latest |
macOS | arm64 (M1) | 3 cores / 7 GB | .dmg |
macos-15-intel |
macOS | x64 (Intel) | 4 cores / 14 GB | .dmg |
windows-latest |
Windows 2025 | x64 | 4 cores / 16 GB | .exe |
ubuntu-latest |
Ubuntu 24.04 | x64 | 4 cores / 16 GB | .AppImage |
ubuntu-24.04-arm |
Ubuntu 24.04 | arm64 | 4 cores / 16 GB | .AppImage |
windows-11-arm |
Windows 11 | arm64 | 4 cores / 16 GB | .exe |
Key steps:
- Checkout - Clone your repository
- Setup R - Install R using r-lib/actions
- Setup Node.js - Install Node.js 22
- Install dependencies - R packages including shinyelectron
-
Build - Run
shinyelectron::export() - Upload artifacts - Save build outputs
Release Job
Triggers only when you push a version tag (e.g., v1.0.0):
- Downloads all build artifacts
- Creates a GitHub Release
- Attaches all platform builds
Summary Job
Provides a build status summary in the Actions UI.
Customization
Changing the App Directory
If your Shiny app isn’t in app/, update APP_DIR:
env:
APP_DIR: 'src/shiny-app' # Custom locationBuilding for Specific Platforms
To build only for certain platforms, modify the matrix:
matrix:
include:
# Only macOS and Windows
- os: macos-latest
platform: mac
arch: arm64
- os: windows-latest
platform: win
arch: x64Using a Configuration File
If you have a _shinyelectron.yml in your app directory, the build will automatically use it. The workflow parameters override config file values.
Example app/_shinyelectron.yml:
app:
name: "My Shiny Dashboard"
version: "1.0.0"
window:
width: 1400
height: 900
build:
type: "r-shinylive"Adding Custom Icons
Place icons in your repository and reference them:
- name: Build Electron app
run: |
Rscript -e "
shinyelectron::export(
appdir = '${{ env.APP_DIR }}',
destdir = 'build',
icon = 'assets/icon.icns',
# ... other options
)
"Note
Icon format requirements:
- macOS:
.icns(useiconutilto create)- Windows:
.ico(multi-resolution recommended)- Linux:
.png(512x512 recommended)
Creating Releases
Automatic Releases
Push a version tag to create a release automatically:
git tag v1.0.0
git push origin v1.0.0The workflow will:
- Build for all platforms
- Create a GitHub Release named “v1.0.0”
- Attach all build artifacts
Pre-releases
Tags containing -alpha or -beta are marked as pre-releases:
git tag v1.0.0-beta.1
git push origin v1.0.0-beta.1Manual Releases
Trigger a build manually from the Actions tab using “workflow_dispatch”:
- Go to Actions → Build Electron App
- Click “Run workflow”
- Select branch and click “Run workflow”
Advanced Topics
Caching Dependencies
The template includes npm caching. To also cache R packages:
- name: Setup R
uses: r-lib/actions/setup-r@v2
with:
r-version: ${{ env.R_VERSION }}
use-public-rspm: true
- name: Cache R packages
uses: actions/cache@v4
with:
path: ${{ env.R_LIBS_USER }}
key: ${{ runner.os }}-r-${{ hashFiles('**/DESCRIPTION') }}Build Status Badge
Add a badge to your README:
[](https://github.com/YOUR-USERNAME/YOUR-REPO/actions/workflows/build-electron.yml)Code Signing
Code signing requires additional setup:
macOS:
env:
CSC_LINK: ${{ secrets.MAC_CERTIFICATE }}
CSC_KEY_PASSWORD: ${{ secrets.MAC_CERTIFICATE_PASSWORD }}
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }}Windows:
env:
CSC_LINK: ${{ secrets.WIN_CERTIFICATE }}
CSC_KEY_PASSWORD: ${{ secrets.WIN_CERTIFICATE_PASSWORD }}Warning
Code signing requires purchasing certificates from Apple and/or a Certificate Authority. Unsigned apps may trigger security warnings on user machines.
Secrets Management
Store sensitive values in GitHub Secrets:
- Go to Settings → Secrets and variables → Actions
- Click “New repository secret”
- Add your secret (e.g.,
MAC_CERTIFICATE)
Reference in workflow:
env:
MY_SECRET: ${{ secrets.MY_SECRET_NAME }}Troubleshooting
Build Fails on Linux
Symptom: Missing system libraries
Solution: Add system dependencies:
- name: Install system dependencies (Linux)
if: runner.os == 'Linux'
run: |
sudo apt-get update
sudo apt-get install -y libcurl4-openssl-dev libxml2-devBuild Fails: App Directory Not Found
Symptom: “App directory ‘app’ not found”
Solution: Ensure your Shiny app is in the correct directory and update APP_DIR if needed.
R Package Installation Fails
Symptom: “Package not available” errors
Solution: Ensure packages are available on CRAN or add custom repositories:
- name: Install R dependencies
uses: r-lib/actions/setup-r-dependencies@v2
with:
extra-packages: |
any::shinyelectron
github::user/packageBuild Times Out
Symptom: Job exceeds 6 hour limit
Solution: Optimize your build or split into smaller jobs. Consider building fewer platforms per workflow run.
Artifacts Not Found
Symptom: Upload step shows “No files found”
Solution: Check the build output path. Run ls -laR build/ to debug:
- name: Debug build output
run: ls -laR build/
shell: bashUsing sitrep for Diagnostics
Add diagnostic output to your workflow:
- name: Run diagnostics
run: |
Rscript -e "
library(shinyelectron)
sitrep_shinyelectron()
"Complete Example
Here’s a minimal working example:
Repository structure:
my-app/
├── .github/workflows/build-electron.yml
├── app/
│ └── app.R
└── README.md
app/app.R:
library(shiny)
ui <- fluidPage(
titlePanel("Hello Shiny!"),
sliderInput("n", "Number:", 1, 100, 50),
textOutput("result")
)
server <- function(input, output) {
output$result <- renderText(paste("You selected:", input$n))
}
shinyApp(ui, server)Workflow trigger: Push to main or create a tag like v1.0.0.
Next Steps
- Getting Started: Local development workflow
-
Configuration: Customize with
_shinyelectron.yml - Troubleshooting: Diagnose build issues