Windows aplikace pro automatické nasazování přes GitHub Actions self-hosted runner. Primárně pro flashování firmware do IoT zařízení (Arduino), volitelně i pro nasazení .NET aplikací z předem připravených buildů (artefaktů).
IoTDeploy umožňuje jedním kliknutím (nebo z příkazové řádky) spustit deployment workflow na GitHubu. Aplikace:
- Připojí se k GitHub repozitáři přes GitHub App autentizaci
- Stáhne a nakonfiguruje GitHub Actions self-hosted runner
- Stáhne Arduino CLI toolchain (capability deployera — využije ho IoT workflow, .NET workflow ho ignoruje)
- Volitelně rozliší build artefakt z předchozího CI runu (
--useartifact <runId|latest>) - Spustí deployment workflow s parametry (větev, prostředí, COM port a/nebo artefakt)
- Automaticky schválí deployment přes GitHub Environments
- Po dokončení uklidí runner
- Windows 10/11 (aplikace je WinForms)
- .NET 9.0 Runtime – stáhnout zde
- IoT zařízení připojené přes USB (COM port)
- Přístup k internetu (stahování runneru, Arduino CLI, GitHub API)
Aplikace se autentizuje vůči GitHubu pomocí GitHub App (ne osobním tokenem). Postupuj takto:
-
Přejdi do GitHub → Settings → Developer settings → GitHub Apps → New GitHub App (nebo pro organizaci: Org Settings → Developer settings → GitHub Apps)
-
Vyplň:
- GitHub App name:
IoT Deployer(nebo libovolný název) - Homepage URL: libovolná URL (např. URL repozitáře)
- Webhook: odškrtni
Active(webhook nepotřebujeme)
- GitHub App name:
-
Permissions – nastav tato oprávnění:
Oprávnění Úroveň Repository → Actions Read & write Repository → Administration Read & write Repository → Deployments Read & write Repository → Environments Read-only Repository → Metadata Read-only -
Where can this GitHub App be installed? → dle potřeby (
Only on this accountneboAny account) -
Klikni Create GitHub App
Po vytvoření se zobrazí stránka s nastavením aplikace. App ID je hned nahoře (číslo). Zapiš si ho.
- Na stránce nastavení GitHub App scrolluj dolů na sekci Private keys
- Klikni Generate a private key
- Stáhne se soubor ve formátu
<jméno-aplikace>.<datum>.private-key.pem - Přejmenuj nebo ponech soubor tak, aby odpovídal vzoru
iot-deployer.*.private-key.pem- Pokud máš jiný název, uprav
PemFilePatternvappsettings.json
- Pokud máš jiný název, uprav
- Zkopíruj
.pemsoubor do složky vedle spustitelného souboru aplikace
- Na stránce GitHub App klikni Install App (vlevo)
- Vyber účet/organizaci a poté repozitář (nebo všechny)
- Klikni Install
- Po instalaci se v URL zobrazí Installation ID (číslo za
/installations/). Zapiš si ho.- Alternativně: v nastavení organizace Installed GitHub Apps → klikni na app → URL obsahuje installation ID
Aby aplikace mohla automaticky schvalovat deployment, musí být GitHub App přidána jako Required Reviewer v Environment:
- Přejdi do repozitáře → Settings → Environments
- Vyber (nebo vytvoř) environment, do kterého chceš nasazovat
- V sekci Deployment protection rules zaškrtni Required reviewers
- Přidej GitHub App jako reviewera (zadej jméno app)
- Ulož
Alternativně použij přiložený PowerShell skript:
.\setup-environment-reviewer.ps1 `
-Repository "nazev-repozitare" `
-Environment "nazev-prostredi" `
-Token "ghp_tvujPersonalniToken"Vedle spustitelného .exe souboru musí být soubor appsettings.json:
{
"GitHub": {
"AppId": "ZDE_APP_ID",
"InstallationId": ZDE_INSTALLATION_ID,
"Owner": "jmeno-organizace-nebo-uzivatele",
"PemFilePattern": "iot-deployer.*.private-key.pem"
},
"Runner": {
"WorkflowTimeoutMinutes": 2,
"Labels": ["iot"]
}
}| Položka | Popis | Příklad |
|---|---|---|
GitHub.AppId |
App ID z GitHub App (viz krok 2) | "2427873" |
GitHub.InstallationId |
Installation ID (viz krok 4) | 98456061 |
GitHub.Owner |
Jméno GitHub uživatele nebo organizace | "MojeOrg" |
GitHub.PemFilePattern |
Vzor pro nalezení .pem souboru |
"iot-deployer.*.private-key.pem" |
Runner.WorkflowTimeoutMinutes |
Timeout čekání na spuštění workflow (minuty) | 2 |
Runner.Labels |
Labely self-hosted runneru (musí odpovídat runs-on ve workflow) |
["iot"] |
Výsledná struktura složky aplikace musí vypadat takto:
IoTDeploy/
├── IoTDeployUI.exe ← spustitelný soubor
├── appsettings.json ← konfigurace
└── iot-deployer.2026-01-01.private-key.pem ← privátní klíč GitHub App
GitHub Actions Runner a Arduino CLI se stahují automaticky při prvním spuštění deploymentu do podsložky
runners/.
Tvůj repozitář musí obsahovat workflow, který:
- Běží na self-hosted runneru s labelem nastaveným v
Runner.Labels(výchozí:iot) - Je spouštěn přes
deployment_statusevent - Čte parametry z
github.event.deployment.payload.<Key>
on:
deployment_status:
jobs:
flash-firmware:
if: github.event.deployment_status.state == 'success'
runs-on: [self-hosted, iot]
environment: ${{ github.event.deployment.environment }}
steps:
- uses: actions/checkout@v4
- name: Upload firmware
run: arduino-cli upload --port ${{ github.event.deployment.payload.serial_port }} ...CI workflow (build.yml) vytváří artefakt:
name: Build
on:
push:
branches: [main, develop]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-dotnet@v4
with:
dotnet-version: '9.0.x'
- run: dotnet publish -c Release -o publish/
- uses: actions/upload-artifact@v4
with:
name: publish
path: publish/Deployment workflow (deploy.yml) — IoTDeploy předá v payloadu artifact_run_id (a artifact_name):
on:
deployment_status:
jobs:
deploy:
if: github.event.deployment_status.state == 'success'
runs-on: [self-hosted, iot]
environment: ${{ github.event.deployment.environment }}
steps:
- uses: actions/download-artifact@v4
with:
run-id: ${{ github.event.deployment.payload.artifact_run_id }}
name: ${{ github.event.deployment.payload.artifact_name }}
github-token: ${{ secrets.GITHUB_TOKEN }}
path: app
- name: Deploy
shell: pwsh
run: |
$target = "${{ github.event.deployment.payload.target_path }}"
Copy-Item -Recurse -Force app\* $targetPozor:
actions/download-artifact@v4srun-idz jiného workflow potřebuje token sactions: read. GitHub App, kterou IoTDeploy používá, máActions: Read & write, což to pokrývá —secrets.GITHUB_TOKENv deploymentu funguje.
- Spusť
IoTDeployUI.exe - Aplikace se připojí k GitHubu a načte repozitáře dostupné pro GitHub App
- Vyber:
- Repository – repozitář
- Branch – větev
- Environment – GitHub Environment (musí existovat v repozitáři)
- COM port – volitelné, jen pro IoT flashování
- Use artifact – volitelné, pro .NET deploye. Po zaškrtnutí dropdown nabídne posledních 10 úspěšných buildů na vybrané větvi (první položka =
Latest).
- Klikni Deploy
- Sleduj průběh ve stavovém řádku
- Pro zrušení klikni Cancel
IoTDeploy.exe <repository> <branch> <environment> [<port>]
[--useartifact <runId|latest>] [--artifact-name <name>] [--workflow <file>]
| Argument | Popis |
|---|---|
<repository> |
Jméno repozitáře (povinné, poziční) |
<branch> |
Větev (povinné, poziční) |
<environment> |
GitHub Environment (povinné, poziční) |
<port> |
COM port (volitelné 4. poziční). Pokud zadáno, předá se jako serial_port. |
--useartifact <id|latest> |
Předá artifact_run_id v payloadu. latest se resolvuje těsně před triggerem na nejnovější úspěšný run s artefaktem na dané větvi. |
--artifact-name <name> |
Filtr na konkrétní jméno artefaktu (z actions/upload-artifact). Při latest resolve omezuje, v který run se má hledat. |
--workflow <file> |
Filtr na konkrétní CI workflow (build.yml). Použije se při latest resolve. |
Příklady:
# IoT (zpětně kompatibilní s předchozí verzí)
IoTDeploy.exe my-firmware main prod COM3
# .NET — latest build z větve main
IoTDeploy.exe my-app main staging --useartifact latest
# .NET — konkrétní run, jen artefakty se jménem 'publish' z workflow build.yml
IoTDeploy.exe my-app main staging --useartifact 12345678 --artifact-name publish --workflow build.ymlPři --useartifact latest zapíše IoTDeploy do logu konkrétní run_id, který se předal — auditní stopa pro případ, že potřebuješ vědět, jaký artefakt se nasadil.
Logy jsou ukládány do %LOCALAPPDATA%\IoTDeploy\logs\ (tlačítko Open Log otevře aktuální log v Notepadu).
| Problém | Řešení |
|---|---|
FileNotFoundException: appsettings.json |
Zkontroluj, že appsettings.json je ve stejné složce jako .exe |
FileNotFoundException: *.pem |
Zkontroluj název souboru s privátním klíčem – musí odpovídat vzoru PemFilePattern |
InvalidOperationException při startu |
Chybné AppId, InstallationId nebo neplatný privátní klíč |
| Repozitář se nezobrazuje | GitHub App není nainstalována do daného repozitáře (viz krok 4) |
| Workflow se nespustí (timeout) | Prodluž WorkflowTimeoutMinutes, zkontroluj, zda workflow existuje v repozitáři |
| Runner se nepřipojí | Zkontroluj, zda má GitHub App oprávnění Administration: Read & write |
| Arduino CLI nenajde zařízení | Zkontroluj COM port a zda není blokován jiným programem |
No successful run with artifact ... found |
Na zvolené větvi neexistuje úspěšný run s odpovídajícím artefaktem. Ověř, že CI workflow proběhl a --artifact-name / --workflow filtry odpovídají. |
--useartifact <id> workflow stáhne 0 souborů |
actions/download-artifact@v4 v deploy workflow potřebuje github-token s actions: read (typicky ${{ secrets.GITHUB_TOKEN }}). |