Converting a Python Shiny App to a Python Shinylive App and Deploying via GitHub
For an example repository showcasing the workflow, please see https://github.com/coatless-tutorials/convert-py-shiny-app-to-py-shinylive-app
Background
We’ll be working with an app that was initially developed in R Shiny and later translated to Shiny for Python. The original R Shiny App’s source code originated from a StackOverflow Question by Faustin Gashakamba, which led to the creation of the first tutorial on deploying an R Shiny app using R Shinylive.
Deploying Automatically with GitHub Actions
Serving a Website from a GitHub Repository
We recommend against using the gh-pages
branch deployment technique for sharing the app on GitHub Pages. Instead, opt for the GitHub Actions approach. This method is preferred because it doesn’t store conversion artifacts inside the repository, and it allows Shinylive apps to be deployed up to the GitHub Pages maximum size limit of about 1 GB.
Project Layout
For this to work, we’re advocating for a repository structure of:
.
├── .github
│ └── workflows
│ └── build-and-deploy-py-shinylive-app.yml
├── README.md
├── app.py
├── requirements-ci.txt
└── requirements-dev.txt
With this file structure, we can place any Python package requirements into two requirement files:
requirements-dev.txt
: Handles local development requirements like developing the Shiny for Python app outside of Python Shinylive as well as converting with a local copy ofshinylive
.requirements-ci.txt
: Describes the python packages to install and cache for faster iterations.
It may seem odd to have two separate requirements*.txt
files, however, the actual conversion of the Shiny for Python app into a Python shinylive app requires just the shinylive
python package.
[!IMPORTANT]
Please avoid using
requirements.txt
sincepy-shinylive
will attempt to install packages listed in that file for the app. This is problematic aspy-shinylive
itself has a dependency that does not have a Pyodide-compiled Python package wheel causing the app to fail.
With this said, the source for the Shiny for Python app can be placed into the app.py
file. Moreover, we can use the following GitHub Action in .github/workflows/build-and-deploy-py-shinylive-app.yml
to build and deploy the shinylive app every time the repository is updated.
GitHub Action Workflow for Converting and Deploying
The following workflow contains a single step that encompasses both the build and deploy phases. We use the requirements-ci.txt
discussed above as the pip
package cache to speed up the conversion and, subsequently, the deployment of the Python Shinylive app. For more details about customizing the conversion step or the deployment step, please see the two notes that immediately follow from the workflow.
on:
push:
branches: [main, master]
release:
types: [published]
workflow_dispatch: {}
name: demo-py-shinylive-app
jobs:
build-and-deploy-py-shinylive-app:
runs-on: ubuntu-latest
# Only restrict concurrency for non-PR jobs
concurrency:
group: py-shinylive-website-${{ github.event_name != 'pull_request' || github.run_id }}
# Describe the permissions for obtain repository contents and
# deploying a GitHub pages website for the repository
permissions:
contents: read
pages: write
id-token: write
steps:
# Obtain the contents of the repository
- name: "Check out repository"
uses: actions/checkout@v4
# Install Python on the GitHub Actions worker
- name: "Setup Python"
uses: actions/setup-python@v5
with:
python-version: '3.12'
cache: 'pip' # caching pip dependencies
cache-dependency-path: 'requirements-ci.txt'
# Install the dependencies for the py-shinylive app
- name: "Setup Python dependency for Shinylive App export"
shell: bash
run: pip install -r requirements-ci.txt
# Export the current working directory as the py-shiny app
# using the version of the py-shinylive package
- name: Create Python Shinylive App from working directory files
shell: bash
run: |
shinylive export . _site
# Upload a tar file that will work with GitHub Pages
# Make sure to set a retention day to avoid running into a cap
# This artifact shouldn't be required after deployment onto pages was a success.
- name: Upload Pages artifact
uses: actions/upload-pages-artifact@v2
with:
retention-days: 1
# Use an Action deploy to push the artifact onto GitHub Pages
# This requires the `Action` tab being structured to allow for deployment
# instead of using `docs/` or the `gh-pages` branch of the repository
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v2
Conversion Assumptions
When exporting the Shiny for Python app, we assume:
- The app is located in the working directory, denoted by
.
. - The deployment folder or what should be shown on the web is
_site
.
If these assumptions don’t align with your setup, please modify the conversion step accordingly.
- name: Create Python Shinylive App from working directory files
shell: bash
run: |
shinylive export . _site
Customize Deployment Path
The output directory _site
for the converted Shinylive app is used as it’s the default path for the upload-pages-artifact
action. You can change this by supplying a path
parameter under with
in the “Upload Pages artifact” step, e.g.
- name: Upload Pages artifact
uses: actions/upload-pages-artifact@v2
with:
retention-days: 1
path: "new-path-here"
Enabling GitHub Pages Deployment
To enable deployment through GitHub Actions to GitHub Pages:
- Navigate to the repository’s Settings page.
- Select Pages on the left sidebar.
- Choose the GitHub Actions option in the Source drop-down under the Build and Deployment section.
- Ensure that Enforced HTTPS is checked.
Working Example
You can view the example shinylive-ified [app.py source included in the repository here:
https://tutorials.thecoatlessprofessor.com/convert-py-shiny-app-to-py-shinylive-app/
Keep in mind that the exported app size is not mobile-friendly (approximately 38 MB).
If you are data constrained, you can see the app in this screenshot:
Moreover, you can view one of the deployment apps sizes here:
Fin
That’s it! You’ve successfully learned how to deploy a Python Shinylive app via GitHub Pages using GitHub Actions.