Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
4406014
chore: add npm manifest, TypeScript, lint, and test configuration
alihesari Aug 30, 2026
9f2a37e
feat: add action metadata with inputs, outputs, and branding
alihesari Aug 30, 2026
687f92f
feat: parse action inputs and mask the API key on read
alihesari Aug 30, 2026
91259b4
feat: map FoPost API errors to actionable, redacted messages
alihesari Aug 30, 2026
7dff6f4
feat: upload local media files before attaching them to a post
alihesari Aug 30, 2026
6c67f6d
feat: resolve accounts, create and publish the post, and write a job …
alihesari Aug 30, 2026
e028bb6
test: cover input parsing, secret masking, dry run, media upload, and…
alihesari Aug 30, 2026
41eb006
build: commit the ncc bundle that GitHub runs
alihesari Aug 30, 2026
e65ff8b
ci: add CI, stale-bundle check, self test, and tagged release workflows
alihesari Aug 30, 2026
7d5819d
docs: document usage, security, releasing, and add example workflows
alihesari Aug 30, 2026
9686e40
fix(media): upload to /v1 instead of the 404 /api/v1 path
alihesari Aug 30, 2026
520c6d8
test: match SDK requests by resource suffix, pin only our own upload URL
alihesari Aug 30, 2026
102c0fc
docs: correct the API base path and record the required 0.2.3 bump
alihesari Aug 30, 2026
63b50e7
build: rebuild the bundle with the corrected upload path
alihesari Aug 30, 2026
f5fd9a8
fix(action): drop the ${{ }} expression from the api-key description
alihesari Aug 30, 2026
6d4d395
test: fail on any ${{ }} expression in action.yml
alihesari Aug 30, 2026
87831af
fix(action): read fail-on-error before parsing, so a bad input honour…
alihesari Aug 30, 2026
8c692ae
test: cover fail-on-error false with an input-validation failure
alihesari Aug 30, 2026
b6aee0b
build: rebuild the bundle from lockfile-exact dependencies
alihesari Aug 30, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# The ncc bundle is build output that has to be committed for GitHub to run it.
# Keep it out of diffs and out of the language stats.
dist/** -diff linguist-generated=true
62 changes: 62 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
name: CI

on:
push:
branches: [main]
pull_request:
workflow_dispatch:

permissions:
contents: read

concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true

jobs:
check:
name: Node ${{ matrix.node }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
node: [20, 22]
steps:
- uses: actions/checkout@v4

- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}
cache: npm

- run: npm ci

- run: npm run lint
- run: npm run format:check
- run: npm run typecheck
- run: npm test

bundle:
name: dist is current
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

# Pinned to one version on purpose: the committed bundle has to be
# byte-identical to what this job produces, and that only holds when
# everyone builds on the same toolchain.
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm

- run: npm ci
- run: npm run build

- name: Fail if dist/ is stale
run: |
if ! git diff --exit-code --stat -- dist/; then
echo "::error::dist/ is out of date. Run \`npm run build\` and commit the result."
exit 1
fi
echo "dist/ matches the source."
71 changes: 71 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
name: Release

# Tag the commit `v<version>` matching package.json, e.g. v0.1.0.
on:
push:
tags:
- 'v*'
workflow_dispatch:

permissions:
contents: write

concurrency:
group: release
cancel-in-progress: false

jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0

- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm

- run: npm ci

- name: Verify tag matches package version
if: startsWith(github.ref, 'refs/tags/v')
run: |
TAG="${GITHUB_REF_NAME#v}"
VERSION=$(node -p "require('./package.json').version")
[ "$VERSION" = "$TAG" ] || { echo "::error::package.json is $VERSION but tag is $TAG"; exit 1; }

- run: npm run lint
- run: npm run typecheck
- run: npm test

# A release that ships a stale bundle ships the previous version's code.
- name: Verify the committed bundle is current
run: |
npm run build
if ! git diff --exit-code --stat -- dist/; then
echo "::error::dist/ does not match the source on this ref. Rebuild, commit, and re-tag."
exit 1
fi

- name: Create the GitHub Release
if: startsWith(github.ref, 'refs/tags/v')
env:
GH_TOKEN: ${{ github.token }}
run: |
gh release create "$GITHUB_REF_NAME" \
--title "$GITHUB_REF_NAME" \
--generate-notes \
--verify-tag

# Consumers pin `fopost/fopost-github-action@v0`, so the floating major
# tag has to follow every release on that major. A lightweight tag needs
# no committer identity.
- name: Move the major version tag
if: startsWith(github.ref, 'refs/tags/v')
run: |
MAJOR="${GITHUB_REF_NAME%%.*}"
git tag -f "$MAJOR" "$GITHUB_SHA"
git push --force origin "refs/tags/$MAJOR"
echo "$MAJOR now points at $GITHUB_SHA"
86 changes: 86 additions & 0 deletions .github/workflows/self-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
name: Self test

# Runs the committed bundle against itself in dry-run mode, so every change is
# exercised end to end: inputs parse, the account list resolves, outputs are
# set, and the job summary renders. No live key and no mutating call.

on:
push:
branches: [main]
pull_request:
workflow_dispatch:

permissions:
contents: read

jobs:
dry-run:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Post release notes (dry run)
id: fopost
uses: ./
with:
# A placeholder key is enough: a dry run never reaches a mutating
# endpoint, and the read it attempts degrades to the ids as given.
api-key: ${{ secrets.FOPOST_API_KEY || 'placeholder-key-for-dry-run' }}
workspace-id: 00000000-0000-4000-8000-000000000000
accounts: |
00000000-0000-4000-8000-000000000001
00000000-0000-4000-8000-000000000002
text: |
${{ github.repository }} built ${{ github.sha }}.
This is the FoPost action exercising itself.
labels: ci, self-test
publish: true
dry-run: true

- name: Assert the dry run set its outputs
run: |
test "${{ steps.fopost.outputs.status }}" = "dry-run"
test -z "${{ steps.fopost.outputs.post-id }}"
test "${{ steps.fopost.outputs.delivery-count }}" = "0"

- name: Post from a file (dry run)
id: from-file
uses: ./
with:
api-key: ${{ secrets.FOPOST_API_KEY || 'placeholder-key-for-dry-run' }}
workspace-id: 00000000-0000-4000-8000-000000000000
accounts: 00000000-0000-4000-8000-000000000001
text-file: README.md
schedule-at: '2099-01-01T09:00:00Z'
dry-run: true

- name: Assert the file was read
run: test "${{ steps.from-file.outputs.status }}" = "dry-run"

- name: A bad input fails the step
id: bad
continue-on-error: true
uses: ./
with:
api-key: placeholder-key-for-dry-run
accounts: 00000000-0000-4000-8000-000000000001
status: scheduled
text: missing a schedule-at
dry-run: true

- name: Assert it failed
run: test "${{ steps.bad.outcome }}" = "failure"

- name: fail-on-error false keeps the job green
id: soft
uses: ./
with:
api-key: placeholder-key-for-dry-run
accounts: 00000000-0000-4000-8000-000000000001
text: missing a schedule-at
status: scheduled
fail-on-error: false
dry-run: true

- name: Assert it warned instead
run: test "${{ steps.soft.outputs.status }}" = "error"
4 changes: 4 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
dist/
node_modules/
coverage/
package-lock.json
7 changes: 7 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"semi": true,
"singleQuote": true,
"trailingComma": "all",
"printWidth": 100,
"tabWidth": 2
}
Loading
Loading