Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
97 changes: 97 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
name: CI

# Lint + typecheck + test gate runs on every PR and push to main.
#
# The SDK filter/shape conformance check needs the canonical manifest from the
# private makegov/tango repo, which requires a TANGO_API_REPO_ACCESS_TOKEN secret
# the public CI does not have. The conformance job SKIPS cleanly when the token
# is absent (rather than failing on an empty token) and becomes a hard gate the
# moment the secret is configured. The lint + test gate below is self-contained
# and blocks the PR on failure.
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
workflow_dispatch:

jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest]
node-version: ["18", "20", "22"]

steps:
- uses: actions/checkout@v4

- name: Set up Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}

- name: Install dependencies
# No lockfile is committed (package-lock.json is gitignored), and the
# "prepare" script runs a build that needs tsc — so ignore scripts here
# and build explicitly below.
run: npm install --ignore-scripts --no-audit --no-fund

- name: Lint
run: npm run lint

- name: Typecheck
run: npm run typecheck

- name: Build
run: npm run build

- name: Test
# `vitest run` forces a single non-watch pass in CI.
run: npx vitest run

conformance:

Check warning

Code scanning / CodeQL

Workflow does not contain permissions Medium

Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {contents: read}
Comment on lines +20 to +54
# Requires the canonical filter_shape manifest from the private makegov/tango
# repo. When TANGO_API_REPO_ACCESS_TOKEN is not configured, every real step
# is skipped and the job passes (rather than failing on an empty token).
# Configure the secret to turn this into a hard gate automatically.
runs-on: ubuntu-latest

steps:
- name: Determine token availability
id: gate
env:
TANGO_API_REPO_ACCESS_TOKEN: ${{ secrets.TANGO_API_REPO_ACCESS_TOKEN }}
run: |
if [ -n "$TANGO_API_REPO_ACCESS_TOKEN" ]; then
echo "ready=true" >> "$GITHUB_OUTPUT"
else
echo "ready=false" >> "$GITHUB_OUTPUT"
echo "::notice::Skipping SDK conformance check — TANGO_API_REPO_ACCESS_TOKEN not configured."
fi

- uses: actions/checkout@v4
if: steps.gate.outputs.ready == 'true'

- name: Checkout tango API repo (manifest source)
if: steps.gate.outputs.ready == 'true'
uses: actions/checkout@v4
with:
repository: makegov/tango
path: tango-api
token: ${{ secrets.TANGO_API_REPO_ACCESS_TOKEN }}

- name: Set up Node.js
if: steps.gate.outputs.ready == 'true'
uses: actions/setup-node@v4
with:
node-version: "20"

- name: Install dependencies
if: steps.gate.outputs.ready == 'true'
run: npm install --ignore-scripts --no-audit --no-fund

- name: Check SDK filter/shape conformance
if: steps.gate.outputs.ready == 'true'
run: npx tsx scripts/check-filter-shape-conformance.ts --manifest tango-api/contracts/filter_shape_contract.json

Check warning

Code scanning / CodeQL

Workflow does not contain permissions Medium

Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {contents: read}
Comment thread
github-advanced-security[bot] marked this conversation as resolved.
Fixed
Comment on lines +59 to +97
51 changes: 51 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,57 @@ This project follows [Semantic Versioning](https://semver.org/).

## [Unreleased]

## [1.1.0] - 2026-05-29

### Changed (breaking)
- Removed `getIdvSummary` and `listIdvSummaryAwards`. These called
`/api/idvs/{id}/summary/` and `/api/idvs/{id}/summary/awards/`, which have
never existed in the Tango API (no OpenAPI backing), so no consumer could
have been using them successfully. Use `getIdv` + `listIdvAwards` instead.

### Fixed
- `Contract` interface: removed dead fields (`id`, `award_id`,
`recipient_name`, `award_amount`, `awarding_agency`, `funding_agency`) and
added the real API fields from `ContractListSerializer` (`key`, `piid`,
`obligated`, `total_contract_value`, `base_and_exercised_options_value`,
`awarding_office`, `funding_office`, `naics_code`, `psc_code`, `set_aside`,
`solicitation_identifier`, `parent_award`, `legislative_mandates`,
`subawards_summary`, `place_of_performance`). All fields optional (the
endpoint is shape-on-demand). The deprecated fields remain declared (marked
`@deprecated`) for one minor cycle and will be removed in `2.0.0`. New
exported types: `OrganizationOfficePayload`, `PlaceOfPerformance`,
`SubawardsSummary`, `LegislativeMandates`, `ParentAwardReference`,
`EntityBasic`.
- `listContracts`: no longer sends `page=1` to the cursor-only `/api/contracts/`
endpoint. When no cursor is supplied, neither `page` nor `cursor` is sent and
the API returns the first page by default. The stale code comment claiming
page-based pagination support has been corrected.
- Shape validation: registered the `ContractOrIDVCompetition` nested schema
(alias of `Competition`) so nested selections like
`competition(extent_competed,number_of_offers_received)` on contract / IDV
shapes validate instead of raising a shape-validation error.

### Added
- Budget accounts surface (tango v4.6.8): `listBudgetAccounts`,
`getBudgetAccount`, `getBudgetAccountQuarters`, `getBudgetAccountRecipients`.
New exported `BudgetAccount` interface and `ListBudgetAccountsOptions`.
- Singleton detail GETs: `getContract`, `getContractSubawards`,
`getContractTransactions`, `getForecast`, `getGrant`, `getNotice`,
`getOpportunity`, `getSubaward`.
- `getEntityBudgetFlows(uei)` for `/api/entities/{uei}/budget-flows/`.
- `listVehicleOrders(uuid, options)` for `/api/vehicles/{uuid}/orders/`
(parity with Python).
- `grantId` filter on `listGrants` (camelCase alias mapped to the `grant_id`
API param; `grant_id` also accepted directly).

### CI
- Added `ci.yml` PR + push-to-main gate (lint, typecheck, build, test on Node
18/20/22). The filter/shape conformance check is a separate job that skips
cleanly until a `TANGO_API_REPO_ACCESS_TOKEN` secret for the private manifest
repo is configured, at which point it becomes a hard gate.
- Gave the webhooks real-HTTP-server round-trip tests an explicit 20s timeout
(the default 5s was tight on the slower Node 18 CI runtime).

## [1.0.0] - 2026-05-13

First stable release. `tango-node` is now at **full feature parity** with both the Tango API and `tango-python` for the surface that remains after the subject-based webhook removal (see "Removed" below). Every read method and every endpoint/alert/signing helper available on `tango_python.TangoClient` has an idiomatic camelCase counterpart on `TangoClient`, the SDK's docs are auto-published to `docs.makegov.com/sdks/node/` via the composer pipeline (makegov/docs#15 / makegov/docs#16), and from `1.x` on we'll only ship breaking changes on a major bump.
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@makegov/tango-node",
"version": "1.0.0",
"version": "1.1.0",
"description": "Official Node.js SDK for the Tango API – dynamic response shaping, typed models, and full endpoint coverage.",
"type": "module",
"main": "./dist/index.js",
Expand Down
1 change: 1 addition & 0 deletions scripts/check-filter-shape-conformance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ export const RESOURCE_TO_METHOD: Record<string, string | null> = {
naics: "listNaics",
gsa_elibrary_contracts: "listGsaElibraryContracts",
itdashboard: "listItDashboard",
budget_accounts: "listBudgetAccounts",
offices: "listOffices",
};

Expand Down
Loading
Loading