Automate Pinning with GitHub Actions
Automatically upload build artifacts to IPFS every time you push to your repository.
Set up secrets
Add your Pinner API key as a repository secret:
- Go to Settings → Secrets and variables → Actions
- Click New repository secret
- Name:
PINNER_AUTH_TOKEN - Value: your API key from API Keys
Create the workflow
Create .github/workflows/pinner.yml:
name: Pin to IPFS
on:
push:
branches: [main]
jobs:
pin:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Pinner CLI
run: go install go.lumeweb.com/pinner-cli/cmd/pinner@latest
- name: Authenticate
run: pinner auth ${{ secrets.PINNER_AUTH_TOKEN }}
- name: Upload build output
id: upload
run: pinner upload ./dist/ --name "ci-build"
- name: Verify pin
run: pinner status ${{ steps.upload.outputs.cid }}How it works
- On every push to
main, the workflow installs the Pinner CLI - It authenticates with your JWT token using
pinner auth - It uploads the
./dist/directory withpinner upload - It verifies the pin was created with
pinner status
The pinner upload command outputs the CID, gateway URL, size, and duration. The pinner status command checks whether the pin has reached a terminal state (pinned or failed).
Using the SDK instead
If you prefer the JavaScript SDK in a Node.js script:
- name: Upload with SDK
env:
PINNER_AUTH_TOKEN: ${{ secrets.PINNER_AUTH_TOKEN }}
run: node scripts/upload-to-ipfs.mjs// scripts/upload-to-ipfs.mjs
import { Pinner } from "@lumeweb/pinner";
import fs from "fs";
const pinner = new Pinner({ jwt: process.env.PINNER_AUTH_TOKEN });
const files = fs.readdirSync("./dist").map((name) => {
const buffer = fs.readFileSync(`./dist/${name}`);
return new File([buffer], name);
});
const operation = await pinner.uploadDirectory(files, { name: "ci-build" });
const result = await operation.result;
console.log("Root CID:", result.cid);