Pulse
CLI

Deployment

Capture deployments as verified events. Wire pulse deploy into your pipeline and every release records itself at the strongest trust level available.

Updated 5 min readStable

pulse deploy publishes deployment metadata to Pulse: what shipped, where it shipped, and which commit actually reached the environment. It runs in your pipeline, at the point where the deployment is known to have succeeded, and produces a verified PUSH on the project timeline.

Pulse does not deploy anything. It does not run your builds, hold your credentials, or sit in the path of a release. pulse deploy is a report — a statement, made by the system that performed the deployment, that a specific version reached a specific environment. That report becomes an event, and the pipeline that made it is what verifies it.

Deployments are the highest-signal events an engineering team produces. They are the moment intent becomes production, and they are the anchor every other event hangs off: an incident is 'after the 14:02 deploy', a fix 'shipped in v2.4.1'. A timeline without deployments is a timeline with no clock.

A repository webhook can tell Pulse that a tag was created or a branch was merged. It cannot tell Pulse that the release actually reached production, which environment received it, or which commit is genuinely running — merges get reverted, deploys fail halfway, and the tag is often not what shipped. Trusting the repository for deployment facts means recording things that did not happen.

The deploying system is the only thing that knows the truth, and it knows it at exactly one moment: after the deployment succeeded. So the command runs there. That placement is also what earns the trust level — an event reported by a CI pipeline that observed the deployment attests at L3, while the same claim made from a laptop cannot rise above self-attestation, because a laptop can say anything.

  • Environment — where it shipped: production, staging, or whatever you call yours. Free-form, but be consistent; it is what timelines filter on.
  • Version — what shipped. A semantic version, a tag, or a commit SHA. Whatever you can point at later.
  • Commit — the SHA actually deployed. Defaults to the checked-out HEAD, which in CI is the commit that was built.
  • Trust level — L3 when reported by a pipeline Pulse can confirm; L1 when reported by an unverifiable machine.
  1. Your pipeline deploys, using whatever tooling you already use.
  2. On success, it runs pulse deploy with the environment and the version.
  3. The CLI reports the deployment, authenticated by PULSE_TOKEN.
  4. The event is appended as a PUSH, attributed to the engineer whose commit shipped — not to the pipeline.
  5. The verification engine confirms it against the CI source and mints a proof at L3.
  6. It lands on the project timeline, in the feed, and in Delivery and Reliability for its author.

The pipeline is the reporter, not the author. Pulse attributes the deployment to the engineer behind the commit that shipped, which is why a CI-driven deployment still moves a person's Build Cred, and why nobody has to log anything by hand to get credit for the release they actually shipped.

  1. Add PULSE_TOKEN to your CI secret store.
  2. Add a step at the end of the deploy job — after the deployment has succeeded, never before.
  3. Pass the environment and the version you actually shipped.
  4. Verify with pulse status that deployments are landing at L3.
  5. Stop thinking about it. Every release from now on records itself.
.github/workflows/deploy.yml
bash
name: Deploy

on:
  push:
    tags: ["v*"]

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

      - name: Deploy to production
        run: ./scripts/deploy.sh production

      - name: Record the deployment
        if: success()
        env:
          PULSE_TOKEN: ${{ secrets.PULSE_TOKEN }}
        run: |
          npm install -g @pulse/cli
          pulse deploy \
            --environment production \
            --version ${{ github.ref_name }}
FlagDescription
--environment <name>Where it shipped. Defaults to defaults.environment in pulse.json.
--version <version>What shipped — a semver, tag or SHA. Required.
--commit <sha>The commit deployed. Defaults to the checked-out HEAD.
--project <slug>Overrides pulse.json. Useful when deploying several projects from one pipeline.
--status <status>success or failed. Defaults to success. A failed deployment is a real event and worth recording.
--jsonPrint the resulting event as JSON.
pulse deploy
The resulting event
json
{
  "id": "evt_gateway_v240_push",
  "kind": "PUSH",
  "title": "Deployed v2.4.0 to production",
  "actor": "@aria",
  "project": "atlas-gateway",
  "environment": "production",
  "version": "v2.4.0",
  "commit": "8f21c9e",
  "occurred_at": "2026-07-03T09:30:00Z",
  "verification": {
    "status": "verified",
    "level": "L3",
    "method": "ci_pipeline",
    "methodLabel": "GitHub Actions · northwind/atlas-gateway",
    "proofId": "proof_5c8ea114"
  }
}
  • Run it after the deployment, gated on success. Reporting a deployment that then failed puts a false event on a permanent timeline.
  • Record failed deployments too, with --status failed. A rollback rate is one of the most honest reliability signals a team has, and hiding it only fools yourself.
  • Use the version you can look up later — the tag you actually shipped, not a build number nobody can resolve.
  • Keep environment names stable across projects. staging in one and stage in another quietly breaks every filter you will later want.
  • Deploy from CI, not from laptops. It is better engineering practice anyway, and it is the difference between L3 and L1.
  • Running pulse deploy before the deployment, or in a job that continues on error. The event says it shipped, permanently, whether it did or not.
  • Reporting every merge to main as a production deployment when a merge is not a deploy. The timeline stops meaning anything.
  • Putting PULSE_TOKEN in pulse.json. It is a credential; pulse.json is committed.
  • Expecting an L3 proof from a script on your machine. The trust level comes from the source, and a personal shell is not one.
  • Deploying several projects from one pipeline without --project, so every deployment lands on whichever project pulse.json happens to name.
  • Deployments and releases are both PUSH events. The kind is the verb; the environment and version are what distinguish them.
  • If the CI source cannot be confirmed, the event is recorded as pending rather than rejected, and is attested when the source responds.
  • Deployment events feed Delivery directly and Reliability over time — Reliability is a function of whether what you shipped kept working.
  • The command is idempotent per version and environment. A retried pipeline does not produce a duplicate event.