{"id":48355055,"url":"https://github.com/get-skipper/skipper","last_synced_at":"2026-04-21T01:01:21.963Z","repository":{"id":344567939,"uuid":"1182239555","full_name":"get-skipper/skipper","owner":"get-skipper","description":"Enable and disable tests directly from a Google Spreadsheet — no code changes required.","archived":false,"fork":false,"pushed_at":"2026-04-09T06:23:10.000Z","size":194,"stargazers_count":2,"open_issues_count":2,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-09T06:23:41.397Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://get-skipper.github.io","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/get-skipper.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-15T08:33:30.000Z","updated_at":"2026-04-09T06:23:13.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/get-skipper/skipper","commit_stats":null,"previous_names":["get-skipper/skipper"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/get-skipper/skipper","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/get-skipper%2Fskipper","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/get-skipper%2Fskipper/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/get-skipper%2Fskipper/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/get-skipper%2Fskipper/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/get-skipper","download_url":"https://codeload.github.com/get-skipper/skipper/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/get-skipper%2Fskipper/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32072323,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-20T21:26:33.338Z","status":"ssl_error","status_checked_at":"2026-04-20T21:26:22.081Z","response_time":94,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":[],"created_at":"2026-04-05T11:00:25.772Z","updated_at":"2026-04-21T01:01:21.954Z","avatar_url":"https://github.com/get-skipper.png","language":"TypeScript","funding_links":[],"categories":["Uncategorized","Software"],"sub_categories":["Uncategorized","Test Management"],"readme":"# Skipper\n\nEnable and disable tests directly from a Google Spreadsheet — no code changes required.\n\nSkipper integrates with your existing test suite via a minimal config. Each test is identified by its file path + title. Set a `disabledUntil` date in the spreadsheet to skip a test until that date; leave it empty (or set a past date) to run it normally.\n\n## Packages\n\n| Package | Framework |\n|---|---|\n| [`@get-skipper/playwright`](packages/playwright/README.md) | Playwright |\n| [`@get-skipper/jest`](packages/jest/README.md) | Jest |\n| [`@get-skipper/vitest`](packages/vitest/README.md) | Vitest |\n| [`@get-skipper/cypress`](packages/cypress/README.md) | Cypress |\n| [`@get-skipper/nightwatch`](packages/nightwatch/README.md) | Nightwatch.js |\n\n## How It Works\n\n- **`read-only` mode** (default): Skipper reads the spreadsheet at the start of the test run and skips any test whose `disabledUntil` date is in the future.\n- **`sync` mode** (`SKIPPER_MODE=sync`): Same as read-only, plus after the run Skipper reconciles the spreadsheet — adding rows for new tests and, when `SKIPPER_SYNC_ALLOW_DELETE=true`, removing rows for tests no longer in the suite.\n\n## Spreadsheet Schema\n\nCreate a Google Spreadsheet with the following columns in the first row (header):\n\n| `testId` | `disabledUntil` | `notes` |\n|---|---|---|\n| `tests/auth/login.spec.ts \u003e login \u003e should log in` | | |\n| `tests/checkout/payment.spec.ts \u003e payment \u003e stripe` | `2026-04-01` | Flaky until fix |\n| `tests/payments/refund.spec.ts \u003e refund` | `2099-12-31` | Disabled indefinitely |\n\n- **`testId`** — `{relative file path} \u003e {describe blocks} \u003e {test name}`, automatically generated by the plugin.\n- **`disabledUntil`** — ISO 8601 date (e.g. `2026-04-01`). Empty or past date = test runs. Future date = test is skipped.\n- **`notes`** — optional free-text field, ignored by the plugin.\n\n## Configuration Reference\n\nAll Skipper plugins accept the same `SkipperConfig` object:\n\n| Option | Type | Required | Default | Description |\n|---|---|---|---|---|\n| `spreadsheetId` | `string` | ✅ | — | The Google Spreadsheet ID (from the URL) |\n| `credentials` | object | ✅ | — | Service account credentials — see below |\n| `sheetName` | `string` | | first tab | Name of the sheet tab to read/write |\n| `referenceSheets` | `string[]` | | `[]` | Additional sheet tabs to read (read-only); merged with the primary sheet |\n| `testIdColumn` | `string` | | `\"testId\"` | Column header for the test identifier |\n| `disabledUntilColumn` | `string` | | `\"disabledUntil\"` | Column header for the disable date |\n\n### Credentials\n\n```ts\n// Base64-encoded JSON (recommended for CI)\ncredentials: { credentialsBase64: process.env.GOOGLE_CREDS_B64! }\n\n// Path to a local JSON file (recommended for local dev)\ncredentials: { credentialsFile: './service-account.json' }\n\n// Raw service account object\ncredentials: { client_email: '...', private_key: '...' }\n```\n\n### `sheetName`\n\nBy default Skipper uses the first tab of the spreadsheet. Use `sheetName` to target a specific tab:\n\n```ts\n{\n  spreadsheetId: '...',\n  credentials: { credentialsBase64: '...' },\n  sheetName: 'E2E Tests', // reads and writes to this tab only\n}\n```\n\n### `referenceSheets`\n\nAdditional sheet tabs to read (never written to). Useful for sharing a common list of disabled tests across multiple suites. When the same `testId` appears in more than one sheet, the most restrictive (latest future) `disabledUntil` wins:\n\n```ts\n{\n  spreadsheetId: '...',\n  credentials: { credentialsBase64: '...' },\n  sheetName: 'E2E Tests',        // primary sheet (read + write in sync mode)\n  referenceSheets: ['Shared'],   // additional sheets (read-only)\n}\n```\n\n## Google Sheets Setup\n\n### 1. Create a Google Cloud Project and enable the API\n\n1. Go to [Google Cloud Console](https://console.cloud.google.com/)\n2. Create a new project (or select an existing one)\n3. Navigate to **APIs \u0026 Services → Library**\n4. Search for **Google Sheets API** and enable it\n\n### 2. Create a Service Account\n\n1. Navigate to **APIs \u0026 Services → Credentials**\n2. Click **Create Credentials → Service Account**\n3. Give it a name (e.g. `skipper-bot`) and click **Done**\n4. Click on the service account → **Keys** tab → **Add Key → Create new key → JSON**\n5. Download the JSON file — keep it secret\n\n### 3. Share the Spreadsheet\n\nOpen your Google Spreadsheet and share it with the service account email (found in the JSON file as `client_email`):\n\n- **Viewer** role for `read-only` mode\n- **Editor** role for `sync` mode\n\n### 4. Prepare Credentials for CI\n\nConvert the JSON file to a base64 string for use as a CI secret:\n\n```bash\nbase64 -i service-account.json | tr -d '\\n'\n```\n\nSave the output as a secret named `GOOGLE_CREDS_B64` in your CI environment (e.g. GitHub Actions secrets).\n\nFor local development, keep the JSON file and reference it via `credentialsFile`:\n\n```ts\ncredentials: { credentialsFile: './service-account.json' }\n```\n\n### 5. Populate the Spreadsheet for the First Time\n\nRun your test suite in sync mode once to auto-populate all test rows:\n\n```bash\nSKIPPER_MODE=sync SKIPPER_SPREADSHEET_ID=\u003cyour-spreadsheet-id\u003e pnpm test\n```\n\nAll tests will be added to the spreadsheet with an empty `disabledUntil` (enabled by default). You can then set dates in the spreadsheet to disable specific tests.\n\n## Environment Variables\n\n| Variable | Default | Description |\n|---|---|---|\n| `SKIPPER_MODE` | `read-only` | Set to `sync` to enable spreadsheet reconciliation after the test run |\n| `SKIPPER_FAIL_OPEN` | `true` | When `true`, runs all tests if the API is unreachable and no valid cache exists. Set to `false` to crash instead |\n| `SKIPPER_CACHE_TTL` | `300` | Seconds a local `.skipper-cache.json` is considered valid. Skipper writes this file after each successful fetch and reads it as a fallback on API failure |\n| `SKIPPER_SYNC_ALLOW_DELETE` | `false` | When `false`, orphaned rows (tests removed from the suite) are only warned about. Set to `true` to delete them |\n| `SKIPPER_DEBUG` | — | Set to any truthy value to enable verbose logging |\n\n## Modes\n\n### read-only (default)\n\nNo env var needed. Tests with a future `disabledUntil` are skipped.\n\n```bash\nSKIPPER_SPREADSHEET_ID=\u003cid\u003e pnpm test\n```\n\n### sync (CI on merge to main)\n\n```bash\nSKIPPER_MODE=sync SKIPPER_SPREADSHEET_ID=\u003cid\u003e pnpm test\n```\n\nAfter the run:\n- New tests → added to the spreadsheet with empty `disabledUntil`\n- Removed tests → warned (set `SKIPPER_SYNC_ALLOW_DELETE=true` to also delete them)\n\n## CI Example (GitHub Actions)\n\n```yaml\n# .github/workflows/test.yml\nname: Test\n\non:\n  pull_request:\n  push:\n    branches: [main]\n\njobs:\n  test:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - uses: pnpm/action-setup@v3\n      - uses: actions/setup-node@v4\n        with:\n          node-version: 20\n          cache: pnpm\n\n      - run: pnpm install\n\n      - name: Test (read-only on PR)\n        if: github.event_name == 'pull_request'\n        env:\n          SKIPPER_SPREADSHEET_ID: ${{ secrets.SKIPPER_SPREADSHEET_ID }}\n          GOOGLE_CREDS_B64: ${{ secrets.GOOGLE_CREDS_B64 }}\n        run: pnpm test\n\n      - name: Test + sync (on merge to main)\n        if: github.ref == 'refs/heads/main'\n        env:\n          SKIPPER_MODE: sync\n          SKIPPER_SPREADSHEET_ID: ${{ secrets.SKIPPER_SPREADSHEET_ID }}\n          GOOGLE_CREDS_B64: ${{ secrets.GOOGLE_CREDS_B64 }}\n        run: pnpm test\n```\n\n## License\n\nMIT — see [LICENSE](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fget-skipper%2Fskipper","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fget-skipper%2Fskipper","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fget-skipper%2Fskipper/lists"}