GitHub Action
Upload builds from GitHub Actions with automatic metadata collection.
Quick Start
- name: Upload to nunu.ai
uses: nunu-ai/upload-build-action@v1
with:
api-token: ${{ secrets.NUNU_API_TOKEN }}
project-id: ${{ secrets.NUNU_PROJECT_ID }}
file: "build/app.apk"
name: "Build ${{ github.run_number }}"Setup
1. Get API Token
- Go to Project Admin → API Keys in nunu.ai
- Create token with
project:manage-build-storagepermission - Copy the token
2. Add Secrets
In your GitHub repository:
- Go to Settings → Secrets and variables → Actions
- Add
NUNU_API_TOKENwith your API token - Add
NUNU_PROJECT_IDwith your project ID
3. Use the Action
Add to your workflow:
name: Build and Upload
on:
push:
branches: [main]
pull_request:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build
run: ./build.sh
- name: Upload to nunu.ai
uses: nunu-ai/upload-build-action@v1
with:
api-token: ${{ secrets.NUNU_API_TOKEN }}
project-id: ${{ secrets.NUNU_PROJECT_ID }}
file: "build/app.apk"
name: "Build ${{ github.run_number }}"Inputs
Required
| Input | Description |
|---|---|
api-token | nunu.ai API token |
project-id | nunu.ai project ID |
file | Path to build file or glob pattern |
Optional
| Input | Default | Description |
|---|---|---|
name | Build {run_number} | Build name |
platform | Auto-detected | Target platform (see platform detection) |
description | None | Build description |
auto-delete | false | Auto-delete old builds when capacity reached |
deletion-policy | least_recent | Policy: least_recent or oldest |
upload-timeout | 10 (single) 60 (multipart) | Upload timeout in minutes (1-1440) |
tags | None | Comma-separated tags |
cli-version | latest | nunu-cli version to use |
File Pattern Matching
The file input supports glob patterns for when you don’t know the exact filename:
# When version is in filename
- uses: nunu-ai/upload-build-action@v1
with:
api-token: ${{ secrets.NUNU_API_TOKEN }}
project-id: ${{ secrets.NUNU_PROJECT_ID }}
file: "build/app-v*.apk"
name: "Android Release ${{ github.run_number }}"
# When build adds timestamps or hashes
- uses: nunu-ai/upload-build-action@v1
with:
api-token: ${{ secrets.NUNU_API_TOKEN }}
project-id: ${{ secrets.NUNU_PROJECT_ID }}
file: "dist/myapp-*.exe"
name: "Windows Build"Supported patterns:
*- Any characters (e.g.,app-v*.apk)?- Single character (e.g.,app-?.apk)[...]- Character sets (e.g.,app-[123].apk)
This is useful when your build process generates filenames with version numbers, timestamps, or other dynamic values.
If multiple files match, each becomes a separate build.
Platform Detection
Platform is auto-detected from file extension:
| Extensions | Platform |
|---|---|
.exe, .msi | windows |
.dmg, .pkg | macos |
.deb, .rpm, .appimage | linux |
.apk | android |
.ipa | ios-native |
For ambiguous files (.zip, .tar, .app), specify platform explicitly.
Outputs
| Output | Description |
|---|---|
build-id | UUID of the uploaded build |
Using Outputs
- name: Upload
id: upload
uses: nunu-ai/upload-build-action@v1
with:
api-token: ${{ secrets.NUNU_API_TOKEN }}
project-id: ${{ secrets.NUNU_PROJECT_ID }}
file: "build/app.apk"
- name: Comment on PR
run: |
echo "Build uploaded: ${{ steps.upload.outputs.build-id }}"Examples
Multi-Platform
strategy:
matrix:
include:
- os: ubuntu-latest
platform: linux
file: "dist/app-linux"
- os: macos-latest
platform: macos
file: "dist/app-macos"
- os: windows-latest
platform: windows
file: "dist/app.exe"
steps:
- uses: actions/checkout@v4
- name: Build
run: ./build.sh
- name: Upload
uses: nunu-ai/upload-build-action@v1
with:
api-token: ${{ secrets.NUNU_API_TOKEN }}
project-id: ${{ secrets.NUNU_PROJECT_ID }}
file: ${{ matrix.file }}
name: "${{ matrix.platform }} Build ${{ github.run_number }}"
platform: ${{ matrix.platform }}With Tags
- name: Upload
uses: nunu-ai/upload-build-action@v1
with:
api-token: ${{ secrets.NUNU_API_TOKEN }}
project-id: ${{ secrets.NUNU_PROJECT_ID }}
file: "build/app.apk"
name: "Production Build"
tags: "version:1.2.3,env:production,commit:${{ github.sha }}"Auto-Delete Old Builds
- name: Upload
uses: nunu-ai/upload-build-action@v1
with:
api-token: ${{ secrets.NUNU_API_TOKEN }}
project-id: ${{ secrets.NUNU_PROJECT_ID }}
file: "build/app.apk"
name: "Dev Build"
auto-delete: true
deletion-policy: "least_recent"How It Works
This action downloads and runs nunu-cli , which automatically collects metadata from the GitHub Actions environment:
- Git: Commit hash, branch, author, message
- Pull Request: PR number, title, source/target branches (when applicable)
- CI: Workflow name, run number, run URL, runner, triggered by
- Build: Timestamp, CLI version
The same metadata collection works when using nunu-cli directly in other CI/CD systems.
Troubleshooting
”File not found”
Verify the file exists:
- name: Verify file
run: ls -lh build/app.apk
- name: Upload
uses: nunu-ai/upload-build-action@v1
# ...“Invalid API token”
Check:
- Token has
project:manage-build-storagepermission - Secret name is exactly
NUNU_API_TOKEN - Try regenerating the token
Upload timeout
For large files, increase timeout:
with:
upload-timeout: "120" # 2 hoursNext Steps
- Build Storage Triggers - Automatically run tests on upload
- CLI Documentation - Upload from other CI/CD systems
- API Reference - Build custom integrations