mirror of
https://github.com/tailscale/github-action.git
synced 2026-08-21 19:09:21 +00:00
Compare commits
153 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d1b6cd204f | ||
|
|
f2a4d7820e | ||
|
|
a122c3446c | ||
|
|
55d8693392 | ||
|
|
546937c0d1 | ||
|
|
0e42fa1ff3 | ||
|
|
508737e196 | ||
|
|
5a0d794b30 | ||
|
|
ba16990ca0 | ||
|
|
191eb01caf | ||
|
|
404e7c5705 | ||
|
|
73c8a00bae | ||
|
|
780049a30b | ||
|
|
a36a368140 | ||
|
|
60d77a38ad | ||
|
|
2499098b43 | ||
|
|
06afa10de8 | ||
|
|
7155a879c8 | ||
|
|
c175bd7aa8 | ||
|
|
30ec0949da | ||
|
|
586e48b2b7 | ||
|
|
62a8a348b3 | ||
|
|
13ce09aa75 | ||
|
|
bf966a7aba | ||
|
|
0c9f54d028 | ||
|
|
0611d734da | ||
|
|
85073788ab | ||
|
|
306e68a486 | ||
|
|
989d9be101 | ||
|
|
69584d71ae | ||
|
|
cda17d523f | ||
|
|
81231eb3b2 | ||
|
|
48c6d0317a | ||
|
|
cfed5b8999 | ||
|
|
31d93e60e2 | ||
|
|
564fe381c8 | ||
|
|
127daded26 | ||
|
|
94b700f285 | ||
|
|
ec0ada4dce | ||
|
|
9c1802ce6b | ||
|
|
61e1192a01 | ||
|
|
53acf82332 | ||
|
|
376b8a186d | ||
|
|
6b3a1307e5 | ||
|
|
f166a64f7b | ||
|
|
2d4cde5889 | ||
|
|
afff14da14 | ||
|
|
fb25ad2e95 | ||
|
|
e8244c1283 | ||
|
|
d197c1d0f5 | ||
|
|
8d0691471a | ||
|
|
95e09948b8 | ||
|
|
1cc03b2f9b | ||
|
|
67f81e554b | ||
|
|
fee37da258 | ||
|
|
bfc6672599 | ||
|
|
1ab6ecf072 | ||
|
|
dea278bd44 | ||
|
|
f987cba5e9 | ||
|
|
a392da0a18 | ||
|
|
ef403f0d06 | ||
|
|
c8de7faf7a | ||
|
|
bf5cb7c4d7 | ||
|
|
bd97ec6ea8 | ||
|
|
c17f550392 | ||
|
|
3a217367ca | ||
|
|
1293ebc018 | ||
|
|
2ddbe90864 | ||
|
|
aa604318b6 | ||
|
|
b69384a992 | ||
|
|
0edb496506 | ||
|
|
ac425ca194 | ||
|
|
2976a889fc | ||
|
|
2c45c8a0fd | ||
|
|
d4729ea54c | ||
|
|
392b48279b | ||
|
|
d2d502c92b | ||
|
|
cff51cdb0c | ||
|
|
fc77efa75d | ||
|
|
75aaac9f12 | ||
|
|
90629cdeb4 | ||
|
|
cf94bd9cf6 | ||
|
|
660d7be521 | ||
|
|
39ac0a5882 | ||
|
|
391d5e0792 | ||
|
|
ed8cd4e9bf | ||
|
|
b9a346ef11 | ||
|
|
992dc80701 | ||
|
|
ea786a8afe | ||
|
|
ece0596be3 | ||
|
|
540ac650e6 | ||
|
|
7bdbdbb519 | ||
|
|
1db1f8e300 | ||
|
|
a8723264f7 | ||
|
|
6cae46e2d7 | ||
|
|
2208a5a58b | ||
|
|
3eef1cc07c | ||
|
|
0263d9e6d7 | ||
|
|
dc4930bf38 | ||
|
|
6d2f2497d7 | ||
|
|
59c4d74575 | ||
|
|
c7fc043ee0 | ||
|
|
fd5642846a | ||
|
|
c66619accf | ||
|
|
84a3f23bb4 | ||
|
|
8fe6f78f60 | ||
|
|
6986d2c82a | ||
|
|
029c99af76 | ||
|
|
5d536117a7 | ||
|
|
9a0fda8cbb | ||
|
|
91154e3930 | ||
|
|
32856f8a74 | ||
|
|
7af7df6221 | ||
|
|
4c25f5bef4 | ||
|
|
d954cb8727 | ||
|
|
694e85d253 | ||
|
|
09e4120d08 | ||
|
|
a31fee8af4 | ||
|
|
76ab37942a | ||
|
|
b4a7d2da83 | ||
|
|
19a6f4f99f | ||
|
|
b09fabcbed | ||
|
|
93605f7b8f | ||
|
|
d32d8550d2 | ||
|
|
f0c3dac2f5 | ||
|
|
5dddea1dff | ||
|
|
2b498977f3 | ||
|
|
2cbc2550a7 | ||
|
|
8688eb839e | ||
|
|
aef4d1b9e2 | ||
|
|
1ec4a5d914 | ||
|
|
cb0029737d | ||
|
|
67573e622a | ||
|
|
16d7e0b781 | ||
|
|
0893401420 | ||
|
|
57133d573b | ||
|
|
eac66e8ca4 | ||
|
|
b2b96d3c7f | ||
|
|
42b6960a76 | ||
|
|
c688cd1540 | ||
|
|
0eefde4707 | ||
|
|
408d716839 | ||
|
|
7af1b1f12d | ||
|
|
0bf9b9f36b | ||
|
|
3efa8e1ffc | ||
|
|
ca42c49ccd | ||
|
|
6ecfb8d7e8 | ||
|
|
92fe4f860b | ||
|
|
9a38686973 | ||
|
|
2075411ebb | ||
|
|
7a0b30ed35 | ||
|
|
a5ed86cd49 | ||
|
|
721822aa67 |
20 changed files with 126803 additions and 128 deletions
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
dist/** linguist-generated=true
|
||||
10
.github/dependabot.yml
vendored
Normal file
10
.github/dependabot.yml
vendored
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: npm
|
||||
directory: /
|
||||
schedule:
|
||||
interval: daily
|
||||
- package-ecosystem: github-actions
|
||||
directory: /
|
||||
schedule:
|
||||
interval: daily
|
||||
44
.github/workflows/lint.yml
vendored
Normal file
44
.github/workflows/lint.yml
vendored
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
name: "Lint Checks"
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
# Basic linter check
|
||||
lint-check:
|
||||
name: Lint check
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
|
||||
with:
|
||||
node-version: "24"
|
||||
cache: "npm"
|
||||
|
||||
- name: Install Dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Run formatter check
|
||||
run: |
|
||||
./node_modules/.bin/prettier --check --loglevel silent "src/**/*.ts" || ( \
|
||||
echo "Run this command on your local device to fix the error:" && \
|
||||
echo "" && \
|
||||
echo " make format" && \
|
||||
echo "" && exit 1)
|
||||
|
||||
- name: Run build check
|
||||
run: |
|
||||
npm run build && test -z "$(git status --porcelain)" || ( \
|
||||
echo "dist is out of date, run this command on your local device to fix the error:" && \
|
||||
echo "" && \
|
||||
echo " make build" && \
|
||||
echo "" && exit 1)
|
||||
52
.github/workflows/smoke-test.yml
vendored
Normal file
52
.github/workflows/smoke-test.yml
vendored
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
name: "Smoke Tests"
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
# Basic smoke test that doesn't require secrets
|
||||
smoke-test:
|
||||
name: Smoke Test (${{ matrix.os }})
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
|
||||
with:
|
||||
node-version: "24"
|
||||
cache: "npm"
|
||||
|
||||
- name: Install Dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Build Action
|
||||
run: npm run build
|
||||
|
||||
- name: Test Action Loading (No Auth)
|
||||
uses: ./
|
||||
with:
|
||||
version: "latest"
|
||||
continue-on-error: true
|
||||
id: smoke-test
|
||||
|
||||
# The action should fail gracefully with a proper error message
|
||||
- name: Verify Expected Failure
|
||||
shell: bash
|
||||
run: |
|
||||
if [ "${{ steps.smoke-test.outcome }}" == "success" ]; then
|
||||
echo "❌ Expected action to fail without authentication, but it succeeded"
|
||||
exit 1
|
||||
else
|
||||
echo "✅ Action correctly failed without authentication as expected"
|
||||
fi
|
||||
27
.github/workflows/tailscale.yml
vendored
27
.github/workflows/tailscale.yml
vendored
|
|
@ -1,27 +0,0 @@
|
|||
name: tailscale
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
branches:
|
||||
- '*'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Tailscale Action
|
||||
uses: ./
|
||||
with:
|
||||
oauth-client-id: ${{ secrets.TS_OAUTH_CLIENT_ID }}
|
||||
oauth-secret: ${{ secrets.TS_OAUTH_SECRET }}
|
||||
tags: tag:ci
|
||||
|
||||
- name: check for hello.ts.net in netmap
|
||||
run:
|
||||
tailscale status | grep -q hello
|
||||
168
.github/workflows/test.yml
vendored
Normal file
168
.github/workflows/test.yml
vendored
Normal file
|
|
@ -0,0 +1,168 @@
|
|||
name: "Integration Tests"
|
||||
|
||||
permissions:
|
||||
id-token: write # This is required for requesting the JWT for workload identity
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
# Matrix test for all supported platforms and architectures
|
||||
|
||||
integration-tests:
|
||||
# Skip our integration tests if the PR is from a fork. This has the consequence of
|
||||
# disabling these even if the PR is from a forked repo into itself, but given that
|
||||
# these tests are very specific to our internal test environment that is a good thing.
|
||||
#
|
||||
# Similarly, skip if this is running from a PR that has been opened by dependabot as
|
||||
# the bot does not have credentials for the integration testing tailnet.
|
||||
# TODO(mpminardi): revisit / remove this if / when we give dependabot a tailnet for
|
||||
# testing with a smaller blast radius.
|
||||
if: ${{ github.event_name == 'push' || (github.event.pull_request.head.repo.full_name == github.repository && github.actor != 'dependabot[bot]') }}
|
||||
name: ${{ matrix.os }} (${{ matrix.arch }}) (${{ matrix.credential-type }}) tailscale-${{ matrix.version }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
# Linux tests (AMD64)
|
||||
- os: ubuntu-latest
|
||||
runner-os: Linux
|
||||
arch: amd64
|
||||
version: latest
|
||||
ping: 100.99.0.2,lax-pve.pineapplefish.ts.net,lax-pve
|
||||
credential-type: oauth
|
||||
|
||||
# Try unstable too
|
||||
- os: ubuntu-latest
|
||||
runner-os: Linux
|
||||
arch: amd64
|
||||
version: unstable
|
||||
credential-type: oauth
|
||||
|
||||
# Try a pinned version
|
||||
- os: ubuntu-latest
|
||||
runner-os: Linux
|
||||
arch: amd64
|
||||
credential-type: oauth
|
||||
# leave version blank to fall back to default
|
||||
|
||||
# Linux tests (ARM64)
|
||||
- os: ubuntu-24.04-arm
|
||||
runner-os: Linux
|
||||
arch: arm64
|
||||
version: latest
|
||||
credential-type: oauth
|
||||
|
||||
# Windows tests (AMD64)
|
||||
- os: windows-latest
|
||||
runner-os: Windows
|
||||
arch: amd64
|
||||
version: latest
|
||||
ping: 100.99.0.2,lax-pve.pineapplefish.ts.net,lax-pve
|
||||
credential-type: oauth
|
||||
|
||||
# Windows tests (ARM64)
|
||||
- os: windows-11-arm
|
||||
runner-os: Windows
|
||||
arch: arm64
|
||||
version: latest
|
||||
credential-type: oauth
|
||||
|
||||
# macOS 14 (ARM)
|
||||
- os: macos-14
|
||||
runner-os: macOS
|
||||
arch: arm64
|
||||
version: latest
|
||||
ping: 100.99.0.2,lax-pve.pineapplefish.ts.net,lax-pve
|
||||
credential-type: oauth
|
||||
|
||||
# macOS latest (ARM)
|
||||
- os: macos-latest
|
||||
runner-os: macOS
|
||||
arch: arm64
|
||||
version: latest
|
||||
ping: 100.99.0.2,lax-pve.pineapplefish.ts.net,lax-pve
|
||||
credential-type: oauth
|
||||
|
||||
# Try workload identity for each platform
|
||||
- os: macos-latest
|
||||
runner-os: macOS
|
||||
arch: amd64
|
||||
version: latest
|
||||
ping: 100.99.0.2,lax-pve.pineapplefish.ts.net,lax-pve
|
||||
credential-type: workload-identity
|
||||
|
||||
- os: windows-latest
|
||||
runner-os: Windows
|
||||
arch: amd64
|
||||
ping: 100.99.0.2,lax-pve.pineapplefish.ts.net,lax-pve
|
||||
credential-type: workload-identity
|
||||
# leave version blank to fall back to default
|
||||
|
||||
# Try adding in an unstable
|
||||
- os: ubuntu-latest
|
||||
runner-os: Linux
|
||||
arch: amd64
|
||||
version: unstable
|
||||
credential-type: workload-identity
|
||||
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
|
||||
with:
|
||||
node-version: "24"
|
||||
cache: "npm"
|
||||
|
||||
- name: Install Dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Build Action
|
||||
run: npm run build
|
||||
|
||||
# Test with OAuth authentication
|
||||
- name: Test Action
|
||||
id: tailscale-oauth
|
||||
uses: ./
|
||||
with:
|
||||
oauth-client-id: ${{ matrix.credential-type == 'oauth' && secrets.TS_AUTH_KEYS_OAUTH_CLIENT_ID || secrets.TS_WORKLOAD_IDENTITY_CLIENT_ID }}
|
||||
oauth-secret: ${{ matrix.credential-type == 'oauth' && secrets.TS_AUTH_KEYS_OAUTH_CLIENT_SECRET || '' }}
|
||||
audience: ${{ matrix.credential-type == 'workload-identity' && secrets.TS_AUDIENCE || ''}}
|
||||
tags: "tag:ci"
|
||||
version: "${{ matrix.version }}"
|
||||
use-cache: false
|
||||
timeout: "5m"
|
||||
retry: 3
|
||||
ping: "${{ matrix.ping }}"
|
||||
|
||||
# Look up names to make sure MagicDNS is working
|
||||
- name: Look up qualified name
|
||||
run: nslookup lax-pve.pineapplefish.ts.net
|
||||
|
||||
- name: Look up unqualified name
|
||||
run: nslookup lax-pve
|
||||
|
||||
# Test Tailscale status command
|
||||
- name: Check Tailscale Status
|
||||
if: steps.tailscale-oauth.outcome == 'success'
|
||||
run: |
|
||||
echo "Testing Tailscale status command..."
|
||||
if [ "${{ matrix.runner-os }}" == "Windows" ]; then
|
||||
# Windows uses system-installed binary without sudo
|
||||
tailscale status
|
||||
tailscale version
|
||||
else
|
||||
# Linux and macOS use system-installed binary with sudo
|
||||
sudo -E tailscale status
|
||||
tailscale version
|
||||
fi
|
||||
shell: bash
|
||||
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
node_modules
|
||||
3
LICENSE
3
LICENSE
|
|
@ -1,6 +1,7 @@
|
|||
BSD 3-Clause License
|
||||
|
||||
Copyright (c) 2020 Tailscale & AUTHORS.
|
||||
Copyright (c) 2020 Tailscale Inc & Contributors
|
||||
Copyright (c) 2025 Lee Briggs
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
|
|
|||
42
Makefile
Normal file
42
Makefile
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
# Makefile for building a TypeScript GitHub Action
|
||||
|
||||
# Variables
|
||||
SHELL := /bin/bash
|
||||
SRC_DIR := src
|
||||
BUILD_DIR := dist
|
||||
ENTRY_POINT := $(SRC_DIR)/index.ts
|
||||
|
||||
# Binaries
|
||||
TS_NODE := ./node_modules/.bin/ts-node
|
||||
TS_C := ./node_modules/.bin/tsc
|
||||
ESLINT := ./node_modules/.bin/eslint
|
||||
PRETTIER := ./node_modules/.bin/prettier
|
||||
|
||||
# Targets
|
||||
.PHONY: all clean install build format
|
||||
|
||||
all: clean install build
|
||||
|
||||
# Clean up the lib directory
|
||||
clean:
|
||||
rm -rf $(BUILD_DIR)
|
||||
|
||||
# Install npm dependencies
|
||||
install:
|
||||
npm install
|
||||
|
||||
# Build the TypeScript code
|
||||
build: clean format
|
||||
npm run build
|
||||
|
||||
# Lint the TypeScript code
|
||||
lint:
|
||||
$(ESLINT) $(SRC_DIR)
|
||||
|
||||
# Format the TypeScript code
|
||||
format:
|
||||
$(PRETTIER) --write "$(SRC_DIR)/**/*.ts"
|
||||
|
||||
# Run the action locally (for testing purposes)
|
||||
run: build
|
||||
|
||||
201
README.md
201
README.md
|
|
@ -4,25 +4,202 @@ This GitHub Action connects to your [Tailscale network](https://tailscale.com)
|
|||
by adding a step to your workflow.
|
||||
|
||||
```yaml
|
||||
- name: Tailscale
|
||||
uses: tailscale/github-action@v2
|
||||
with:
|
||||
oauth-client-id: ${{ secrets.TS_OAUTH_CLIENT_ID }}
|
||||
oauth-secret: ${{ secrets.TS_OAUTH_SECRET }}
|
||||
tags: tag:ci
|
||||
- name: Tailscale
|
||||
uses: tailscale/github-action@v4
|
||||
with:
|
||||
oauth-client-id: ${{ secrets.TS_OAUTH_CLIENT_ID }}
|
||||
oauth-secret: ${{ secrets.TS_OAUTH_SECRET }}
|
||||
tags: tag:ci
|
||||
```
|
||||
|
||||
Subsequent steps in the Action can then access nodes in your Tailnet.
|
||||
|
||||
oauth-client-id and oauth-secret are an [OAuth client](https://tailscale.com/s/oauth-clients/)
|
||||
oauth-client-id and oauth-secret are an [OAuth client][kb-oauth-clients]
|
||||
for the tailnet to be accessed. We recommend storing these as
|
||||
[GitHub Encrypted Secrets.](https://docs.github.com/en/actions/security-guides/encrypted-secrets)
|
||||
OAuth clients used for this purpose must have the writable
|
||||
[`auth_keys` scope.][kb-trust-credentials-scopes]
|
||||
|
||||
tags is a comma-separated list of one or more [ACL Tags](https://tailscale.com/kb/1068/acl-tags/)
|
||||
tags is a comma-separated list of one or more [Tags][kb-tags]
|
||||
for the node. At least one tag is required: an OAuth client is not associated
|
||||
with any of the Users on the tailnet, it has to Tag its nodes.
|
||||
|
||||
Nodes created by this Action are [marked as Ephemeral](https://tailscale.com/s/ephemeral-nodes) to
|
||||
be automatically removed by the coordination server a short time after they
|
||||
finish their run. The nodes are also [marked Preapproved](https://tailscale.com/kb/1085/auth-keys/)
|
||||
on tailnets which use [Device Approval](https://tailscale.com/kb/1099/device-approval/)
|
||||
Nodes created by this Action are [marked as Ephemeral][kb-ephemeral-nodes] to
|
||||
and log out immediately after finishing their CI run, at which point they are automatically removed
|
||||
by the coordination server. The nodes are also [marked Preapproved][kb-auth-keys]
|
||||
on tailnets which use [Device Approval][kb-device-approval]
|
||||
|
||||
### Workload identity federation
|
||||
|
||||
[Workload identity federation][kb-workload-identity-federation] can also be used for authenticating nodes with your tailnet:
|
||||
|
||||
```yaml
|
||||
- name: Tailscale
|
||||
uses: tailscale/github-action@v4
|
||||
with:
|
||||
oauth-client-id: ${{ secrets.TS_OAUTH_CLIENT_ID }}
|
||||
audience: ${{ secrets.TS_AUDIENCE }}
|
||||
tags: tag:ci
|
||||
```
|
||||
|
||||
Workload identity federation requires the `id-token: write` [permission setting](https://docs.github.com/en/actions/how-tos/secure-your-work/security-harden-deployments/oidc-in-cloud-providers#adding-permissions-settings) for the workflow:
|
||||
|
||||
```yaml
|
||||
permissions:
|
||||
id-token: write # This is required for the tailscale action to request a JWT from GitHub
|
||||
```
|
||||
|
||||
OIDC federated identity credentials used for this purpose must have the writable [`auth_keys` scope.][kb-trust-credentials-scopes]
|
||||
|
||||
tags is a comma-separated list of one or more [Tags][kb-tags]
|
||||
for the node. At least one tag is required: a federated identity is not associated
|
||||
with any of the Users on the tailnet, it has to Tag its nodes.
|
||||
|
||||
> [!IMPORTANT]
|
||||
> Tailscale version `1.90.1` or later is required for workload identity federation.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before using the Tailscale GitHub Action, ensure you have the following:
|
||||
|
||||
1. A Tailscale account with Owner, Admin, or Network admin permissions.
|
||||
1. A GitHub repository that you have admin access to (required to set up the GitHub Action).
|
||||
1. At least one configured [tag][kb-tags] if using OAuth or workload identity federation.
|
||||
1. An [OAuth client][kb-oauth-clients] ID and secret, [federated identity][kb-workload-identity-federation] client ID and audience, OR an [auth key][kb-auth-keys].
|
||||
1. A runner image version >= 2.237.1 (required to support running Node.js 24).
|
||||
|
||||
## Eventual consistency
|
||||
|
||||
Propagating information about new peers - such as the node created by this action - across your tailnet
|
||||
is an eventually consistent process, and brief delays are expected. Until the GitHub workflow node
|
||||
becomes visible, other peers will not accept connections. It is best to verify connectivity to the
|
||||
intended nodes before executing steps that rely on them.
|
||||
|
||||
You can do this by adding a list of hosts to ping to the action configuration:
|
||||
|
||||
```yaml
|
||||
- name: Tailscale
|
||||
uses: tailscale/github-action@v4
|
||||
with:
|
||||
ping: 100.x.y.z,my-machine.my-tailnet.ts.net
|
||||
```
|
||||
|
||||
or with the [tailscale ping][kb-cli-ping] command if you do not know the peers at the time of installing Tailscale in the workflow:
|
||||
|
||||
```bash
|
||||
tailscale ping my-target.my-tailnet.ts.net
|
||||
```
|
||||
|
||||
The `ping` option will wait up to 3 minutes for a connection (direct or relayed).
|
||||
|
||||
## Log mode
|
||||
|
||||
By default, this action folds its major setup and cleanup phases into GitHub Actions log groups.
|
||||
You can change this with the `log-mode` input:
|
||||
|
||||
```yaml
|
||||
- name: Tailscale
|
||||
uses: tailscale/github-action@v4
|
||||
with:
|
||||
oauth-client-id: ${{ secrets.TS_OAUTH_CLIENT_ID }}
|
||||
oauth-secret: ${{ secrets.TS_OAUTH_SECRET }}
|
||||
tags: tag:ci
|
||||
log-mode: normal
|
||||
```
|
||||
|
||||
Supported values are:
|
||||
|
||||
- `grouped`: fold major action phases in the log. This is the default.
|
||||
- `normal`: print routine action logs without grouping.
|
||||
- `quiet`: suppress routine informational output while preserving warnings and errors.
|
||||
|
||||
## Tailnet Lock
|
||||
|
||||
If you are using this Action in a [Tailnet Lock][kb-tailnet-lock] enabled network, you need to:
|
||||
|
||||
- Authenticate using an ephemeral reusable [pre-signed auth key][kb-tailnet-lock-pre-signed]
|
||||
rather than an OAuth client.
|
||||
- Specify a [state directory][kb-tailscaled-flags] for the
|
||||
client to store the Tailnet Key Authority data in.
|
||||
|
||||
```yaml
|
||||
- name: Tailscale
|
||||
uses: tailscale/github-action@v4
|
||||
with:
|
||||
authkey: tskey-auth-...
|
||||
statedir: /tmp/tailscale-state/
|
||||
```
|
||||
|
||||
## Defining Tailscale version
|
||||
|
||||
Which Tailscale version to use can be set like this:
|
||||
|
||||
```yaml
|
||||
- name: Tailscale
|
||||
uses: tailscale/github-action@v4
|
||||
with:
|
||||
oauth-client-id: ${{ secrets.TS_OAUTH_CLIENT_ID }}
|
||||
oauth-secret: ${{ secrets.TS_OAUTH_SECRET }}
|
||||
tags: tag:ci
|
||||
version: 1.52.0
|
||||
```
|
||||
|
||||
If you'd like to specify the latest version, simply set the version as `latest`
|
||||
|
||||
```yaml
|
||||
- name: Tailscale
|
||||
uses: tailscale/github-action@v4
|
||||
with:
|
||||
oauth-client-id: ${{ secrets.TS_OAUTH_CLIENT_ID }}
|
||||
oauth-secret: ${{ secrets.TS_OAUTH_SECRET }}
|
||||
tags: tag:ci
|
||||
version: latest
|
||||
```
|
||||
|
||||
You can find the latest Tailscale stable version number at
|
||||
https://pkgs.tailscale.com/stable/#static.
|
||||
|
||||
You can also specify `version: unstable` to use the latest unstable version of Tailscale.
|
||||
For Linux and Windows, this uses the version published at https://pkgs.tailscale.com/unstable,
|
||||
and for MacOS it uses the HEAD of the `main` branch of https://github.com/tailscale/tailscale/.
|
||||
|
||||
## Cache Tailscale binaries
|
||||
|
||||
Caching can reduce download times and download failures on runners with slower network connectivity.
|
||||
As of v4 of this action, caching is enabled by default.
|
||||
|
||||
Although caching is generally recommended, you can disable it by passing `'false'` to the `use-cache` input:
|
||||
|
||||
```yaml
|
||||
- name: Tailscale
|
||||
uses: tailscale/github-action@v4
|
||||
with:
|
||||
oauth-client-id: ${{ secrets.TS_OAUTH_CLIENT_ID }}
|
||||
oauth-secret: ${{ secrets.TS_OAUTH_SECRET }}
|
||||
use-cache: "false"
|
||||
```
|
||||
|
||||
## Usage on persistent self-hosted runners
|
||||
|
||||
When running on self-hosted runners that persist after CI jobs have finished,
|
||||
the GitHub Action leaves tailscale binaries installed but stops the tailscale background processes.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### requested tags [tag:mytag] are invalid or not permitted
|
||||
|
||||
You may encounter this error when using a trust credential (OAuth client or OIDC federated identity).
|
||||
Trust credentials must have the writable [`auth_keys` scope][kb-trust-credentials-scopes] with one or more [tags][kb-tags],
|
||||
and the tags specified with `tags` must match all tags on the trust credential or be tags owned by the tags on the trust credential.
|
||||
|
||||
[kb-auth-keys]: https://tailscale.com/kb/1085/auth-keys
|
||||
[kb-cli-ping]: https://tailscale.com/kb/1080/cli#ping
|
||||
[kb-device-approval]: https://tailscale.com/kb/1099/device-approval
|
||||
[kb-ephemeral-nodes]: https://tailscale.com/kb/1111/ephemeral-nodes
|
||||
[kb-oauth-clients]: https://tailscale.com/kb/1215/oauth-clients
|
||||
[kb-tags]: https://tailscale.com/kb/1068/tags
|
||||
[kb-tailnet-lock]: https://tailscale.com/kb/1226/tailnet-lock
|
||||
[kb-tailnet-lock-pre-signed]: https://tailscale.com/kb/1226/tailnet-lock#add-a-node-using-a-pre-signed-auth-key
|
||||
[kb-tailscaled-flags]: https://tailscale.com/kb/1278/tailscaled#flags-to-tailscaled
|
||||
[kb-trust-credentials-scopes]: https://tailscale.com/kb/1623/trust-credentials#scopes
|
||||
[kb-workload-identity-federation]: https://tailscale.com/kb/1581/workload-identity-federation
|
||||
|
|
|
|||
5
README_CI.md
Normal file
5
README_CI.md
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
### CI Notes
|
||||
|
||||
CI tests run against the pineapplefish-tailnet.org.github tailnet. Check our usual credential store for credentials.
|
||||
|
||||
`tag:ci` must have access to the `lax-pve` server.
|
||||
135
action.yml
135
action.yml
|
|
@ -1,116 +1,75 @@
|
|||
# Copyright (c) Tailscale Inc & AUTHORS
|
||||
# Copyright (c) Lee Briggs, Tailscale Inc, & Contributors
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
name: 'Connect Tailscale'
|
||||
description: 'Connect your GitHub Action workflow to Tailscale'
|
||||
branding:
|
||||
icon: 'arrow-right-circle'
|
||||
color: 'gray-dark'
|
||||
|
||||
inputs:
|
||||
authkey:
|
||||
description: 'Your Tailscale authentication key, from the admin panel.'
|
||||
required: false
|
||||
deprecationMessage: 'An OAuth API client https://tailscale.com/s/oauth-clients is recommended instead of an authkey'
|
||||
oauth-client-id:
|
||||
description: 'Your Tailscale OAuth Client ID.'
|
||||
description: 'Your Tailscale OAuth or OIDC Federated Identity clientID.'
|
||||
required: false
|
||||
audience:
|
||||
description: 'Your Tailscale OIDC Federated Identity Audience'
|
||||
required: false
|
||||
oauth-secret:
|
||||
description: 'Your Tailscale OAuth Client Secret.'
|
||||
required: false
|
||||
tags:
|
||||
description: 'Comma separated list of Tags to be applied to nodes. The OAuth client must have permission to apply these tags.'
|
||||
description: 'Comma separated list of Tags to be applied to nodes. When using an OAuth client, the OAuth client must have the `auth_keys` scope and alls tags on the OAuth client must match all tags specified here.'
|
||||
required: false
|
||||
version:
|
||||
description: 'Tailscale version to use.'
|
||||
description: 'Tailscale version to use. Specify `latest` to use the latest stable version, and `unstable` to use the latest development version.'
|
||||
required: true
|
||||
default: '1.42.0'
|
||||
default: '1.94.2'
|
||||
args:
|
||||
description: 'Optional additional arguments to `tailscale up`.'
|
||||
required: false
|
||||
default: ''
|
||||
tailscaled-args:
|
||||
description: 'Optional additional arguments to `tailscaled`.'
|
||||
required: false
|
||||
default: ''
|
||||
hostname:
|
||||
description: 'Fixed hostname to use. Must be a valid DNS label (alphanumeric and dashes only, 1-63 characters, cannot start or end with a dash). If not provided, a hostname will be generated based on the runner name.'
|
||||
required: false
|
||||
default: ''
|
||||
timeout:
|
||||
description: 'Timeout for `tailscale up`.'
|
||||
required: false
|
||||
default: '2m'
|
||||
retry:
|
||||
description: 'Number of retries for `tailscale up`.'
|
||||
required: false
|
||||
default: '5'
|
||||
use-cache:
|
||||
description: 'Enable caching of Tailscale binaries to speed up subsequent runs.'
|
||||
required: false
|
||||
default: 'true'
|
||||
statedir:
|
||||
description: 'Directory to store Tailscale state. If empty, uses in-memory storage.'
|
||||
required: false
|
||||
default: ''
|
||||
sha256sum:
|
||||
description: 'Expected SHA256 checksum of the tarball.'
|
||||
required: false
|
||||
default: ''
|
||||
args:
|
||||
description: 'Optional additional arguments to `tailscale up`'
|
||||
ping:
|
||||
description: 'Comma separated list of hosts (Tailscale IP addresses or machine names if MagicDNS is enabled on the tailnet) to `tailscale ping` for connectivity verification after `tailscale up` completes.'
|
||||
required: false
|
||||
default: ''
|
||||
tailscaled-args:
|
||||
description: 'Optional additional arguments to `tailscaled`'
|
||||
log-mode:
|
||||
description: 'Controls action log output mode. Use `grouped` to fold major setup and cleanup phases, `normal` for ungrouped logs, or `quiet` to suppress routine informational output.'
|
||||
required: false
|
||||
default: ''
|
||||
hostname:
|
||||
description: 'Fixed hostname to use.'
|
||||
required: false
|
||||
default: ''
|
||||
default: 'grouped'
|
||||
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- name: Check Runner OS
|
||||
if: ${{ runner.os != 'Linux' }}
|
||||
shell: bash
|
||||
run: |
|
||||
echo "::error title=⛔ error hint::Support Linux Only"
|
||||
exit 1
|
||||
- name: Check Auth Info Empty
|
||||
if: ${{ inputs.authkey == '' && (inputs['oauth-secret'] == '' || inputs.tags == '') }}
|
||||
shell: bash
|
||||
run: |
|
||||
echo "::error title=⛔ error hint::OAuth identity empty, Maybe you need to populate it in the Secrets for your workflow, see more in https://docs.github.com/en/actions/security-guides/encrypted-secrets and https://tailscale.com/s/oauth-clients"
|
||||
exit 1
|
||||
- name: Download Tailscale
|
||||
shell: bash
|
||||
id: download
|
||||
env:
|
||||
VERSION: ${{ inputs.version }}
|
||||
SHA256SUM: ${{ inputs.sha256sum }}
|
||||
run: |
|
||||
if [ ${{ runner.arch }} = "ARM64" ]; then
|
||||
TS_ARCH="arm64"
|
||||
elif [ ${{ runner.arch }} = "ARM" ]; then
|
||||
TS_ARCH="arm"
|
||||
elif [ ${{ runner.arch }} = "X86" ]; then
|
||||
TS_ARCH="386"
|
||||
elif [ ${{ runner.arch }} = "X64" ]; then
|
||||
TS_ARCH="amd64"
|
||||
else
|
||||
TS_ARCH="amd64"
|
||||
fi
|
||||
MINOR=$(echo "$VERSION" | awk -F '.' {'print $2'})
|
||||
if [ $((MINOR % 2)) -eq 0 ]; then
|
||||
URL="https://pkgs.tailscale.com/stable/tailscale_${VERSION}_${TS_ARCH}.tgz"
|
||||
else
|
||||
URL="https://pkgs.tailscale.com/unstable/tailscale_${VERSION}_${TS_ARCH}.tgz"
|
||||
fi
|
||||
if ! [[ "$SHA256SUM" ]] ; then
|
||||
SHA256SUM="$(curl -H user-agent:tailscale-github-action -L "${URL}.sha256")"
|
||||
fi
|
||||
curl -H user-agent:tailscale-github-action -L "$URL" -o tailscale.tgz --max-time 300
|
||||
echo "$SHA256SUM tailscale.tgz" | sha256sum -c
|
||||
tar -C /tmp -xzf tailscale.tgz
|
||||
rm tailscale.tgz
|
||||
TSPATH=/tmp/tailscale_${VERSION}_${TS_ARCH}
|
||||
sudo mv "${TSPATH}/tailscale" "${TSPATH}/tailscaled" /usr/bin
|
||||
- name: Start Tailscale Daemon
|
||||
shell: bash
|
||||
env:
|
||||
ADDITIONAL_DAEMON_ARGS: ${{ inputs.tailscaled-args }}
|
||||
run: |
|
||||
sudo -E tailscaled --state=mem: ${ADDITIONAL_DAEMON_ARGS} 2>~/tailscaled.log &
|
||||
# And check that tailscaled came up. The CLI will block for a bit waiting
|
||||
# for it. And --json will make it exit with status 0 even if we're logged
|
||||
# out (as we will be). Without --json it returns an error if we're not up.
|
||||
sudo -E tailscale status --json >/dev/null
|
||||
- name: Connect to Tailscale
|
||||
shell: bash
|
||||
env:
|
||||
TAILSCALE_AUTHKEY: ${{ inputs.authkey }}
|
||||
ADDITIONAL_ARGS: ${{ inputs.args }}
|
||||
HOSTNAME: ${{ inputs.hostname }}
|
||||
TS_EXPERIMENT_OAUTH_AUTHKEY: true
|
||||
run: |
|
||||
if [ -z "${HOSTNAME}" ]; then
|
||||
HOSTNAME="github-$(cat /etc/hostname)"
|
||||
fi
|
||||
if [ -n "${{ inputs['oauth-secret'] }}" ]; then
|
||||
TAILSCALE_AUTHKEY="${{ inputs['oauth-secret'] }}?preauthorized=true&ephemeral=true"
|
||||
TAGS_ARG="--advertise-tags=${{ inputs.tags }}"
|
||||
fi
|
||||
timeout 5m sudo -E tailscale up ${TAGS_ARG} --authkey=${TAILSCALE_AUTHKEY} --hostname=${HOSTNAME} --accept-routes ${ADDITIONAL_ARGS}
|
||||
using: 'node24'
|
||||
main: 'dist/index.js'
|
||||
post: 'dist/logout/index.js'
|
||||
|
|
|
|||
96019
dist/index.js
generated
vendored
Normal file
96019
dist/index.js
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
28072
dist/logout/index.js
generated
vendored
Normal file
28072
dist/logout/index.js
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
771
package-lock.json
generated
Normal file
771
package-lock.json
generated
Normal file
|
|
@ -0,0 +1,771 @@
|
|||
{
|
||||
"name": "github-action",
|
||||
"version": "4.0.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "github-action",
|
||||
"version": "4.0.0",
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"@actions/cache": "^5.0.2",
|
||||
"@actions/core": "^2.0.2",
|
||||
"@actions/exec": "^2.0.0",
|
||||
"@actions/tool-cache": "^3.0.0",
|
||||
"semver": "^7.7.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^24.10.2",
|
||||
"@vercel/ncc": "^0.38.3",
|
||||
"prettier": "^3.8.3",
|
||||
"prettier-plugin-organize-imports": "^4.3.0",
|
||||
"typescript": "^6.0.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=24.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/cache": {
|
||||
"version": "5.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@actions/cache/-/cache-5.0.2.tgz",
|
||||
"integrity": "sha512-6w3i9n12eWJyut6TOnh7SIxGmeIepB5wbXMvlPv9+6CjvTD4OYKi1Wjh7TQrjEf8xLb6hxsVCpPsL/1gxnlTtw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@actions/core": "^2.0.0",
|
||||
"@actions/exec": "^2.0.0",
|
||||
"@actions/glob": "^0.5.0",
|
||||
"@actions/http-client": "^3.0.1",
|
||||
"@actions/io": "^2.0.0",
|
||||
"@azure/abort-controller": "^1.1.0",
|
||||
"@azure/core-rest-pipeline": "^1.22.0",
|
||||
"@azure/storage-blob": "^12.29.1",
|
||||
"@protobuf-ts/runtime-rpc": "^2.11.1",
|
||||
"semver": "^6.3.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/cache/node_modules/@actions/http-client": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-3.0.1.tgz",
|
||||
"integrity": "sha512-SbGS8c/vySbNO3kjFgSW77n83C4MQx/Yoe+b1hAdpuvfHxnkHzDq2pWljUpAA56Si1Gae/7zjeZsV0CYjmLo/w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"tunnel": "^0.0.6",
|
||||
"undici": "^5.28.5"
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/cache/node_modules/@actions/io": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@actions/io/-/io-2.0.0.tgz",
|
||||
"integrity": "sha512-Jv33IN09XLO+0HS79aaODsvIRyduiF7NY/F6LYeK5oeUmrsz7aFdRphQjFoESF4jS7lMauDOttKALcpapVDIAg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@actions/cache/node_modules/semver": {
|
||||
"version": "6.3.1",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
|
||||
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
|
||||
"license": "ISC",
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/core": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@actions/core/-/core-2.0.2.tgz",
|
||||
"integrity": "sha512-Ast1V7yHbGAhplAsuVlnb/5J8Mtr/Zl6byPPL+Qjq3lmfIgWF1ak1iYfF/079cRERiuTALTXkSuEUdZeDCfGtA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@actions/exec": "^2.0.0",
|
||||
"@actions/http-client": "^3.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/core/node_modules/@actions/http-client": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-3.0.1.tgz",
|
||||
"integrity": "sha512-SbGS8c/vySbNO3kjFgSW77n83C4MQx/Yoe+b1hAdpuvfHxnkHzDq2pWljUpAA56Si1Gae/7zjeZsV0CYjmLo/w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"tunnel": "^0.0.6",
|
||||
"undici": "^5.28.5"
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/exec": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@actions/exec/-/exec-2.0.0.tgz",
|
||||
"integrity": "sha512-k8ngrX2voJ/RIN6r9xB82NVqKpnMRtxDoiO+g3olkIUpQNqjArXrCQceduQZCQj3P3xm32pChRLqRrtXTlqhIw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@actions/io": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/exec/node_modules/@actions/io": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@actions/io/-/io-2.0.0.tgz",
|
||||
"integrity": "sha512-Jv33IN09XLO+0HS79aaODsvIRyduiF7NY/F6LYeK5oeUmrsz7aFdRphQjFoESF4jS7lMauDOttKALcpapVDIAg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@actions/glob": {
|
||||
"version": "0.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@actions/glob/-/glob-0.5.0.tgz",
|
||||
"integrity": "sha512-tST2rjPvJLRZLuT9NMUtyBjvj9Yo0MiJS3ow004slMvm8GFM+Zv9HvMJ7HWzfUyJnGrJvDsYkWBaaG3YKXRtCw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@actions/core": "^1.9.1",
|
||||
"minimatch": "^3.0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/glob/node_modules/@actions/core": {
|
||||
"version": "1.11.1",
|
||||
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.11.1.tgz",
|
||||
"integrity": "sha512-hXJCSrkwfA46Vd9Z3q4cpEpHB1rL5NG04+/rbqW9d3+CSvtB1tYe8UTpAlixa1vj0m/ULglfEK2UKxMGxCxv5A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@actions/exec": "^1.1.1",
|
||||
"@actions/http-client": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/glob/node_modules/@actions/exec": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@actions/exec/-/exec-1.1.1.tgz",
|
||||
"integrity": "sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@actions/io": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/http-client": {
|
||||
"version": "2.2.3",
|
||||
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.2.3.tgz",
|
||||
"integrity": "sha512-mx8hyJi/hjFvbPokCg4uRd4ZX78t+YyRPtnKWwIl+RzNaVuFpQHfmlGVfsKEJN8LwTCvL+DfVgAM04XaHkm6bA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"tunnel": "^0.0.6",
|
||||
"undici": "^5.25.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/io": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@actions/io/-/io-1.1.3.tgz",
|
||||
"integrity": "sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@actions/tool-cache": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@actions/tool-cache/-/tool-cache-3.0.0.tgz",
|
||||
"integrity": "sha512-JBx8gEWuu8Lqaqx/hEnL6QdKvF06suBR4y+dBDi9vJbHx1r+p6QtmBKhQYhiKjDUYIoDX1bUrbyAYPChoPK+XA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@actions/core": "^2.0.1",
|
||||
"@actions/exec": "^2.0.0",
|
||||
"@actions/http-client": "^3.0.1",
|
||||
"@actions/io": "^2.0.0",
|
||||
"semver": "^6.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/tool-cache/node_modules/@actions/http-client": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-3.0.1.tgz",
|
||||
"integrity": "sha512-SbGS8c/vySbNO3kjFgSW77n83C4MQx/Yoe+b1hAdpuvfHxnkHzDq2pWljUpAA56Si1Gae/7zjeZsV0CYjmLo/w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"tunnel": "^0.0.6",
|
||||
"undici": "^5.28.5"
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/tool-cache/node_modules/@actions/io": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@actions/io/-/io-2.0.0.tgz",
|
||||
"integrity": "sha512-Jv33IN09XLO+0HS79aaODsvIRyduiF7NY/F6LYeK5oeUmrsz7aFdRphQjFoESF4jS7lMauDOttKALcpapVDIAg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@actions/tool-cache/node_modules/semver": {
|
||||
"version": "6.3.1",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
|
||||
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
|
||||
"license": "ISC",
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
}
|
||||
},
|
||||
"node_modules/@azure/abort-controller": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-1.1.0.tgz",
|
||||
"integrity": "sha512-TrRLIoSQVzfAJX9H1JeFjzAoDGcoK1IYX1UImfceTZpsyYfWr09Ss1aHW1y5TrrR3iq6RZLBwJ3E24uwPhwahw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"tslib": "^2.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@azure/core-auth": {
|
||||
"version": "1.10.1",
|
||||
"resolved": "https://registry.npmjs.org/@azure/core-auth/-/core-auth-1.10.1.tgz",
|
||||
"integrity": "sha512-ykRMW8PjVAn+RS6ww5cmK9U2CyH9p4Q88YJwvUslfuMmN98w/2rdGRLPqJYObapBCdzBVeDgYWdJnFPFb7qzpg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@azure/abort-controller": "^2.1.2",
|
||||
"@azure/core-util": "^1.13.0",
|
||||
"tslib": "^2.6.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@azure/core-auth/node_modules/@azure/abort-controller": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.2.tgz",
|
||||
"integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"tslib": "^2.6.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@azure/core-client": {
|
||||
"version": "1.10.1",
|
||||
"resolved": "https://registry.npmjs.org/@azure/core-client/-/core-client-1.10.1.tgz",
|
||||
"integrity": "sha512-Nh5PhEOeY6PrnxNPsEHRr9eimxLwgLlpmguQaHKBinFYA/RU9+kOYVOQqOrTsCL+KSxrLLl1gD8Dk5BFW/7l/w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@azure/abort-controller": "^2.1.2",
|
||||
"@azure/core-auth": "^1.10.0",
|
||||
"@azure/core-rest-pipeline": "^1.22.0",
|
||||
"@azure/core-tracing": "^1.3.0",
|
||||
"@azure/core-util": "^1.13.0",
|
||||
"@azure/logger": "^1.3.0",
|
||||
"tslib": "^2.6.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@azure/core-client/node_modules/@azure/abort-controller": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.2.tgz",
|
||||
"integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"tslib": "^2.6.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@azure/core-http-compat": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@azure/core-http-compat/-/core-http-compat-2.3.1.tgz",
|
||||
"integrity": "sha512-az9BkXND3/d5VgdRRQVkiJb2gOmDU8Qcq4GvjtBmDICNiQ9udFmDk4ZpSB5Qq1OmtDJGlQAfBaS4palFsazQ5g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@azure/abort-controller": "^2.1.2",
|
||||
"@azure/core-client": "^1.10.0",
|
||||
"@azure/core-rest-pipeline": "^1.22.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@azure/core-http-compat/node_modules/@azure/abort-controller": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.2.tgz",
|
||||
"integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"tslib": "^2.6.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@azure/core-lro": {
|
||||
"version": "2.7.2",
|
||||
"resolved": "https://registry.npmjs.org/@azure/core-lro/-/core-lro-2.7.2.tgz",
|
||||
"integrity": "sha512-0YIpccoX8m/k00O7mDDMdJpbr6mf1yWo2dfmxt5A8XVZVVMz2SSKaEbMCeJRvgQ0IaSlqhjT47p4hVIRRy90xw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@azure/abort-controller": "^2.0.0",
|
||||
"@azure/core-util": "^1.2.0",
|
||||
"@azure/logger": "^1.0.0",
|
||||
"tslib": "^2.6.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@azure/core-lro/node_modules/@azure/abort-controller": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.2.tgz",
|
||||
"integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"tslib": "^2.6.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@azure/core-paging": {
|
||||
"version": "1.6.2",
|
||||
"resolved": "https://registry.npmjs.org/@azure/core-paging/-/core-paging-1.6.2.tgz",
|
||||
"integrity": "sha512-YKWi9YuCU04B55h25cnOYZHxXYtEvQEbKST5vqRga7hWY9ydd3FZHdeQF8pyh+acWZvppw13M/LMGx0LABUVMA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"tslib": "^2.6.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@azure/core-rest-pipeline": {
|
||||
"version": "1.22.2",
|
||||
"resolved": "https://registry.npmjs.org/@azure/core-rest-pipeline/-/core-rest-pipeline-1.22.2.tgz",
|
||||
"integrity": "sha512-MzHym+wOi8CLUlKCQu12de0nwcq9k9Kuv43j4Wa++CsCpJwps2eeBQwD2Bu8snkxTtDKDx4GwjuR9E8yC8LNrg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@azure/abort-controller": "^2.1.2",
|
||||
"@azure/core-auth": "^1.10.0",
|
||||
"@azure/core-tracing": "^1.3.0",
|
||||
"@azure/core-util": "^1.13.0",
|
||||
"@azure/logger": "^1.3.0",
|
||||
"@typespec/ts-http-runtime": "^0.3.0",
|
||||
"tslib": "^2.6.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@azure/core-rest-pipeline/node_modules/@azure/abort-controller": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.2.tgz",
|
||||
"integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"tslib": "^2.6.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@azure/core-tracing": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@azure/core-tracing/-/core-tracing-1.3.1.tgz",
|
||||
"integrity": "sha512-9MWKevR7Hz8kNzzPLfX4EAtGM2b8mr50HPDBvio96bURP/9C+HjdH3sBlLSNNrvRAr5/k/svoH457gB5IKpmwQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"tslib": "^2.6.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@azure/core-util": {
|
||||
"version": "1.13.1",
|
||||
"resolved": "https://registry.npmjs.org/@azure/core-util/-/core-util-1.13.1.tgz",
|
||||
"integrity": "sha512-XPArKLzsvl0Hf0CaGyKHUyVgF7oDnhKoP85Xv6M4StF/1AhfORhZudHtOyf2s+FcbuQ9dPRAjB8J2KvRRMUK2A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@azure/abort-controller": "^2.1.2",
|
||||
"@typespec/ts-http-runtime": "^0.3.0",
|
||||
"tslib": "^2.6.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@azure/core-util/node_modules/@azure/abort-controller": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.2.tgz",
|
||||
"integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"tslib": "^2.6.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@azure/core-xml": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@azure/core-xml/-/core-xml-1.5.0.tgz",
|
||||
"integrity": "sha512-D/sdlJBMJfx7gqoj66PKVmhDDaU6TKA49ptcolxdas29X7AfvLTmfAGLjAcIMBK7UZ2o4lygHIqVckOlQU3xWw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"fast-xml-parser": "^5.0.7",
|
||||
"tslib": "^2.8.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@azure/logger": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@azure/logger/-/logger-1.3.0.tgz",
|
||||
"integrity": "sha512-fCqPIfOcLE+CGqGPd66c8bZpwAji98tZ4JI9i/mlTNTlsIWslCfpg48s/ypyLxZTump5sypjrKn2/kY7q8oAbA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@typespec/ts-http-runtime": "^0.3.0",
|
||||
"tslib": "^2.6.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@azure/storage-blob": {
|
||||
"version": "12.29.1",
|
||||
"resolved": "https://registry.npmjs.org/@azure/storage-blob/-/storage-blob-12.29.1.tgz",
|
||||
"integrity": "sha512-7ktyY0rfTM0vo7HvtK6E3UvYnI9qfd6Oz6z/+92VhGRveWng3kJwMKeUpqmW/NmwcDNbxHpSlldG+vsUnRFnBg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@azure/abort-controller": "^2.1.2",
|
||||
"@azure/core-auth": "^1.9.0",
|
||||
"@azure/core-client": "^1.9.3",
|
||||
"@azure/core-http-compat": "^2.2.0",
|
||||
"@azure/core-lro": "^2.2.0",
|
||||
"@azure/core-paging": "^1.6.2",
|
||||
"@azure/core-rest-pipeline": "^1.19.1",
|
||||
"@azure/core-tracing": "^1.2.0",
|
||||
"@azure/core-util": "^1.11.0",
|
||||
"@azure/core-xml": "^1.4.5",
|
||||
"@azure/logger": "^1.1.4",
|
||||
"@azure/storage-common": "^12.1.1",
|
||||
"events": "^3.0.0",
|
||||
"tslib": "^2.8.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@azure/storage-blob/node_modules/@azure/abort-controller": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.2.tgz",
|
||||
"integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"tslib": "^2.6.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@azure/storage-common": {
|
||||
"version": "12.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@azure/storage-common/-/storage-common-12.1.1.tgz",
|
||||
"integrity": "sha512-eIOH1pqFwI6UmVNnDQvmFeSg0XppuzDLFeUNO/Xht7ODAzRLgGDh7h550pSxoA+lPDxBl1+D2m/KG3jWzCUjTg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@azure/abort-controller": "^2.1.2",
|
||||
"@azure/core-auth": "^1.9.0",
|
||||
"@azure/core-http-compat": "^2.2.0",
|
||||
"@azure/core-rest-pipeline": "^1.19.1",
|
||||
"@azure/core-tracing": "^1.2.0",
|
||||
"@azure/core-util": "^1.11.0",
|
||||
"@azure/logger": "^1.1.4",
|
||||
"events": "^3.3.0",
|
||||
"tslib": "^2.8.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@azure/storage-common/node_modules/@azure/abort-controller": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.2.tgz",
|
||||
"integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"tslib": "^2.6.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@fastify/busboy": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz",
|
||||
"integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"node_modules/@protobuf-ts/runtime": {
|
||||
"version": "2.11.1",
|
||||
"resolved": "https://registry.npmjs.org/@protobuf-ts/runtime/-/runtime-2.11.1.tgz",
|
||||
"integrity": "sha512-KuDaT1IfHkugM2pyz+FwiY80ejWrkH1pAtOBOZFuR6SXEFTsnb/jiQWQ1rCIrcKx2BtyxnxW6BWwsVSA/Ie+WQ==",
|
||||
"license": "(Apache-2.0 AND BSD-3-Clause)"
|
||||
},
|
||||
"node_modules/@protobuf-ts/runtime-rpc": {
|
||||
"version": "2.11.1",
|
||||
"resolved": "https://registry.npmjs.org/@protobuf-ts/runtime-rpc/-/runtime-rpc-2.11.1.tgz",
|
||||
"integrity": "sha512-4CqqUmNA+/uMz00+d3CYKgElXO9VrEbucjnBFEjqI4GuDrEQ32MaI3q+9qPBvIGOlL4PmHXrzM32vBPWRhQKWQ==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@protobuf-ts/runtime": "^2.11.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "24.10.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.2.tgz",
|
||||
"integrity": "sha512-WOhQTZ4G8xZ1tjJTvKOpyEVSGgOTvJAfDK3FNFgELyaTpzhdgHVHeqW8V+UJvzF5BT+/B54T/1S2K6gd9c7bbA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"undici-types": "~7.16.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@typespec/ts-http-runtime": {
|
||||
"version": "0.3.2",
|
||||
"resolved": "https://registry.npmjs.org/@typespec/ts-http-runtime/-/ts-http-runtime-0.3.2.tgz",
|
||||
"integrity": "sha512-IlqQ/Gv22xUC1r/WQm4StLkYQmaaTsXAhUVsNE0+xiyf0yRFiH5++q78U3bw6bLKDCTmh0uqKB9eG9+Bt75Dkg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"http-proxy-agent": "^7.0.0",
|
||||
"https-proxy-agent": "^7.0.0",
|
||||
"tslib": "^2.6.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@vercel/ncc": {
|
||||
"version": "0.38.4",
|
||||
"resolved": "https://registry.npmjs.org/@vercel/ncc/-/ncc-0.38.4.tgz",
|
||||
"integrity": "sha512-8LwjnlP39s08C08J5NstzriPvW1SP8Zfpp1BvC2sI35kPeZnHfxVkCwu4/+Wodgnd60UtT1n8K8zw+Mp7J9JmQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"ncc": "dist/ncc/cli.js"
|
||||
}
|
||||
},
|
||||
"node_modules/agent-base": {
|
||||
"version": "7.1.4",
|
||||
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz",
|
||||
"integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 14"
|
||||
}
|
||||
},
|
||||
"node_modules/balanced-match": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/brace-expansion": {
|
||||
"version": "1.1.12",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
|
||||
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/concat-map": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/debug": {
|
||||
"version": "4.4.3",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
|
||||
"integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ms": "^2.1.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"supports-color": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/events": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
|
||||
"integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.8.x"
|
||||
}
|
||||
},
|
||||
"node_modules/fast-xml-parser": {
|
||||
"version": "5.3.3",
|
||||
"resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.3.3.tgz",
|
||||
"integrity": "sha512-2O3dkPAAC6JavuMm8+4+pgTk+5hoAs+CjZ+sWcQLkX9+/tHRuTkQh/Oaifr8qDmZ8iEHb771Ea6G8CdwkrgvYA==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/NaturalIntelligence"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"strnum": "^2.1.0"
|
||||
},
|
||||
"bin": {
|
||||
"fxparser": "src/cli/cli.js"
|
||||
}
|
||||
},
|
||||
"node_modules/http-proxy-agent": {
|
||||
"version": "7.0.2",
|
||||
"resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz",
|
||||
"integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"agent-base": "^7.1.0",
|
||||
"debug": "^4.3.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 14"
|
||||
}
|
||||
},
|
||||
"node_modules/https-proxy-agent": {
|
||||
"version": "7.0.6",
|
||||
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz",
|
||||
"integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"agent-base": "^7.1.2",
|
||||
"debug": "4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 14"
|
||||
}
|
||||
},
|
||||
"node_modules/minimatch": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/ms": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/prettier": {
|
||||
"version": "3.8.3",
|
||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.3.tgz",
|
||||
"integrity": "sha512-7igPTM53cGHMW8xWuVTydi2KO233VFiTNyF5hLJqpilHfmn8C8gPf+PS7dUT64YcXFbiMGZxS9pCSxL/Dxm/Jw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"prettier": "bin/prettier.cjs"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/prettier/prettier?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/prettier-plugin-organize-imports": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/prettier-plugin-organize-imports/-/prettier-plugin-organize-imports-4.3.0.tgz",
|
||||
"integrity": "sha512-FxFz0qFhyBsGdIsb697f/EkvHzi5SZOhWAjxcx2dLt+Q532bAlhswcXGYB1yzjZ69kW8UoadFBw7TyNwlq96Iw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"prettier": ">=2.0",
|
||||
"typescript": ">=2.9",
|
||||
"vue-tsc": "^2.1.0 || 3"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"vue-tsc": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/semver": {
|
||||
"version": "7.7.3",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz",
|
||||
"integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==",
|
||||
"license": "ISC",
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/strnum": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/strnum/-/strnum-2.1.2.tgz",
|
||||
"integrity": "sha512-l63NF9y/cLROq/yqKXSLtcMeeyOfnSQlfMSlzFt/K73oIaD8DGaQWd7Z34X9GPiKqP5rbSh84Hl4bOlLcjiSrQ==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/NaturalIntelligence"
|
||||
}
|
||||
],
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/tslib": {
|
||||
"version": "2.8.1",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
|
||||
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
|
||||
"license": "0BSD"
|
||||
},
|
||||
"node_modules/tunnel": {
|
||||
"version": "0.0.6",
|
||||
"resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
|
||||
"integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.6.11 <=0.7.0 || >=0.7.3"
|
||||
}
|
||||
},
|
||||
"node_modules/typescript": {
|
||||
"version": "6.0.3",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.3.tgz",
|
||||
"integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
"tsserver": "bin/tsserver"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.17"
|
||||
}
|
||||
},
|
||||
"node_modules/undici": {
|
||||
"version": "5.29.0",
|
||||
"resolved": "https://registry.npmjs.org/undici/-/undici-5.29.0.tgz",
|
||||
"integrity": "sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@fastify/busboy": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.0"
|
||||
}
|
||||
},
|
||||
"node_modules/undici-types": {
|
||||
"version": "7.16.0",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz",
|
||||
"integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
}
|
||||
}
|
||||
}
|
||||
36
package.json
Normal file
36
package.json
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
{
|
||||
"name": "github-action",
|
||||
"version": "4.0.0",
|
||||
"description": "Connect your GitHub Action workflow to Tailscale",
|
||||
"main": "dist/main.js",
|
||||
"engines": {
|
||||
"node": ">=24.0.0"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "ncc build src/main.ts -o dist && ncc build src/logout/logout.ts -o dist/logout"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/tailscale/github-action"
|
||||
},
|
||||
"author": "Lee Briggs, Tailscale Inc, & Contributors",
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"@actions/cache": "^5.0.2",
|
||||
"@actions/core": "^2.0.2",
|
||||
"@actions/exec": "^2.0.0",
|
||||
"@actions/tool-cache": "^3.0.0",
|
||||
"semver": "^7.7.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^24.10.2",
|
||||
"@vercel/ncc": "^0.38.3",
|
||||
"typescript": "^6.0.3",
|
||||
"prettier": "^3.8.3",
|
||||
"prettier-plugin-organize-imports": "^4.3.0"
|
||||
},
|
||||
"overrides": {
|
||||
"glob": "^10.3.10",
|
||||
"inflight": "npm:@isaacs/inflight@^1.0.6"
|
||||
}
|
||||
}
|
||||
92
src/logging.ts
Normal file
92
src/logging.ts
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
// Copyright (c) Lee Briggs, Tailscale Inc, & Contributors
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
import * as core from "@actions/core";
|
||||
import * as exec from "@actions/exec";
|
||||
import * as process from "process";
|
||||
|
||||
export type LogMode = "grouped" | "normal" | "quiet";
|
||||
|
||||
export class ExecError {
|
||||
msg: string;
|
||||
exitCode: number;
|
||||
stderr: string;
|
||||
|
||||
public constructor(msg: string, exitCode: number, stderr: string) {
|
||||
this.msg = msg;
|
||||
this.exitCode = exitCode;
|
||||
this.stderr = stderr;
|
||||
}
|
||||
|
||||
public toString(): string {
|
||||
return this.msg;
|
||||
}
|
||||
}
|
||||
|
||||
export function getLogMode(): LogMode {
|
||||
const logMode = core.getInput("log-mode") || "grouped";
|
||||
if (logMode !== "grouped" && logMode !== "normal" && logMode !== "quiet") {
|
||||
throw new Error(
|
||||
`Invalid log-mode "${logMode}". Expected "grouped", "normal", or "quiet".`,
|
||||
);
|
||||
}
|
||||
return logMode;
|
||||
}
|
||||
|
||||
export function logInfo(logMode: LogMode, message: string): void {
|
||||
if (logMode !== "quiet") {
|
||||
core.info(message);
|
||||
}
|
||||
}
|
||||
|
||||
export function logDebug(logMode: LogMode, message: string): void {
|
||||
if (logMode !== "quiet") {
|
||||
core.debug(message);
|
||||
}
|
||||
}
|
||||
|
||||
export async function withLogGroup<T>(
|
||||
logMode: LogMode,
|
||||
name: string,
|
||||
fn: () => Promise<T>,
|
||||
): Promise<T> {
|
||||
if (logMode !== "grouped") {
|
||||
return fn();
|
||||
}
|
||||
|
||||
core.startGroup(name);
|
||||
try {
|
||||
return await fn();
|
||||
} finally {
|
||||
core.endGroup();
|
||||
}
|
||||
}
|
||||
|
||||
export async function execCommand(
|
||||
commandLine: string,
|
||||
args?: string[],
|
||||
opts?: exec.ExecOptions & { label?: string; logMode?: LogMode },
|
||||
): Promise<exec.ExecOutput> {
|
||||
const { label, logMode = "normal", ...execOpts } = opts || {};
|
||||
if (label) {
|
||||
logInfo(logMode, `▶️ ${label}`);
|
||||
}
|
||||
|
||||
const silent = execOpts.silent || logMode === "quiet" || !core.isDebug();
|
||||
const out = await exec.getExecOutput(commandLine, args, {
|
||||
...execOpts,
|
||||
silent,
|
||||
ignoreReturnCode: true,
|
||||
});
|
||||
if (out.exitCode !== 0) {
|
||||
if (silent) {
|
||||
process.stderr.write(out.stderr);
|
||||
}
|
||||
throw new ExecError(
|
||||
`${commandLine} failed with exit code ${out.exitCode}`,
|
||||
out.exitCode,
|
||||
out.stderr,
|
||||
);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
111
src/logout/logout.ts
Normal file
111
src/logout/logout.ts
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
// Copyright (c) Lee Briggs, Tailscale Inc, & Contributors
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
import * as core from "@actions/core";
|
||||
import * as fs from "fs";
|
||||
import * as os from "os";
|
||||
import * as path from "path";
|
||||
import { execCommand, getLogMode, logInfo, withLogGroup } from "../logging";
|
||||
|
||||
const runnerWindows = "Windows";
|
||||
const runnerMacOS = "macOS";
|
||||
|
||||
async function logout(): Promise<void> {
|
||||
try {
|
||||
const runnerOS = process.env.RUNNER_OS || "";
|
||||
const logMode = getLogMode();
|
||||
|
||||
await withLogGroup(logMode, "Cleaning up Tailscale", async () => {
|
||||
if (runnerOS === runnerMacOS) {
|
||||
// The below is required to allow GitHub's post job cleanup to complete.
|
||||
logInfo(logMode, "Resetting DNS settings on macOS");
|
||||
await execCommand(
|
||||
"networksetup",
|
||||
["-setdnsservers", "Ethernet", "Empty"],
|
||||
{ logMode },
|
||||
);
|
||||
await execCommand(
|
||||
"networksetup",
|
||||
["-setsearchdomains", "Ethernet", "Empty"],
|
||||
{ logMode },
|
||||
);
|
||||
}
|
||||
|
||||
logInfo(logMode, "🔄 Logging out of Tailscale...");
|
||||
|
||||
// Check if tailscale is available first
|
||||
try {
|
||||
await execCommand("tailscale", ["--version"], {
|
||||
logMode,
|
||||
silent: true,
|
||||
});
|
||||
|
||||
// Determine the correct command based on OS
|
||||
let execArgs: string[];
|
||||
if (runnerOS === runnerWindows) {
|
||||
execArgs = ["tailscale", "logout"];
|
||||
} else {
|
||||
// Linux and macOS - use system-installed binary with sudo
|
||||
execArgs = ["sudo", "-E", "tailscale", "logout"];
|
||||
}
|
||||
|
||||
logInfo(logMode, `Running: ${execArgs.join(" ")}`);
|
||||
|
||||
try {
|
||||
await execCommand(execArgs[0], execArgs.slice(1), { logMode });
|
||||
logInfo(logMode, "✅ Successfully logged out of Tailscale");
|
||||
} catch (error) {
|
||||
// Don't fail the action if logout fails - it's just cleanup
|
||||
core.warning(`Failed to logout from Tailscale: ${error}`);
|
||||
logInfo(
|
||||
logMode,
|
||||
"Your ephemeral node will eventually be cleaned up by Tailscale",
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
logInfo(
|
||||
logMode,
|
||||
"Tailscale not found or not accessible, skipping logout",
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
logInfo(logMode, "Stopping tailscale");
|
||||
try {
|
||||
if (runnerOS === runnerWindows) {
|
||||
await execCommand("net", ["stop", "Tailscale"], { logMode });
|
||||
await execCommand("taskkill", ["/F", "/IM", "tailscale-ipn.exe"], {
|
||||
logMode,
|
||||
});
|
||||
} else {
|
||||
const xdgRuntimeDir =
|
||||
process.env.XDG_RUNTIME_DIR ||
|
||||
process.env.XDG_CACHE_HOME ||
|
||||
path.join(os.homedir(), ".cache");
|
||||
const pid = fs
|
||||
.readFileSync(path.join(xdgRuntimeDir, "tailscaled.pid"))
|
||||
.toString();
|
||||
if (pid === "") {
|
||||
throw new Error("pid file empty");
|
||||
}
|
||||
// The pid is actually the pid of the `sudo` parent of tailscaled, so use pkill -P to kill children of that parent
|
||||
await execCommand("sudo", ["pkill", "-P", pid], { logMode });
|
||||
// Clean up DNS and routes.
|
||||
await execCommand("sudo", ["tailscaled", "--cleanup"], { logMode });
|
||||
}
|
||||
logInfo(logMode, "✅ Stopped tailscale");
|
||||
} catch (error) {
|
||||
core.warning(`Failed to stop tailscale: ${error}`);
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
// Don't fail the action for post-cleanup issues
|
||||
core.warning(`Post-action cleanup error: ${error}`);
|
||||
}
|
||||
}
|
||||
|
||||
// Run the logout function
|
||||
logout().catch((error) => {
|
||||
// Even if logout fails, don't fail the action
|
||||
core.warning(`Logout process failed: ${error}`);
|
||||
});
|
||||
1078
src/main.ts
Normal file
1078
src/main.ts
Normal file
File diff suppressed because it is too large
Load diff
63
tsconfig.json
Normal file
63
tsconfig.json
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
/* Basic Options */
|
||||
// "incremental": true, /* Enable incremental compilation */
|
||||
"target": "ES2020", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */
|
||||
"module": "NodeNext", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
|
||||
// "allowJs": true, /* Allow javascript files to be compiled. */
|
||||
// "checkJs": true, /* Report errors in .js files. */
|
||||
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
|
||||
// "declaration": true, /* Generates corresponding '.d.ts' file. */
|
||||
// "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
|
||||
// "sourceMap": true, /* Generates corresponding '.map' file. */
|
||||
// "outFile": "./", /* Concatenate and emit output to single file. */
|
||||
"outDir": "./lib", /* Redirect output structure to the directory. */
|
||||
"rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
|
||||
// "composite": true, /* Enable project compilation */
|
||||
// "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */
|
||||
// "removeComments": true, /* Do not emit comments to output. */
|
||||
// "noEmit": true, /* Do not emit outputs. */
|
||||
// "importHelpers": true, /* Import emit helpers from 'tslib'. */
|
||||
// "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
|
||||
// "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
|
||||
|
||||
/* Strict Type-Checking Options */
|
||||
"strict": true, /* Enable all strict type-checking options. */
|
||||
"noImplicitAny": false, /* Raise error on expressions and declarations with an implied 'any' type. */
|
||||
// "strictNullChecks": true, /* Enable strict null checks. */
|
||||
// "strictFunctionTypes": true, /* Enable strict checking of function types. */
|
||||
// "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
|
||||
// "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
|
||||
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
|
||||
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
|
||||
|
||||
/* Additional Checks */
|
||||
// "noUnusedLocals": true, /* Report errors on unused locals. */
|
||||
// "noUnusedParameters": true, /* Report errors on unused parameters. */
|
||||
// "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
|
||||
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
|
||||
|
||||
/* Module Resolution Options */
|
||||
"moduleResolution": "NodeNext", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
|
||||
// "baseUrl": "./", /* Base directory to resolve non-absolute module names. */
|
||||
// "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
|
||||
// "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
|
||||
// "typeRoots": [], /* List of folders to include type definitions from. */
|
||||
"types": ["node"], /* Type declaration files to be included in compilation. */
|
||||
// "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
|
||||
"esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
|
||||
// "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
|
||||
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
|
||||
|
||||
/* Source Map Options */
|
||||
// "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
|
||||
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
|
||||
// "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
|
||||
// "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
|
||||
|
||||
/* Experimental Options */
|
||||
// "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
|
||||
// "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
|
||||
},
|
||||
"exclude": ["node_modules", "**/*.test.ts"]
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue