Capture a job posting from the page you are looking at, straight into your Postulo instance. Firefox extension. https://source.tiagoagueda.com/postulo/postulo
  • JavaScript 100%
Find a file
Tiago Águeda e531dfbc53
All checks were successful
CI / build (push) Successful in 14s
Give the tag-only release job a workflow of its own
It sat in ci.yml behind `if: startsWith(github.ref, 'refs/tags/v')` and
`needs: build`, and on every push to main the runner picked it up anyway and
ended it in four lines -- "'runs-on' key not defined in CI/build", "Early
termination" -- so every push since the job arrived has been red for a job
that had nothing to do. Forgejo hands a job to a runner before the condition
that would skip it is worth anything, which is the shape of postulo/postulo#81.
A workflow that only exists on a tag push cannot be handed anything else, so
the job is release.yml now, unchanged otherwise, and ci.yml builds on branches
and pull requests.

Refs postulo/postulo#251

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-18 11:42:01 +02:00
.forgejo/workflows Give the tag-only release job a workflow of its own 2026-09-18 11:42:01 +02:00
scripts Build from a commit that cannot move, on a Firefox that understands the manifest 2026-09-16 10:38:38 +02:00
.gitignore The Postulo extension for Firefox, assembled from the shared source 2026-09-05 23:30:51 +02:00
LICENSE The Postulo extension for Firefox, assembled from the shared source 2026-09-05 23:30:51 +02:00
package-lock.json Take the version of the Postulo this is released beside 2026-09-13 06:09:03 +02:00
package.json Build from a commit that cannot move, on a Firefox that understands the manifest 2026-09-16 10:38:38 +02:00
README.md Build from a commit that cannot move, on a Firefox that understands the manifest 2026-09-16 10:38:38 +02:00
source.json Build from a commit that cannot move, on a Firefox that understands the manifest 2026-09-16 10:38:38 +02:00

postulo-firefox

The Postulo browser extension for Firefox, Firefox for Android, and the forks — LibreWolf, Zen, Waterfox, Floorp. One button sends the job posting you are looking at to your own Postulo, for review.

The code is the same as the Chromium extension and lives in postulo-chromium, which builds for both browsers from one source. This repository holds what Firefox and addons.mozilla.org need and nothing else: the pin to the shared source (source.json), the build that assembles the Firefox package from it, the signing and listing notes, and CI. Everything in postulo-chromium's README about privacy and setup applies here.

What Firefox does differently, and how the build handles it

  • Background. Firefox runs an event page (background.scripts), not a service worker. The shared manifest lists both; the Firefox build keeps scripts.
  • Identity. browser_specific_settings.gecko.id (postulo@tiagoagueda.com) is required for a Manifest V3 extension to be signed and to keep its storage across updates. It is in the shared manifest and stays in the Firefox build.
  • Host permissions are opt-in. Firefox grants nothing at install. The extension asks for your instance's origin when you Save the settings, from that click, and says so if you refuse — then it can do nothing, and tells you why.
  • Signing is mandatory. Release Firefox refuses unsigned extensions. npm run sign submits the build to addons.mozilla.org (needs WEB_EXT_API_KEY and WEB_EXT_API_SECRET from your AMO account); Developer Edition and Nightly load dist/ unsigned from about:debugging for development.
  • Android. Firefox for Android installs from addons.mozilla.org, so a capture from a phone comes with the listing.
  • Minimum version. The shared manifest declares data_collection_permissions (required: ["none"] — the extension collects nothing), which Firefox understands from 140 and Firefox for Android from 142. strict_min_version says so: 140 on desktop, 142 on Android. An older Firefox would install the extension and ignore the declaration, which is the one thing a declaration about data must not do. Both values live in postulo-chromium's src/manifest.json, the one manifest, and reach here through the pin.

Build

npm ci
npm run check:pin  # source.json pins something that cannot move
npm run build      # clones postulo-chromium at the pinned ref and assembles dist/
npm run lint       # web-ext lint on dist/
npm run package    # a zip under web-ext-artifacts/

The pin

source.json names the commit of postulo-chromium this package is built from, and it is never a branch. addons.mozilla.org rebuilds a source submission and compares it to the package: with "ref": "main" the reviewer's build is a later extension than the submitted one, and the Firefox and Chromium extensions quietly stop being the same extension. npm run check:pin, which CI runs before the build, refuses a branch or HEAD, and — once postulo-chromium cuts its first tag — refuses any pin that is not the latest of them. postulo-chromium has no tag yet, so the pin is the full commit SHA of its main; the check says how far that is from the tip, and the first tag replaces it.

To ship a new version: tag postulo-chromium, put the tag in source.json, tag this repository vX.Y.Z — CI then builds, lints and leaves the zip as an artifact — and run npm run sign (or upload that zip on addons.mozilla.org). Signing is not done in CI: it needs the AMO credentials.

Licence

AGPL-3.0-or-later, like Postulo.