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
13 changes: 6 additions & 7 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,32 +3,31 @@ on:
push:
branches:
- main
tags:
- 'v*'
pull_request:
paths-ignore:
- '*.md'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}
cancel-in-progress: true
jobs:
nodejs:
name: Node.js
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
node-version: [^20.8, ^22, ^24]
node-version: [^22.20, ^24.12, ^25]
os: [ubuntu-latest, windows-latest]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
with:
node-version: ${{ matrix.node-version }}
- run: npm install --no-audit
- run: npm test
- uses: codecov/codecov-action@v4
- uses: codecov/codecov-action@v5
with:
disable_search: true
files: coverage/lcov.info
name: ${{ matrix.os }}/${{ matrix.node-version }}
token: ${{ secrets.CODECOV_TOKEN }}
195 changes: 152 additions & 43 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -1,88 +1,197 @@
name: Release
on:
push:
tags:
- 'v*'
workflow_dispatch:
inputs:
tag:
description: 'Release tag (e.g., v1.2.3)'
ref:
description: 'Commit ref or existing version tag (e.g., abc1234 or v1.2.3)'
required: true
type: string
new_version:
description: 'New version for npm version (e.g., patch, minor, major, 1.2.3). Must be empty when providing an existing tag.'
required: false
type: string
skip_ci_check:
description: 'Skip CI status check'
required: false
type: boolean
default: false

permissions:
contents: write
id-token: write

jobs:
release:
name: Release
runs-on: ubuntu-latest
environment: npm
preflight:
name: Validate
runs-on: ubuntu-slim
permissions:
actions: read
contents: read
outputs:
ref_is_tag: ${{steps.validation.outputs.ref_is_tag}}
steps:
- name: Validate inputs
id: validation
env:
REF: ${{inputs.ref}}
NEW_VERSION: ${{inputs.new_version}}
run: |
if [[ "$REF" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.-]+)?(\+[a-zA-Z0-9.-]+)?$ ]]; then
echo "ref_is_tag=true" >> "$GITHUB_OUTPUT"
if [[ -n "$NEW_VERSION" ]]; then
echo "::error::new_version must be empty when an existing tag is provided"
exit 1
fi
else
echo "ref_is_tag=false" >> "$GITHUB_OUTPUT"
if [[ -z "$NEW_VERSION" ]]; then
echo "::error::new_version is required when a commit ref is provided"
exit 1
fi
fi

- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v6
with:
ref: ${{ github.event_name == 'workflow_dispatch' && inputs.tag || github.ref }}
ref: ${{inputs.ref}}
fetch-depth: 0

- name: Verify ref is HEAD of main
if: steps.validation.outputs.ref_is_tag == 'false'
env:
REF: ${{inputs.ref}}
run: |
MAIN_SHA=$(git rev-parse origin/main)
CURRENT_SHA=$(git rev-parse HEAD)
if [[ "$CURRENT_SHA" != "$MAIN_SHA" ]]; then
echo "::error::ref ${REF} (${CURRENT_SHA}) is not the HEAD of main (${MAIN_SHA})"
exit 1
fi

- name: Verify tag matches package.json version
if: steps.validation.outputs.ref_is_tag == 'true'
env:
REF: ${{inputs.ref}}
run: |
jq --raw-output --exit-status --arg tag "$RELEASE_TAG" '
jq --raw-output --exit-status --arg tag "$REF" '
if (.version == ($tag | ltrimstr("v"))) then
"Package version (\(.version)) matches tag version (\($tag | ltrimstr("v")))"
"Package version (\(.version)) matches tag version (\($tag | ltrimstr(\"v\")))"
else
"Package version (\(.version)) does not match tag version (\($tag | ltrimstr("v")))" | halt_error(1)
"Package version (\(.version)) does not match tag version (\($tag | ltrimstr(\"v\")))" | halt_error(1)
end' package.json

- name: Check CI status
if: '!inputs.skip_ci_check'
run: |
gh run list --commit "$(git rev-parse HEAD)" --workflow ci.yml --status success --json databaseId \
| jq --raw-output --exit-status '
if (length > 0) then
"CI checks have passed"
else
"CI has not completed successfully for this commit" | halt_error(1)
end'
env:
RELEASE_TAG: ${{ github.event_name == 'workflow_dispatch' && inputs.tag || github.ref_name }}
GH_TOKEN: ${{secrets.GITHUB_TOKEN}}

- name: Verify commit is in main branch
release:
name: Release
runs-on: ubuntu-latest
needs: preflight
environment: npm
permissions:
contents: read
id-token: write
steps:
- name: Checkout
uses: actions/checkout@v6
with:
ref: ${{inputs.ref}}
fetch-depth: 0

- name: Verify ref is still HEAD of main
if: needs.preflight.outputs.ref_is_tag == 'false'
env:
REF: ${{inputs.ref}}
run: |
# Check if the tagged commit is included in the main branch
if git merge-base --is-ancestor ${{ github.sha }} origin/main; then
echo "Tagged commit is properly included in main branch"
else
echo "Tagged commit is not included in the main branch"
echo "Please push the commit to main before releasing"
MAIN_SHA=$(git rev-parse origin/main)
CURRENT_SHA=$(git rev-parse HEAD)
if [[ "$CURRENT_SHA" != "$MAIN_SHA" ]]; then
echo "::error::ref ${REF} (${CURRENT_SHA}) is no longer the HEAD of main (${MAIN_SHA})"
exit 1
fi

