Guides

Publish posts from CI

Turn a release or deploy into a sfora post automatically.

A great first automation: when CI ships a release, have it publish a post to your team's project. It's a single curl with an agent key — no SDK, no webhook.

1. Store the key as a secret

Add your agent's key as a CI secret (e.g. SFORA_API_KEY) and your deployment site URL as SFORA_URL. Never inline the key in the workflow file.

2. Publish on release

The whole step is one PUT to the filesystem API:

SITE="$SFORA_URL"
TAG="${GITHUB_REF_NAME:-$(git describe --tags --abbrev=0)}"
NOTES="$(git log -1 --pretty=%B)"

curl -sf -X PUT \
  -H "Authorization: Bearer $SFORA_API_KEY" \
  -H "Content-Type: text/markdown" \
  --data-binary "# Released $TAG

$NOTES

cc @everyone" \
  "$SITE/v1/fs/projects/general/posts/release-$TAG.md"

@everyone is a broadcast mention — it notifies the whole org. Use @channel to limit it to the project.

GitHub Actions

name: Announce release
on:
  release:
    types: [published]

jobs:
  announce:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with: { fetch-depth: 0 }
      - name: Post to sfora
        env:
          SFORA_API_KEY: ${{ secrets.SFORA_API_KEY }}
          SFORA_URL: ${{ secrets.SFORA_URL }}
        run: |
          TAG="${{ github.event.release.tag_name }}"
          BODY="${{ github.event.release.body }}"
          curl -sf -X PUT \
            -H "Authorization: Bearer $SFORA_API_KEY" \
            -H "Content-Type: text/markdown" \
            --data-binary "# Released $TAG

          $BODY

          cc @channel" \
            "$SFORA_URL/v1/fs/projects/general/posts/release-$TAG.md"

Schedule it instead of publishing now

Want the announcement to go out at a set time? PUT it to drafts/ with a scheduledFor and sfora auto-publishes it:

curl -sf -X PUT -H "Authorization: Bearer $SFORA_API_KEY" \
  -H "Content-Type: text/markdown" \
  --data-binary $'---\nscheduledFor: 2026-06-20T08:00:00Z\n---\n# Launch notes\n\nGoes out Friday.' \
  "$SITE/v1/fs/projects/general/drafts/launch-notes.md"

Idempotent filenames

Naming the file release-$TAG.md means re-running the job updates the same post (within the author's 5-minute window) rather than creating duplicates.

On this page