<?xml version="1.0" encoding="utf-8"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Edge Apps GitHub Actions release notes | Screenly</title><description>The reusable GitHub workflows that check, build and deploy Edge Apps. What has shipped, newest first.</description><link>https://www.screenly.io/releases/edge-apps-actions/</link><language>en</language><atom:link href="https://www.screenly.io/releases/edge-apps-actions/rss.xml" rel="self" type="application/rss+xml"/><lastBuildDate>Mon, 26 Oct 2026 00:00:00 +0000</lastBuildDate><item><title>Edge Apps GitHub Actions 26.10.2: Checks, initialize, and update now come as reusable workflows</title><link>https://www.screenly.io/releases/edge-apps-actions/26.10.2/reusable-workflows/</link><guid isPermaLink="true">https://www.screenly.io/releases/edge-apps-actions/26.10.2/reusable-workflows/</guid><pubDate>Mon, 26 Oct 2026 00:00:00 +0000</pubDate><category>release</category><category>developers</category><description>&lt;p&gt;Until this release, every Edge App repo carried its own full copy of the example workflows: the
triggers, the jobs for each environment, the production tag check, and the id expressions. Now those
live in this repo as reusable workflows, and an app&amp;rsquo;s workflow file calls them:&lt;/p&gt;
&lt;div class="code-block"&gt;
&lt;button type="button" class="code-copy" aria-label="Copy code" data-copy-code&gt;
&lt;svg data-copy viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;
&lt;rect x="9" y="9" width="11" height="11" rx="2"&gt;&lt;/rect&gt;
&lt;path d="M5 15V5a2 2 0 0 1 2-2h10"&gt;&lt;/path&gt;
&lt;/svg&gt;
&lt;svg data-check viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;
&lt;path d="M20 6 9 17l-5-5"&gt;&lt;/path&gt;
&lt;/svg&gt;
&lt;/button&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6ab825;font-weight:bold"&gt;name&lt;/span&gt;:&lt;span style="color:#666"&gt; &lt;/span&gt;Update Edge App&lt;span style="color:#666"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6ab825;font-weight:bold"&gt;on&lt;/span&gt;:&lt;span style="color:#666"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666"&gt; &lt;/span&gt;&lt;span style="color:#6ab825;font-weight:bold"&gt;workflow_dispatch&lt;/span&gt;:&lt;span style="color:#666"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666"&gt; &lt;/span&gt;&lt;span style="color:#6ab825;font-weight:bold"&gt;push&lt;/span&gt;:&lt;span style="color:#666"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666"&gt; &lt;/span&gt;&lt;span style="color:#6ab825;font-weight:bold"&gt;branches&lt;/span&gt;:&lt;span style="color:#666"&gt; &lt;/span&gt;[main, master]&lt;span style="color:#666"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666"&gt; &lt;/span&gt;&lt;span style="color:#6ab825;font-weight:bold"&gt;tags&lt;/span&gt;:&lt;span style="color:#666"&gt; &lt;/span&gt;[&lt;span style="color:#ed9d13"&gt;&amp;#39;v[0-9]*&amp;#39;&lt;/span&gt;]&lt;span style="color:#666"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6ab825;font-weight:bold"&gt;permissions&lt;/span&gt;:&lt;span style="color:#666"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666"&gt; &lt;/span&gt;&lt;span style="color:#6ab825;font-weight:bold"&gt;contents&lt;/span&gt;:&lt;span style="color:#666"&gt; &lt;/span&gt;read&lt;span style="color:#666"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6ab825;font-weight:bold"&gt;jobs&lt;/span&gt;:&lt;span style="color:#666"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666"&gt; &lt;/span&gt;&lt;span style="color:#6ab825;font-weight:bold"&gt;update&lt;/span&gt;:&lt;span style="color:#666"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666"&gt; &lt;/span&gt;&lt;span style="color:#6ab825;font-weight:bold"&gt;uses&lt;/span&gt;:&lt;span style="color:#666"&gt; &lt;/span&gt;Screenly/edge-apps-actions/.github/workflows/update.yml@v26.10.2&lt;span style="color:#666"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666"&gt; &lt;/span&gt;&lt;span style="color:#6ab825;font-weight:bold"&gt;secrets&lt;/span&gt;:&lt;span style="color:#666"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666"&gt; &lt;/span&gt;&lt;span style="color:#6ab825;font-weight:bold"&gt;SCREENLY_API_TOKEN&lt;/span&gt;:&lt;span style="color:#666"&gt; &lt;/span&gt;${{ secrets.SCREENLY_API_TOKEN }}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;When a later release changes how deploys work, bumping that pin is all it takes. Copy the 3 files in
&lt;code&gt;examples/&lt;/code&gt; into your app&amp;rsquo;s &lt;code&gt;.github/workflows/&lt;/code&gt; to start.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Workflow&lt;/th&gt;
&lt;th&gt;Inputs&lt;/th&gt;
&lt;th&gt;Secrets&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;checks.yml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;bun-version&lt;/code&gt; (default &lt;code&gt;latest&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;none&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;initialize.yml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;environment&lt;/code&gt;, &lt;code&gt;edge_app_name&lt;/code&gt;, &lt;code&gt;edge_app_title&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;SCREENLY_API_TOKEN&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;update.yml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;delete_missing_settings&lt;/code&gt; (default &lt;code&gt;true&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;SCREENLY_API_TOKEN&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;code&gt;update.yml&lt;/code&gt; deploys to stage on a push or a manual run on the default branch, and other branches
never deploy. It deploys to production when you push a &lt;code&gt;v*&lt;/code&gt; tag whose commit is on the default
branch, through the &lt;code&gt;production&lt;/code&gt; environment and its reviewers. &lt;code&gt;checks.yml&lt;/code&gt; cancels a check still
running on a branch when a newer push to that branch arrives.&lt;/p&gt;
&lt;h2 id="setting-up-an-app"&gt;Setting up an app&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Create the GitHub environments &lt;code&gt;stage&lt;/code&gt; and &lt;code&gt;production&lt;/code&gt;, and add &lt;code&gt;SCREENLY_API_TOKEN&lt;/code&gt; to each as
an environment secret. An environment secret only reaches jobs that run in that environment, so
the production token stays behind production&amp;rsquo;s reviewers.&lt;/li&gt;
&lt;li&gt;Run &amp;ldquo;Initialize Edge App&amp;rdquo; for &lt;code&gt;stage&lt;/code&gt;. Once the run has finished successfully, set the repository
variable &lt;code&gt;STAGE_EDGE_APP_ID&lt;/code&gt; to the id in its job summary. Setting it earlier lets a deploy start
while Initialize is still running.&lt;/li&gt;
&lt;li&gt;Do the same for &lt;code&gt;production&lt;/code&gt; and &lt;code&gt;PRODUCTION_EDGE_APP_ID&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;code&gt;delete_missing_settings&lt;/code&gt; is &lt;code&gt;true&lt;/code&gt; in &lt;code&gt;update.yml&lt;/code&gt;, so the manifest decides which settings exist.
The &lt;code&gt;update&lt;/code&gt; action on its own still defaults to &lt;code&gt;false&lt;/code&gt;. To keep settings that aren&amp;rsquo;t in your
manifest, pass &lt;code&gt;delete_missing_settings: false&lt;/code&gt; under &lt;code&gt;with:&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;checks&lt;/code&gt;, &lt;code&gt;initialize&lt;/code&gt;, and &lt;code&gt;update&lt;/code&gt; actions are still there to use as steps in a workflow of
your own.&lt;/p&gt;</description></item><item><title>Edge Apps GitHub Actions 26.10.2: Deploys to an environment run one at a time</title><link>https://www.screenly.io/releases/edge-apps-actions/26.10.2/deploys-run-one-at-a-time/</link><guid isPermaLink="true">https://www.screenly.io/releases/edge-apps-actions/26.10.2/deploys-run-one-at-a-time/</guid><pubDate>Mon, 26 Oct 2026 00:00:00 +0000</pubDate><category>improvement</category><category>developers</category><description>&lt;p&gt;Merge 3 pull requests into &lt;code&gt;main&lt;/code&gt; in a row, and the update workflow deploys the first to stage while
the second waits. When the third arrives, it takes the second&amp;rsquo;s place in line. Stage ends up on the
newest commit after 2 deploys, and a running deploy is never cancelled to get there.&lt;/p&gt;
&lt;p&gt;Production tags queue the same way, separately from stage. If an older production run is still
waiting for a reviewer, reject it so the newest one goes next.&lt;/p&gt;
&lt;p&gt;Initialize has a queue of its own, so a push can&amp;rsquo;t take the place of an Initialize run that&amp;rsquo;s
waiting.&lt;/p&gt;
&lt;p&gt;To redo a failed or cancelled production deploy, re-run that tag&amp;rsquo;s workflow run. You don&amp;rsquo;t need a
new tag. If the earlier run stopped part-way, the re-run can report success while the app stays on
its previous revision, so check the live revision in Screenly afterward. If it didn&amp;rsquo;t move, push a
new tag with a change to the app&amp;rsquo;s files.&lt;/p&gt;</description></item><item><title>Edge Apps GitHub Actions 26.10.2: The initialize action won't create the same app twice, and other fixes</title><link>https://www.screenly.io/releases/edge-apps-actions/26.10.2/fixes-and-improvements/</link><guid isPermaLink="true">https://www.screenly.io/releases/edge-apps-actions/26.10.2/fixes-and-improvements/</guid><pubDate>Mon, 26 Oct 2026 00:00:00 +0000</pubDate><category>roundup</category><description>&lt;h2 id="fixes"&gt;Fixes&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;If &lt;code&gt;package.json&lt;/code&gt; can&amp;rsquo;t be parsed, &lt;code&gt;initialize&lt;/code&gt; and &lt;code&gt;update&lt;/code&gt; stop with an error instead of
deploying the repo root.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="improvements"&gt;Improvements&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;initialize&lt;/code&gt; stops if an Edge App with the same name already exists in that environment, so
running it twice can&amp;rsquo;t create 2 apps. If it can&amp;rsquo;t get the list of Edge Apps to check, it stops
without creating anything.&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Edge Apps GitHub Actions 26.10.1: Initialize runs once per environment and shows the new id right away</title><link>https://www.screenly.io/releases/edge-apps-actions/26.10.1/initialize-runs-once/</link><guid isPermaLink="true">https://www.screenly.io/releases/edge-apps-actions/26.10.1/initialize-runs-once/</guid><pubDate>Sat, 24 Oct 2026 00:00:00 +0000</pubDate><category>improvement</category><category>developers</category><description>&lt;p&gt;&lt;code&gt;initialize&lt;/code&gt; is for the first deploy to an environment, and it holds to that now. Pass it the
environment&amp;rsquo;s id variable, and if the variable is set, the run stops with an error that points you
to &lt;code&gt;update&lt;/code&gt;:&lt;/p&gt;
&lt;div class="code-block"&gt;
&lt;button type="button" class="code-copy" aria-label="Copy code" data-copy-code&gt;
&lt;svg data-copy viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;
&lt;rect x="9" y="9" width="11" height="11" rx="2"&gt;&lt;/rect&gt;
&lt;path d="M5 15V5a2 2 0 0 1 2-2h10"&gt;&lt;/path&gt;
&lt;/svg&gt;
&lt;svg data-check viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;
&lt;path d="M20 6 9 17l-5-5"&gt;&lt;/path&gt;
&lt;/svg&gt;
&lt;/button&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;- &lt;span style="color:#6ab825;font-weight:bold"&gt;uses&lt;/span&gt;:&lt;span style="color:#666"&gt; &lt;/span&gt;Screenly/edge-apps-actions/initialize@v26.10.1&lt;span style="color:#666"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666"&gt; &lt;/span&gt;&lt;span style="color:#6ab825;font-weight:bold"&gt;with&lt;/span&gt;:&lt;span style="color:#666"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666"&gt; &lt;/span&gt;&lt;span style="color:#6ab825;font-weight:bold"&gt;screenly_api_token&lt;/span&gt;:&lt;span style="color:#666"&gt; &lt;/span&gt;${{ secrets.SCREENLY_API_TOKEN }}&lt;span style="color:#666"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666"&gt; &lt;/span&gt;&lt;span style="color:#6ab825;font-weight:bold"&gt;edge_app_name&lt;/span&gt;:&lt;span style="color:#666"&gt; &lt;/span&gt;${{ inputs.edge_app_name }}&lt;span style="color:#666"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666"&gt; &lt;/span&gt;&lt;span style="color:#6ab825;font-weight:bold"&gt;edge_app_title&lt;/span&gt;:&lt;span style="color:#666"&gt; &lt;/span&gt;${{ inputs.edge_app_title }}&lt;span style="color:#666"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666"&gt; &lt;/span&gt;&lt;span style="color:#6ab825;font-weight:bold"&gt;environment&lt;/span&gt;:&lt;span style="color:#666"&gt; &lt;/span&gt;${{ inputs.environment }}&lt;span style="color:#666"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666"&gt; &lt;/span&gt;&lt;span style="color:#6ab825;font-weight:bold"&gt;edge_app_id&lt;/span&gt;:&lt;span style="color:#666"&gt; &lt;/span&gt;${{ (inputs.environment == &amp;#39;production&amp;#39; &amp;amp;&amp;amp; vars.PRODUCTION_EDGE_APP_ID) || (inputs.environment == &amp;#39;stage&amp;#39; &amp;amp;&amp;amp; vars.STAGE_EDGE_APP_ID) || &amp;#39;&amp;#39; }}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The new app&amp;rsquo;s id shows up as soon as the app exists, before the build and deploy steps: as a notice
in the log, and under &amp;ldquo;Edge App id&amp;rdquo; in the job summary, together with the name of the variable to
set. If a later step fails, you still have the id.&lt;/p&gt;
&lt;p&gt;To start an environment over, delete its Edge App in Screenly, clear the id variable, and run
&lt;code&gt;initialize&lt;/code&gt; again.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;If this affects you:&lt;/strong&gt; if a workflow runs &lt;code&gt;initialize&lt;/code&gt; with &lt;code&gt;edge_app_id&lt;/code&gt; set to deploy to an
app that already exists, that run now fails. Move that job to the &lt;code&gt;update&lt;/code&gt; action, which takes the
same &lt;code&gt;screenly_api_token&lt;/code&gt;, &lt;code&gt;environment&lt;/code&gt;, and &lt;code&gt;edge_app_id&lt;/code&gt; inputs.&lt;/p&gt;
&lt;/blockquote&gt;</description></item><item><title>Edge Apps GitHub Actions 26.10.1: Any app with a build script is built and deployed from dist</title><link>https://www.screenly.io/releases/edge-apps-actions/26.10.1/fixes-and-improvements/</link><guid isPermaLink="true">https://www.screenly.io/releases/edge-apps-actions/26.10.1/fixes-and-improvements/</guid><pubDate>Sat, 24 Oct 2026 00:00:00 +0000</pubDate><category>roundup</category><description>&lt;ul&gt;
&lt;li&gt;&lt;code&gt;initialize&lt;/code&gt; and &lt;code&gt;update&lt;/code&gt; build any app whose &lt;code&gt;package.json&lt;/code&gt; has a &lt;code&gt;build&lt;/code&gt; script, and deploy it
from &lt;code&gt;dist/&lt;/code&gt;, whether or not it depends on &lt;code&gt;@screenly/edge-apps&lt;/code&gt;. Apps without a &lt;code&gt;build&lt;/code&gt; script
deploy from the repo root as they are.&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Edge Apps GitHub Actions 26.10.0: The update action needs an edge_app_id on every deploy</title><link>https://www.screenly.io/releases/edge-apps-actions/26.10.0/update-requires-edge-app-id/</link><guid isPermaLink="true">https://www.screenly.io/releases/edge-apps-actions/26.10.0/update-requires-edge-app-id/</guid><pubDate>Thu, 08 Oct 2026 00:00:00 +0000</pubDate><category>improvement</category><category>developers</category><description>&lt;p&gt;&lt;code&gt;update&lt;/code&gt; requires &lt;code&gt;edge_app_id&lt;/code&gt; now. If it&amp;rsquo;s empty, or holds a leftover like &lt;code&gt;false&lt;/code&gt;, &lt;code&gt;null&lt;/code&gt;, or &lt;code&gt;0&lt;/code&gt;
from an expression that didn&amp;rsquo;t resolve to an id, the run stops in its first step and names the
variable to set: &lt;code&gt;STAGE_EDGE_APP_ID&lt;/code&gt; or &lt;code&gt;PRODUCTION_EDGE_APP_ID&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Both &lt;code&gt;initialize&lt;/code&gt; and &lt;code&gt;update&lt;/code&gt; also stop before doing anything else when:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;screenly_api_token&lt;/code&gt; is empty. The error asks you to add the &lt;code&gt;SCREENLY_API_TOKEN&lt;/code&gt; secret for that
environment, since stage and production each need one.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;environment&lt;/code&gt; is anything other than &lt;code&gt;stage&lt;/code&gt; or &lt;code&gt;production&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Screenly rejects the token for that environment. &lt;code&gt;initialize&lt;/code&gt; checks this now too, before it
creates an app.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;initialize&lt;/code&gt; treats the same leftovers (&lt;code&gt;false&lt;/code&gt;, &lt;code&gt;null&lt;/code&gt;, &lt;code&gt;0&lt;/code&gt;, and so on) as no id at all, so a first
run creates the app as expected.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;If this affects you:&lt;/strong&gt; if any &lt;code&gt;update&lt;/code&gt; step runs without &lt;code&gt;edge_app_id&lt;/code&gt;, add the repository
variables &lt;code&gt;STAGE_EDGE_APP_ID&lt;/code&gt; and &lt;code&gt;PRODUCTION_EDGE_APP_ID&lt;/code&gt; with each environment&amp;rsquo;s Edge App id, and
pass &lt;code&gt;edge_app_id: ${{ vars.STAGE_EDGE_APP_ID }}&lt;/code&gt; or &lt;code&gt;${{ vars.PRODUCTION_EDGE_APP_ID }}&lt;/code&gt; to each
&lt;code&gt;update&lt;/code&gt; step. Check that both environments have a &lt;code&gt;SCREENLY_API_TOKEN&lt;/code&gt; secret before you bump your
pin to &lt;code&gt;v26.10.0&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;</description></item><item><title>Edge Apps GitHub Actions 26.9.1: Stage and production both deploy from screenly.yml</title><link>https://www.screenly.io/releases/edge-apps-actions/26.9.1/one-manifest-for-both-environments/</link><guid isPermaLink="true">https://www.screenly.io/releases/edge-apps-actions/26.9.1/one-manifest-for-both-environments/</guid><pubDate>Mon, 21 Sep 2026 00:00:00 +0000</pubDate><category>removed</category><category>developers</category><description>&lt;p&gt;&lt;code&gt;initialize&lt;/code&gt; and &lt;code&gt;update&lt;/code&gt; read &lt;code&gt;screenly.yml&lt;/code&gt; in stage and production alike. &lt;code&gt;screenly_qc.yml&lt;/code&gt; isn&amp;rsquo;t
read anymore, whether or not you pass &lt;code&gt;edge_app_id&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;That also means an app with only &lt;code&gt;screenly.yml&lt;/code&gt; can run its first &lt;code&gt;initialize&lt;/code&gt; in stage. Leave
&lt;code&gt;edge_app_id&lt;/code&gt; out for that first run, then set the environment&amp;rsquo;s variable to the id of the app it
created. Every run after that passes the id:&lt;/p&gt;
&lt;div class="code-block"&gt;
&lt;button type="button" class="code-copy" aria-label="Copy code" data-copy-code&gt;
&lt;svg data-copy viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;
&lt;rect x="9" y="9" width="11" height="11" rx="2"&gt;&lt;/rect&gt;
&lt;path d="M5 15V5a2 2 0 0 1 2-2h10"&gt;&lt;/path&gt;
&lt;/svg&gt;
&lt;svg data-check viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;
&lt;path d="M20 6 9 17l-5-5"&gt;&lt;/path&gt;
&lt;/svg&gt;
&lt;/button&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;- &lt;span style="color:#6ab825;font-weight:bold"&gt;uses&lt;/span&gt;:&lt;span style="color:#666"&gt; &lt;/span&gt;Screenly/edge-apps-actions/update@v26.9.1&lt;span style="color:#666"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666"&gt; &lt;/span&gt;&lt;span style="color:#6ab825;font-weight:bold"&gt;with&lt;/span&gt;:&lt;span style="color:#666"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666"&gt; &lt;/span&gt;&lt;span style="color:#6ab825;font-weight:bold"&gt;screenly_api_token&lt;/span&gt;:&lt;span style="color:#666"&gt; &lt;/span&gt;${{ secrets.SCREENLY_API_TOKEN }}&lt;span style="color:#666"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666"&gt; &lt;/span&gt;&lt;span style="color:#6ab825;font-weight:bold"&gt;environment&lt;/span&gt;:&lt;span style="color:#666"&gt; &lt;/span&gt;stage&lt;span style="color:#666"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666"&gt; &lt;/span&gt;&lt;span style="color:#6ab825;font-weight:bold"&gt;edge_app_id&lt;/span&gt;:&lt;span style="color:#666"&gt; &lt;/span&gt;${{ vars.STAGE_EDGE_APP_ID }}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The id you pass wins over any &lt;code&gt;id&lt;/code&gt; in &lt;code&gt;screenly.yml&lt;/code&gt;, so 1 manifest serves both environments.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;If this affects you:&lt;/strong&gt; if your repo has a &lt;code&gt;screenly_qc.yml&lt;/code&gt;, move to 1 manifest before you bump
your pin to &lt;code&gt;v26.9.1&lt;/code&gt;. Copy anything that differs into &lt;code&gt;screenly.yml&lt;/code&gt; and delete &lt;code&gt;screenly_qc.yml&lt;/code&gt;.
Add the repository variables &lt;code&gt;STAGE_EDGE_APP_ID&lt;/code&gt; (the &lt;code&gt;id&lt;/code&gt; from &lt;code&gt;screenly_qc.yml&lt;/code&gt;) and
&lt;code&gt;PRODUCTION_EDGE_APP_ID&lt;/code&gt; (the &lt;code&gt;id&lt;/code&gt; from &lt;code&gt;screenly.yml&lt;/code&gt;), and pass
&lt;code&gt;edge_app_id: ${{ vars.STAGE_EDGE_APP_ID }}&lt;/code&gt; to your stage steps and
&lt;code&gt;edge_app_id: ${{ vars.PRODUCTION_EDGE_APP_ID }}&lt;/code&gt; to your production steps.&lt;/p&gt;
&lt;/blockquote&gt;</description></item><item><title>Edge Apps GitHub Actions 26.9.0: Each environment's Edge App id comes from a repository variable</title><link>https://www.screenly.io/releases/edge-apps-actions/26.9.0/edge-app-id-input/</link><guid isPermaLink="true">https://www.screenly.io/releases/edge-apps-actions/26.9.0/edge-app-id-input/</guid><pubDate>Tue, 08 Sep 2026 00:00:00 +0000</pubDate><category>release</category><category>developers</category><description>&lt;p&gt;An Edge App that runs in stage and production has 2 ids, and until now each one lived in its own
manifest: &lt;code&gt;screenly_qc.yml&lt;/code&gt; for stage and &lt;code&gt;screenly.yml&lt;/code&gt; for production. A setting added to one file
had to be added to the other.&lt;/p&gt;
&lt;p&gt;With the new &lt;code&gt;edge_app_id&lt;/code&gt; input, the id comes from the workflow instead. Keep each environment&amp;rsquo;s id
in a repository variable and pass the matching one:&lt;/p&gt;
&lt;div class="code-block"&gt;
&lt;button type="button" class="code-copy" aria-label="Copy code" data-copy-code&gt;
&lt;svg data-copy viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;
&lt;rect x="9" y="9" width="11" height="11" rx="2"&gt;&lt;/rect&gt;
&lt;path d="M5 15V5a2 2 0 0 1 2-2h10"&gt;&lt;/path&gt;
&lt;/svg&gt;
&lt;svg data-check viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;
&lt;path d="M20 6 9 17l-5-5"&gt;&lt;/path&gt;
&lt;/svg&gt;
&lt;/button&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;- &lt;span style="color:#6ab825;font-weight:bold"&gt;uses&lt;/span&gt;:&lt;span style="color:#666"&gt; &lt;/span&gt;Screenly/edge-apps-actions/update@v26.9.0&lt;span style="color:#666"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666"&gt; &lt;/span&gt;&lt;span style="color:#6ab825;font-weight:bold"&gt;with&lt;/span&gt;:&lt;span style="color:#666"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666"&gt; &lt;/span&gt;&lt;span style="color:#6ab825;font-weight:bold"&gt;screenly_api_token&lt;/span&gt;:&lt;span style="color:#666"&gt; &lt;/span&gt;${{ secrets.SCREENLY_API_TOKEN }}&lt;span style="color:#666"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666"&gt; &lt;/span&gt;&lt;span style="color:#6ab825;font-weight:bold"&gt;environment&lt;/span&gt;:&lt;span style="color:#666"&gt; &lt;/span&gt;stage&lt;span style="color:#666"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666"&gt; &lt;/span&gt;&lt;span style="color:#6ab825;font-weight:bold"&gt;edge_app_id&lt;/span&gt;:&lt;span style="color:#666"&gt; &lt;/span&gt;${{ vars.STAGE_EDGE_APP_ID }}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;When &lt;code&gt;edge_app_id&lt;/code&gt; is set, the action reads &lt;code&gt;screenly.yml&lt;/code&gt; in both environments, and the id you pass
wins over any &lt;code&gt;id&lt;/code&gt; in the manifest. So 1 manifest serves stage and production, and only the variable
changes between them.&lt;/p&gt;
&lt;p&gt;Leave it out and nothing changes: stage still reads &lt;code&gt;screenly_qc.yml&lt;/code&gt;, and production reads
&lt;code&gt;screenly.yml&lt;/code&gt;, each with its own &lt;code&gt;id&lt;/code&gt;.&lt;/p&gt;</description></item><item><title>Edge Apps GitHub Actions 26.9.0: The actions' version numbers moved to CalVer</title><link>https://www.screenly.io/releases/edge-apps-actions/26.9.0/calver-version-numbers/</link><guid isPermaLink="true">https://www.screenly.io/releases/edge-apps-actions/26.9.0/calver-version-numbers/</guid><pubDate>Tue, 08 Sep 2026 00:00:00 +0000</pubDate><category>improvement</category><category>developers</category><description>&lt;p&gt;Releases of the Edge Apps GitHub Actions are numbered by year and month now, so the release after
1.3.0 is 26.9.0. That&amp;rsquo;s the same scheme Screenly, ScreenlyOS, the CLI, and the Edge Apps library
use.&lt;/p&gt;
&lt;p&gt;Each release is 1 fixed tag, such as &lt;code&gt;v26.9.0&lt;/code&gt;, and there&amp;rsquo;s no moving tag that follows the latest
release. &lt;code&gt;v1&lt;/code&gt; stays on 1.3.0 for good. A workflow that uses &lt;code&gt;@v1&lt;/code&gt; keeps running exactly what it ran
before, and it won&amp;rsquo;t get anything released from here on.&lt;/p&gt;
&lt;p&gt;Nothing about the actions&amp;rsquo; behavior changes with the numbering.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;If this affects you:&lt;/strong&gt; a workflow that uses &lt;code&gt;@v1&lt;/code&gt; won&amp;rsquo;t pick up new releases. Replace &lt;code&gt;@v1&lt;/code&gt; with
an exact tag, such as &lt;code&gt;Screenly/edge-apps-actions/update@v26.9.0&lt;/code&gt;, and bump it when you want a
newer release. Dependabot&amp;rsquo;s &lt;code&gt;github-actions&lt;/code&gt; updates can open those bumps for you.&lt;/p&gt;
&lt;/blockquote&gt;</description></item><item><title>Edge Apps GitHub Actions 26.9.0: Builds work with the Edge Apps library in dependencies, and other improvements</title><link>https://www.screenly.io/releases/edge-apps-actions/26.9.0/fixes-and-improvements/</link><guid isPermaLink="true">https://www.screenly.io/releases/edge-apps-actions/26.9.0/fixes-and-improvements/</guid><pubDate>Tue, 08 Sep 2026 00:00:00 +0000</pubDate><category>roundup</category><description>&lt;h2 id="fixes"&gt;Fixes&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;initialize&lt;/code&gt; and &lt;code&gt;update&lt;/code&gt; build your app when &lt;code&gt;@screenly/edge-apps&lt;/code&gt; is listed under
&lt;code&gt;dependencies&lt;/code&gt;, not only under &lt;code&gt;devDependencies&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="improvements"&gt;Improvements&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;initialize&lt;/code&gt; and &lt;code&gt;update&lt;/code&gt; run Screenly CLI 26.9.0 instead of whichever CLI release is newest, so a
new CLI release doesn&amp;rsquo;t change how your app deploys until you move to a newer version of the
actions.&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Edge Apps GitHub Actions 1.3.0: Settings deleted from the manifest are removed from Screenly too</title><link>https://www.screenly.io/releases/edge-apps-actions/1.3.0/delete-missing-settings/</link><guid isPermaLink="true">https://www.screenly.io/releases/edge-apps-actions/1.3.0/delete-missing-settings/</guid><pubDate>Fri, 24 Apr 2026 00:00:00 +0000</pubDate><category>improvement</category><category>developers</category><description>&lt;p&gt;A deploy adds and updates the settings in your manifest, and leaves alone any setting that&amp;rsquo;s in
Screenly but no longer in the file. When the manifest is the only place you manage settings, set
&lt;code&gt;delete_missing_settings&lt;/code&gt; and those leftovers go too:&lt;/p&gt;
&lt;div class="code-block"&gt;
&lt;button type="button" class="code-copy" aria-label="Copy code" data-copy-code&gt;
&lt;svg data-copy viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;
&lt;rect x="9" y="9" width="11" height="11" rx="2"&gt;&lt;/rect&gt;
&lt;path d="M5 15V5a2 2 0 0 1 2-2h10"&gt;&lt;/path&gt;
&lt;/svg&gt;
&lt;svg data-check viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;
&lt;path d="M20 6 9 17l-5-5"&gt;&lt;/path&gt;
&lt;/svg&gt;
&lt;/button&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;- &lt;span style="color:#6ab825;font-weight:bold"&gt;uses&lt;/span&gt;:&lt;span style="color:#666"&gt; &lt;/span&gt;Screenly/edge-apps-actions/update@v1&lt;span style="color:#666"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666"&gt; &lt;/span&gt;&lt;span style="color:#6ab825;font-weight:bold"&gt;with&lt;/span&gt;:&lt;span style="color:#666"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666"&gt; &lt;/span&gt;&lt;span style="color:#6ab825;font-weight:bold"&gt;screenly_api_token&lt;/span&gt;:&lt;span style="color:#666"&gt; &lt;/span&gt;${{ secrets.SCREENLY_API_TOKEN }}&lt;span style="color:#666"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666"&gt; &lt;/span&gt;&lt;span style="color:#6ab825;font-weight:bold"&gt;environment&lt;/span&gt;:&lt;span style="color:#666"&gt; &lt;/span&gt;production&lt;span style="color:#666"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666"&gt; &lt;/span&gt;&lt;span style="color:#6ab825;font-weight:bold"&gt;delete_missing_settings&lt;/span&gt;:&lt;span style="color:#666"&gt; &lt;/span&gt;&lt;span style="color:#6ab825;font-weight:bold"&gt;true&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;It&amp;rsquo;s &lt;code&gt;false&lt;/code&gt; by default, so a deploy only deletes settings when you ask it to.&lt;/p&gt;</description></item><item><title>Edge Apps GitHub Actions 1.2.2: Deploy logs no longer list your other Edge Apps</title><link>https://www.screenly.io/releases/edge-apps-actions/1.2.2/fixes-and-improvements/</link><guid isPermaLink="true">https://www.screenly.io/releases/edge-apps-actions/1.2.2/fixes-and-improvements/</guid><pubDate>Fri, 24 Apr 2026 00:00:00 +0000</pubDate><category>roundup</category><description>&lt;h2 id="improvements"&gt;Improvements&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;The update action no longer prints the names of every Edge App in your account to the deploy
log. The log shows the app you&amp;rsquo;re deploying and nothing else.&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Edge Apps GitHub Actions 1.2.1: The update action checks your API token before it builds</title><link>https://www.screenly.io/releases/edge-apps-actions/1.2.1/fixes-and-improvements/</link><guid isPermaLink="true">https://www.screenly.io/releases/edge-apps-actions/1.2.1/fixes-and-improvements/</guid><pubDate>Fri, 24 Apr 2026 00:00:00 +0000</pubDate><category>roundup</category><description>&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;update&lt;/code&gt; action checks &lt;code&gt;screenly_api_token&lt;/code&gt; against Screenly before it builds anything. If
Screenly rejects the token, the run stops right there and the log shows the HTTP status.&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Edge Apps GitHub Actions 1.2.0: A new update action deploys an existing Edge App</title><link>https://www.screenly.io/releases/edge-apps-actions/1.2.0/update-action/</link><guid isPermaLink="true">https://www.screenly.io/releases/edge-apps-actions/1.2.0/update-action/</guid><pubDate>Wed, 22 Apr 2026 00:00:00 +0000</pubDate><category>release</category><category>developers</category><description>&lt;p&gt;Once &lt;code&gt;initialize&lt;/code&gt; has created an Edge App, the &lt;code&gt;update&lt;/code&gt; action ships each new version of it. Put it
in a workflow that runs on push, and every merge reaches Screenly without anyone running the CLI by
hand:&lt;/p&gt;
&lt;div class="code-block"&gt;
&lt;button type="button" class="code-copy" aria-label="Copy code" data-copy-code&gt;
&lt;svg data-copy viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;
&lt;rect x="9" y="9" width="11" height="11" rx="2"&gt;&lt;/rect&gt;
&lt;path d="M5 15V5a2 2 0 0 1 2-2h10"&gt;&lt;/path&gt;
&lt;/svg&gt;
&lt;svg data-check viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;
&lt;path d="M20 6 9 17l-5-5"&gt;&lt;/path&gt;
&lt;/svg&gt;
&lt;/button&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;- &lt;span style="color:#6ab825;font-weight:bold"&gt;uses&lt;/span&gt;:&lt;span style="color:#666"&gt; &lt;/span&gt;Screenly/edge-apps-actions/update@v1&lt;span style="color:#666"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666"&gt; &lt;/span&gt;&lt;span style="color:#6ab825;font-weight:bold"&gt;with&lt;/span&gt;:&lt;span style="color:#666"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666"&gt; &lt;/span&gt;&lt;span style="color:#6ab825;font-weight:bold"&gt;screenly_api_token&lt;/span&gt;:&lt;span style="color:#666"&gt; &lt;/span&gt;${{ secrets.SCREENLY_API_TOKEN }}&lt;span style="color:#666"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666"&gt; &lt;/span&gt;&lt;span style="color:#6ab825;font-weight:bold"&gt;environment&lt;/span&gt;:&lt;span style="color:#666"&gt; &lt;/span&gt;stage&lt;span style="color:#666"&gt; &lt;/span&gt;&lt;span style="color:#999;font-style:italic"&gt;# optional, defaults to stage&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;It builds the same way &lt;code&gt;initialize&lt;/code&gt; does. If &lt;code&gt;package.json&lt;/code&gt; lists &lt;code&gt;@screenly/edge-apps&lt;/code&gt; under
&lt;code&gt;devDependencies&lt;/code&gt;, it installs with Bun, runs &lt;code&gt;bun run build&lt;/code&gt;, and deploys &lt;code&gt;dist/&lt;/code&gt;. Otherwise it
deploys the repo root as it is.&lt;/p&gt;
&lt;p&gt;The app it deploys to is the one whose id is in the manifest: &lt;code&gt;screenly_qc.yml&lt;/code&gt; for &lt;code&gt;stage&lt;/code&gt; and
&lt;code&gt;screenly.yml&lt;/code&gt; for &lt;code&gt;production&lt;/code&gt;.&lt;/p&gt;</description></item><item><title>Edge Apps GitHub Actions 1.1.0: A new initialize action creates an Edge App and its first instance</title><link>https://www.screenly.io/releases/edge-apps-actions/1.1.0/initialize-action/</link><guid isPermaLink="true">https://www.screenly.io/releases/edge-apps-actions/1.1.0/initialize-action/</guid><pubDate>Wed, 22 Apr 2026 00:00:00 +0000</pubDate><category>release</category><category>developers</category><description>&lt;p&gt;The &lt;code&gt;initialize&lt;/code&gt; action takes an Edge App from a repo to a running instance in 1 workflow run. It
creates the app in Screenly, deploys the code, and creates an instance:&lt;/p&gt;
&lt;div class="code-block"&gt;
&lt;button type="button" class="code-copy" aria-label="Copy code" data-copy-code&gt;
&lt;svg data-copy viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;
&lt;rect x="9" y="9" width="11" height="11" rx="2"&gt;&lt;/rect&gt;
&lt;path d="M5 15V5a2 2 0 0 1 2-2h10"&gt;&lt;/path&gt;
&lt;/svg&gt;
&lt;svg data-check viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;
&lt;path d="M20 6 9 17l-5-5"&gt;&lt;/path&gt;
&lt;/svg&gt;
&lt;/button&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;- &lt;span style="color:#6ab825;font-weight:bold"&gt;uses&lt;/span&gt;:&lt;span style="color:#666"&gt; &lt;/span&gt;Screenly/edge-apps-actions/initialize@v1&lt;span style="color:#666"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666"&gt; &lt;/span&gt;&lt;span style="color:#6ab825;font-weight:bold"&gt;with&lt;/span&gt;:&lt;span style="color:#666"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666"&gt; &lt;/span&gt;&lt;span style="color:#6ab825;font-weight:bold"&gt;screenly_api_token&lt;/span&gt;:&lt;span style="color:#666"&gt; &lt;/span&gt;${{ secrets.SCREENLY_API_TOKEN }}&lt;span style="color:#666"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666"&gt; &lt;/span&gt;&lt;span style="color:#6ab825;font-weight:bold"&gt;edge_app_name&lt;/span&gt;:&lt;span style="color:#666"&gt; &lt;/span&gt;my-edge-app&lt;span style="color:#666"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666"&gt; &lt;/span&gt;&lt;span style="color:#6ab825;font-weight:bold"&gt;edge_app_title&lt;/span&gt;:&lt;span style="color:#666"&gt; &lt;/span&gt;My Edge App&lt;span style="color:#666"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666"&gt; &lt;/span&gt;&lt;span style="color:#6ab825;font-weight:bold"&gt;environment&lt;/span&gt;:&lt;span style="color:#666"&gt; &lt;/span&gt;stage&lt;span style="color:#666"&gt; &lt;/span&gt;&lt;span style="color:#999;font-style:italic"&gt;# optional, defaults to stage&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;code&gt;edge_app_name&lt;/code&gt; is the app&amp;rsquo;s name, and &lt;code&gt;edge_app_title&lt;/code&gt; is the title its instance gets. &lt;code&gt;environment&lt;/code&gt;
is &lt;code&gt;stage&lt;/code&gt; or &lt;code&gt;production&lt;/code&gt;. Stage reads its manifest from &lt;code&gt;screenly_qc.yml&lt;/code&gt;, and production reads
&lt;code&gt;screenly.yml&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If &lt;code&gt;package.json&lt;/code&gt; lists &lt;code&gt;@screenly/edge-apps&lt;/code&gt; under &lt;code&gt;devDependencies&lt;/code&gt;, the action installs
dependencies with Bun, runs &lt;code&gt;bun run build&lt;/code&gt;, and deploys &lt;code&gt;dist/&lt;/code&gt;. Any other app is deployed from the
repo root as it is.&lt;/p&gt;
&lt;p&gt;The job log ends with the manifest and &lt;code&gt;instance.yml&lt;/code&gt;, so you can copy the new app&amp;rsquo;s id into the
manifest in your repo for later deploys.&lt;/p&gt;</description></item><item><title>Edge Apps GitHub Actions 1.0.0: A checks action runs an Edge App's formatting, lint, build, and tests in 1 step</title><link>https://www.screenly.io/releases/edge-apps-actions/1.0.0/checks-action/</link><guid isPermaLink="true">https://www.screenly.io/releases/edge-apps-actions/1.0.0/checks-action/</guid><pubDate>Mon, 20 Apr 2026 00:00:00 +0000</pubDate><category>release</category><category>developers</category><description>&lt;p&gt;The &lt;code&gt;checks&lt;/code&gt; action runs the usual CI steps for an Edge App as 1 step in your workflow. Add it after
the checkout step:&lt;/p&gt;
&lt;div class="code-block"&gt;
&lt;button type="button" class="code-copy" aria-label="Copy code" data-copy-code&gt;
&lt;svg data-copy viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;
&lt;rect x="9" y="9" width="11" height="11" rx="2"&gt;&lt;/rect&gt;
&lt;path d="M5 15V5a2 2 0 0 1 2-2h10"&gt;&lt;/path&gt;
&lt;/svg&gt;
&lt;svg data-check viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;
&lt;path d="M20 6 9 17l-5-5"&gt;&lt;/path&gt;
&lt;/svg&gt;
&lt;/button&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;- &lt;span style="color:#6ab825;font-weight:bold"&gt;uses&lt;/span&gt;:&lt;span style="color:#666"&gt; &lt;/span&gt;Screenly/edge-apps-actions/checks@v1&lt;span style="color:#666"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666"&gt; &lt;/span&gt;&lt;span style="color:#6ab825;font-weight:bold"&gt;with&lt;/span&gt;:&lt;span style="color:#666"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666"&gt; &lt;/span&gt;&lt;span style="color:#6ab825;font-weight:bold"&gt;bun-version&lt;/span&gt;:&lt;span style="color:#666"&gt; &lt;/span&gt;latest&lt;span style="color:#666"&gt; &lt;/span&gt;&lt;span style="color:#999;font-style:italic"&gt;# optional&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;It sets up Bun, installs dependencies with &lt;code&gt;bun install --frozen-lockfile&lt;/code&gt;, and then runs these
scripts from your &lt;code&gt;package.json&lt;/code&gt;, stopping at the first one that fails:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;format:check&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;lint&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;build&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;test&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;So the repo needs all 4 scripts and a committed Bun lockfile. &lt;code&gt;bun-version&lt;/code&gt; picks the Bun release,
and it&amp;rsquo;s &lt;code&gt;latest&lt;/code&gt; when you leave it out.&lt;/p&gt;</description></item></channel></rss>