- name: Check CI status
if: ${{ !inputs.skip_ci_check }}
run: |
# Check if CI has completed successfully for this commit
gh run list --commit ${{ github.sha }} --status success --json workflowName | jq --raw-output --exit-status '
if any(.[]; .workflowName == "Install and test @ava/typescript") then
"All CI checks have passed!"
else
"CI has not completed successfully for this commit" | halt_error(1)
end'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Generate app token
id: app-token
uses: actions/create-github-app-token@v1
with:
app-id: ${{vars.LAUNCHBOT_ID}}
private-key: ${{secrets.LAUNCHBOT_PRIVATE_KEY}}

- name: Setup Node.js
uses: actions/setup-node@v4
uses: actions/setup-node@v6
with:
node-version-file: package.json
cache: npm
registry-url: https://registry.npmjs.org

- name: Bump version
if: needs.preflight.outputs.ref_is_tag == 'false'
env:
NEW_VERSION: ${{inputs.new_version}}
run: npm version "$NEW_VERSION" --no-git-tag-version

- name: Push version commit
if: needs.preflight.outputs.ref_is_tag == 'false'
id: push-commit
env:
GH_TOKEN: ${{steps.app-token.outputs.token}}
run: |
RELEASE_TAG="v$(jq --raw-output .version package.json)"
PARENT_SHA=$(git rev-parse HEAD)

jq --null-input \
--arg repo "$GITHUB_REPOSITORY" \
--arg parentSha "$PARENT_SHA" \
--arg headline "$RELEASE_TAG" \
--rawfile pkgContent package.json \
--rawfile lockContent package-lock.json \
'{
query: "mutation($input: CreateCommitOnBranchInput!) { createCommitOnBranch(input: $input) { commit { oid } } }",
variables: {
input: {
branch: { repositoryNameWithOwner: $repo, branchName: "main" },
message: { headline: $headline },
expectedHeadOid: $parentSha,
fileChanges: {
additions: [
{ path: "package.json", contents: ($pkgContent | @base64) },
{ path: "package-lock.json", contents: ($lockContent | @base64) }
]
}
}
}
}' > /tmp/request.json

COMMIT_SHA=$(gh api graphql --input /tmp/request.json \
--jq '.data.createCommitOnBranch.commit.oid')

echo "release_tag=$RELEASE_TAG" >> "$GITHUB_OUTPUT"
echo "version_commit_sha=$COMMIT_SHA" >> "$GITHUB_OUTPUT"

- name: Create version tag
if: needs.preflight.outputs.ref_is_tag == 'false'
run: |
gh api "repos/$GITHUB_REPOSITORY/git/refs" \
-f ref="refs/tags/${{steps.push-commit.outputs.release_tag}}" \
-f sha="${{steps.push-commit.outputs.version_commit_sha}}"
env:
GH_TOKEN: ${{steps.app-token.outputs.token}}

- name: Publish to npm with provenance
run: npm publish --provenance
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

- name: Create GitHub Release
run: |
RELEASE_TAG="v$(jq --raw-output .version package.json)"
gh release create "$RELEASE_TAG" \
--title "$RELEASE_TAG" \
--draft \
--generate-notes
env:
RELEASE_TAG: ${{ github.event_name == 'workflow_dispatch' && inputs.tag || github.ref_name }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GH_TOKEN: ${{steps.app-token.outputs.token}}
17 changes: 10 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ This is designed to work for projects that precompile TypeScript. It allows AVA

In other words, say you have a test file at `src/test.ts`. You've configured TypeScript to output to `build/`. Using `@ava/typescript` you can run the test using `npx ava src/test.ts`.

Compatible with AVA 6, 7 and 8. Requires Node.js 22.20, 24.12 or 25 (or newer).

## Enabling TypeScript support

Add this package to your project:
Expand Down Expand Up @@ -37,11 +39,15 @@ You can enable compilation via the `compile` property. If `false`, AVA will assu

Output files are expected to have the `.js` extension.

AVA searches your entire project for `*.js`, `*.cjs`, `*.mjs`, `*.ts`, `*.cts` and `*.mts` files (or other extensions you've configured). It will ignore such files found in the `rewritePaths` targets (e.g. `build/`). If you use more specific paths, for instance `build/main/`, you may need to change AVA's `files` configuration to ignore other directories.
AVA searches your entire project for `*.js`, `*.mjs`, `*.ts` and `*.mts` files﹡ (or other extensions you've configured). It will ignore such files found in the `rewritePaths` targets (e.g. `build/`). If you use more specific paths, for instance `build/main/`, you may need to change AVA's `files` configuration to ignore other directories.

﹡ AVA 6 and 7 will also search for `*.cjs` and `*.cts` files.

## ES Modules

If your `package.json` has configured `"type": "module"`, or you've configured AVA to treat the `js` extension as `module`, then `@ava/typescript` will import the output file as an ES module. Note that this is based on the *output file*, not the `ts` extension.
With AVA 6 and 7, if your `package.json` has configured `"type": "module"`, or you've configured AVA to treat the `js` extension as `module`, then `@ava/typescript` will import the output file as an ES module. Note that this is based on the _output file_, not the `ts` extension.

AVA 8 will _always_ import all files as ES modules.

## Add additional extensions

Expand All @@ -53,10 +59,7 @@ You can configure AVA to recognize additional file extensions. To add (partial
{
"ava": {
"typescript": {
"extensions": [
"ts",
"tsx"
],
"extensions": ["ts", "tsx"],
"rewritePaths": {
"src/": "build/"
}
Expand All @@ -69,4 +72,4 @@ If you use the [`allowJs` TypeScript option](https://www.typescriptlang.org/tsco

See also AVA's [`extensions` option](https://github.com/avajs/ava/blob/master/docs/06-configuration.md#options).

† Note that the [*preserve* mode for JSX](https://www.typescriptlang.org/docs/handbook/jsx.html) is not (yet) supported.
† Note that the [_preserve_ mode for JSX](https://www.typescriptlang.org/docs/handbook/jsx.html) is not (yet) supported.
Loading
Loading