{"id":51914258,"url":"https://github.com/loke-dev/deployproof","last_synced_at":"2026-07-27T09:01:49.572Z","repository":{"id":373217694,"uuid":"1312319686","full_name":"loke-dev/deployproof","owner":"loke-dev","description":"Prove a preview behaves like production before you deploy.","archived":false,"fork":false,"pushed_at":"2026-07-26T09:58:16.000Z","size":79,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-07-26T10:05:35.540Z","etag":null,"topics":["ci","deployment-testing","developer-tools","github-actions","preview-deployments"],"latest_commit_sha":null,"homepage":"https://deployproof.loke.dev","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/loke-dev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-07-25T21:34:10.000Z","updated_at":"2026-07-26T09:55:01.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/loke-dev/deployproof","commit_stats":null,"previous_names":["loke-dev/deployproof"],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/loke-dev/deployproof","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/loke-dev%2Fdeployproof","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/loke-dev%2Fdeployproof/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/loke-dev%2Fdeployproof/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/loke-dev%2Fdeployproof/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/loke-dev","download_url":"https://codeload.github.com/loke-dev/deployproof/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/loke-dev%2Fdeployproof/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35945273,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-07-20T02:08:10.276Z","status":"online","status_checked_at":"2026-07-27T02:00:06.776Z","response_time":101,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ci","deployment-testing","developer-tools","github-actions","preview-deployments"],"created_at":"2026-07-27T09:01:48.860Z","updated_at":"2026-07-27T09:01:49.565Z","avatar_url":"https://github.com/loke-dev.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# DeployProof\n\n[![CI](https://github.com/loke-dev/deployproof/actions/workflows/ci.yml/badge.svg)](https://github.com/loke-dev/deployproof/actions/workflows/ci.yml)\n[![CodeQL](https://github.com/loke-dev/deployproof/actions/workflows/codeql.yml/badge.svg)](https://github.com/loke-dev/deployproof/actions/workflows/codeql.yml)\n[![npm](https://img.shields.io/npm/v/deployproof)](https://www.npmjs.com/package/deployproof)\n[![MIT license](https://img.shields.io/badge/license-MIT-171816)](LICENSE)\n\nProve that a preview deployment behaves like production before you merge it.\nDeployProof sends the same bounded request to both environments, then compares\nthe behavior that commonly drifts between them: status codes, redirect chains,\nfinal paths, cache and security headers, cookie attributes, canonical URLs,\nrobots directives, and titles.\n\nIt is read-only, does not need credentials, and never prints response bodies,\ncookie values, or custom request-header values.\n\nCustom request headers are sent only to the selected base origin and its\nsame-origin redirects. DeployProof drops them if a redirect leaves that origin.\nQuery-string values are represented by deterministic fingerprints in reports,\nso differences remain detectable without printing the original values.\n\n## Quick start\n\n```bash\nnpx deployproof \\\n  --preview https://my-pr.example.workers.dev \\\n  --production https://example.com \\\n  / /docs /api/health\n```\n\nExit code `0` means every route passed. Exit code `1` means a behavioral\ndifference was found. Exit code `2` means DeployProof could not run.\n\n## Configuration\n\nCreate `deployproof.config.json`:\n\n```json\n{\n  \"production\": \"https://example.com\",\n  \"routes\": [\n    \"/\",\n    \"/docs\",\n    {\n      \"path\": \"/api/health\",\n      \"method\": \"GET\",\n      \"expect\": {\n        \"status\": 200,\n        \"contentType\": \"application/json\"\n      }\n    }\n  ],\n  \"timeoutMs\": 10000,\n  \"maxRedirects\": 5,\n  \"maxBodyBytes\": 512000\n}\n```\n\nPass the preview URL from CI:\n\n```bash\nDEPLOYPROOF_PREVIEW=\"$PREVIEW_URL\" npx deployproof --strict\n```\n\nThe CLI also reads `DEPLOYPROOF_PRODUCTION`, so URLs never have to live in the\nconfiguration file.\n\nPath prefixes in preview and production URLs are preserved. For example, a\nroute of `/api/health` under `https://preview.example.com/deployments/123`\nrequests `/deployments/123/api/health`.\n\nContent type expectations match the response media type case-insensitively.\nParameters such as `charset=utf-8` do not affect the match.\nCustom request header names and values are validated when configuration loads,\nbefore any request is made.\nMalformed configuration errors identify the file without echoing its contents,\nso header values cannot leak through JSON parser diagnostics.\nThe timeout applies independently to every request in a redirect chain,\nincluding reading the final HTML response body.\nOrder-only differences in `Cache-Control`, CORS token lists, and `Vary` are\nnormalized so equivalent header behavior does not create noisy reports.\nCanonical links and robots directives are recognized with quoted or unquoted\nHTML attribute values.\n\n## GitHub Action\n\n```yaml\n- uses: loke-dev/deployproof@v0.1.5\n  with:\n    preview: ${{ steps.deploy.outputs.deployment-url }}\n    production: https://example.com\n    strict: true\n```\n\nThe Action emits native annotations for each route difference. It compares\ncookie names and security attributes such as `Secure`, `HttpOnly`, and the\n`SameSite` mode, but never exposes cookie values. Absolute cookie expiration\ntimestamps are normalized so equivalent rolling sessions do not create drift;\nthe presence of `Expires` is still compared. It runs the reviewed CLI bundle\nfrom the selected repository tag without downloading executable code from npm.\n\n## Output formats\n\n```bash\ndeployproof --format human   # readable terminal report\ndeployproof --format json    # automation and dashboards\ndeployproof --format github  # workflow annotations\ndeployproof --format sarif   # code scanning upload\n```\n\nUse `--strict` to make warnings fail the check. Errors always fail. Notices\nremain informational.\n\n## What DeployProof catches\n\n| ID | Difference | Default severity |\n| --- | --- | --- |\n| `DP000` | Request failed or timed out | error |\n| `DP001` | HTTP status | error |\n| `DP002` | Final path and query | error |\n| `DP003` | Redirect chain | warning |\n| `DP004` | Cache, content, and security headers | notice or warning |\n| `DP005` | Cookie names or security attributes | warning |\n| `DP006` | Title, canonical, or robots metadata | notice or warning |\n| `DP007` | Explicit status expectation | error |\n| `DP008` | Explicit response media type expectation | error |\n\nResponse bodies are read only for HTML metadata, capped at 500 KB by default,\nand never included in output.\n\nRoute method values are normalized case-insensitively during configuration\nloading, so `get`, `GET`, and `HEAD` are all supported.\n\n## Development\n\n```bash\npnpm install\npnpm check\npnpm dev -- --preview http://localhost:4173 --production https://example.com\n```\n\nDeployProof is MIT licensed. Product documentation is at\n[deployproof.loke.dev](https://deployproof.loke.dev).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Floke-dev%2Fdeployproof","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Floke-dev%2Fdeployproof","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Floke-dev%2Fdeployproof/lists"}