Composite GitHub Actions for Screenly Edge Apps.
This repo uses Calendar Versioning with vYY.M.PATCH tags (e.g. v26.10.0). Each release is an immutable vYY.M.PATCH tag; pin an exact one and bump it deliberately. The legacy @v1 tag is frozen and receives no fixes. See CONTRIBUTING.md for the full scheme.
Copy these into your app repo under .github/workflows/:
examples/initialize-edge-app.yml— manual create/deploy for stage or productionexamples/update-edge-app.yml— deploy stage on every push tomain/master(rolling); deploy production when a version tag likev26.10.0is pushed
Branch names are only used in your workflow triggers (on.push.branches / github.ref). The actions themselves work the same on main or master — change the branch names in the example to match your repo.
To release to production, tag the commit on main/master and push the tag. The production job refuses to deploy tags whose commit is not on the repo's default branch. We recommend the same CalVer vYY.M.PATCH scheme for app releases (e.g. v26.10.0 for the first release in October 2026, v26.10.1 for the next one that month):
git tag v26.10.0
git push origin v26.10.0Then publish a GitHub Release whose notes list the pull requests merged since the previous release. Add --draft to review the notes before publishing:
gh release create v26.10.0 --verify-tag --generate-notes --title v26.10.0Tip: restrict the GitHub production environment to tags matching v[0-9]* (Settings → Environments → Deployment branches and tags) so only tagged releases can deploy to production.
- Create GitHub Environments named
stageandproduction(workflows setenvironment:to these names). - Add secret
SCREENLY_API_TOKENfor both environments (repo secret shared by both, or the same secret name on each environment when tokens differ). - Do not create
STAGE_EDGE_APP_ID/PRODUCTION_EDGE_APP_IDyet. - Run Initialize Edge App for stage, then for production.
- After each successful initialize, copy the printed Edge App id into the matching repo variable.
- Use Update Edge App for later deploys (requires those vars to be set).
Both stage and production need a Screenly API token. Add SCREENLY_API_TOKEN as a repository secret (shared by both), or as an environment secret on each of the stage and production GitHub Environments when the tokens differ.
| Secret | Required by | Description |
|---|---|---|
SCREENLY_API_TOKEN |
initialize, update (stage and production) |
Screenly API token passed as screenly_api_token |
screenly_api_token: ${{ secrets.SCREENLY_API_TOKEN }}Both actions validate the token against /api/v4.1/users/ on the target API (https://api.screenlyappstage.com for stage, https://api.screenlyapp.com for production) before calling the CLI. An empty or invalid token fails fast with a clear error.
Use only these GitHub Actions repository variables for Edge App ids (never secrets):
| Variable | Environment | When to set |
|---|---|---|
STAGE_EDGE_APP_ID |
stage | After first successful stage initialize |
PRODUCTION_EDGE_APP_ID |
production | After first successful production initialize |
First create: leave the matching var unset. The example expression then resolves to "", and initialize creates a new app.
Later runs: set the var to the real id from initialize. update requires it and will fail if the value is missing or a placeholder (false, 0, null, etc.).
Builds, lints, formats, and tests a Screenly Edge App.
- uses: Screenly/edge-apps-actions/checks@v26.10.0
with:
bun-version: latest # optional| Input | Description | Required | Default |
|---|---|---|---|
bun-version |
Bun version to use | No | latest |
Creates and deploys a new Screenly Edge App instance.
- uses: Screenly/edge-apps-actions/initialize@v26.10.0
with:
screenly_api_token: ${{ secrets.SCREENLY_API_TOKEN }}
edge_app_name: my-edge-app
edge_app_title: My Edge App
environment: ${{ inputs.environment }} # stage or production
edge_app_id: ${{ (inputs.environment == 'production' && vars.PRODUCTION_EDGE_APP_ID) || (inputs.environment == 'stage' && vars.STAGE_EDGE_APP_ID) || '' }}| Input | Description | Required | Default |
|---|---|---|---|
screenly_api_token |
Screenly API token (secrets.SCREENLY_API_TOKEN) |
Yes | |
edge_app_name |
Edge App name (used for the CLI --name flag) |
Yes | |
edge_app_title |
Display title for the Edge App instance | Yes | |
environment |
stage or production only |
No | stage |
edge_app_id |
Edge App ID for this environment | No | "" |
Always uses screenly.yml for both stage and production. When edge_app_id is a real id, it is exported as EDGE_APP_ID and takes precedence over any id in the manifest. Empty / placeholder values are treated as unset (first create).
Safe expression: use the scoped form above with trailing || ''. Do not use production && vars.PRODUCTION_EDGE_APP_ID || vars.STAGE_EDGE_APP_ID — that can pass the stage id into production when the production var is unset.
Requires screenly/cli v26.9.0 or later; see the v26.9.0 release notes for details.
Builds and deploys an existing Screenly Edge App.
- uses: Screenly/edge-apps-actions/update@v26.10.0
with:
screenly_api_token: ${{ secrets.SCREENLY_API_TOKEN }}
environment: stage # or production
delete_missing_settings: false # optional, defaults to false
edge_app_id: ${{ vars.STAGE_EDGE_APP_ID }} # production job: vars.PRODUCTION_EDGE_APP_ID| Input | Description | Required | Default |
|---|---|---|---|
screenly_api_token |
Screenly API token (secrets.SCREENLY_API_TOKEN) |
Yes | |
environment |
stage or production only |
No | stage |
delete_missing_settings |
Delete settings that exist on the server but not in the manifest | No | false |
edge_app_id |
Edge App ID for this environment (required, real id) | Yes* | "" |
*Required at runtime: empty or placeholder values fail the job with a message to set STAGE_EDGE_APP_ID / PRODUCTION_EDGE_APP_ID.
Always uses screenly.yml. Prefer separate jobs per environment (as in examples/update-edge-app.yml), each passing only its own var.
Requires screenly/cli v26.9.0 or later; see the v26.9.0 release notes for details.