Run Portman in GitHub Actions
Run Portman contract tests in a GitHub Actions workflow with npx, a CLI options file, secrets as PORTMAN_ variables and Newman.
You can run Portman in GitHub Actions like any other Node.js CLI: check out the repository, set up Node, and run npx @apideck/portman with your spec, config and the --runNewman flag. Portman then converts the spec, injects the tests and runs them against the API URL you pass with --baseUrl.
Repository layout
openapi.yamlportman-config.jsonportman-cli-options.jsonKeep the CLI options in a file so local runs and CI use the same settings (see CLI options file):
{ "local": "./openapi.yaml", "output": "./tmp/converted/collection.postman.json", "portmanConfigFile": "./portman-config.json", "includeTests": true, "runNewman": true}Workflow
.github/workflows/contract-tests.yml:
name: Contract tests on: pull_request: push: branches: [main] jobs: portman: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: 20 - name: Run Portman contract tests env: PORTMAN_BEARER_TOKEN: ${{ secrets.API_TOKEN }} run: npx @apideck/portman --cliOptionsFile ./portman-cli-options.json --baseUrl ${{ vars.API_BASE_URL }} - name: Upload collection if: always() uses: actions/upload-artifact@v4 with: name: postman-collection path: tmp/converted/What it does:
--cliOptionsFileloads the settings from the file. Flags passed on the command line, here--baseUrl, override the values in the file.PORTMAN_BEARER_TOKENis available in the collection as{{bearerToken}}, because Portman exposes everyPORTMAN_environment variable as a camel-cased Postman variable. See Environment variables.- The generated collection is uploaded as a build artifact, so you can import it into Postman when a test fails.
To use the token, reference it in your Portman config, for example on collection level:
{ "version": 1.0, "globals": { "securityOverwrites": { "bearer": { "token": "{{bearerToken}}" } } }}When any assertion fails, Portman exits with code 1, so the step fails and the job goes red. That makes the workflow safe to use as a required status check (merge gate).
Pin the Portman version
npx @apideck/portman downloads the latest version. To get reproducible runs, add Portman as a dev dependency (see Installation) and run npm ci before the Portman step, or pin a version in the command, for example npx @apideck/portman@<version>.
Sync to Postman from CI
To also upload the collection to Postman on main, add the Postman API key as a secret and pass --syncPostman:
- name: Sync collection to Postman if: github.ref == 'refs/heads/main' env: POSTMAN_API_KEY: ${{ secrets.POSTMAN_API_KEY }} run: npx @apideck/portman -l ./openapi.yaml -c ./portman-config.json --syncPostman --postmanUid ${{ vars.POSTMAN_COLLECTION_UID }}See Postman sync.
Running against a service in the workflow
If the API runs inside the job (for example started in a previous step or as a service container), point --baseUrl at it, such as http://localhost:3050.