mirror of
https://github.com/tailscale/github-action.git
synced 2026-08-20 17:39:23 +00:00
278 lines
11 KiB
YAML
278 lines
11 KiB
YAML
# Copyright (c) Tailscale Inc & AUTHORS
|
|
# 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.'
|
|
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.'
|
|
required: false
|
|
version:
|
|
description: 'Tailscale version to use. Specify `latest` to use the latest stable version.'
|
|
required: true
|
|
default: '1.82.0'
|
|
sha256sum:
|
|
description: 'Expected SHA256 checksum of the tarball.'
|
|
required: false
|
|
default: ''
|
|
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.'
|
|
required: false
|
|
default: ''
|
|
statedir:
|
|
description: 'Optional state directory to use (if unset, memory state is used)'
|
|
required: false
|
|
default: ''
|
|
timeout:
|
|
description: 'Timeout for `tailscale up`'
|
|
required: false
|
|
default: '2m'
|
|
use-cache:
|
|
description: 'Whether to cache the Tailscale binaries (Linux/macOS) or installer (Windows)'
|
|
required: false
|
|
default: 'false'
|
|
runs:
|
|
using: 'composite'
|
|
steps:
|
|
- name: Check Runner OS
|
|
if: ${{ runner.os != 'Linux' && runner.os != 'Windows' && runner.os != 'macOS'}}
|
|
shell: bash
|
|
run: |
|
|
echo "::error title=⛔ error hint::Support Linux, Windows, and macOS 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: Set Resolved Version
|
|
shell: bash
|
|
run: |
|
|
VERSION=${{ inputs.version }}
|
|
if [ "$VERSION" = "latest" ]; then
|
|
RESOLVED_VERSION=$(curl -H user-agent:tailscale-github-action -s "https://pkgs.tailscale.com/stable/?mode=json" | jq -r .Version)
|
|
else
|
|
RESOLVED_VERSION=$VERSION
|
|
fi
|
|
echo "RESOLVED_VERSION=$RESOLVED_VERSION" >> $GITHUB_ENV
|
|
echo "Resolved Tailscale version: $RESOLVED_VERSION"
|
|
- name: Set Tailscale Architecture - Linux
|
|
if: ${{ runner.os == 'Linux' }}
|
|
shell: bash
|
|
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"
|
|
else
|
|
TS_ARCH="amd64"
|
|
fi
|
|
echo "TS_ARCH=$TS_ARCH" >> $GITHUB_ENV
|
|
|
|
- name: Set Tailscale Architecture - Windows
|
|
if: ${{ runner.os == 'Windows' }}
|
|
shell: bash
|
|
run: |
|
|
if [ ${{ runner.arch }} = "ARM64" ]; then
|
|
TS_ARCH="arm64"
|
|
elif [ ${{ runner.arch }} = "X86" ]; then
|
|
TS_ARCH="x86"
|
|
else
|
|
TS_ARCH="amd64"
|
|
fi
|
|
echo "TS_ARCH=$TS_ARCH" >> $GITHUB_ENV
|
|
|
|
- name: Set SHA256 - Linux
|
|
if: ${{ runner.os == 'Linux' }}
|
|
shell: bash
|
|
run: |
|
|
MINOR=$(echo "$RESOLVED_VERSION" | awk -F '.' {'print $2'})
|
|
if [ $((MINOR % 2)) -eq 0 ]; then
|
|
URL="https://pkgs.tailscale.com/stable/tailscale_${RESOLVED_VERSION}_${TS_ARCH}.tgz.sha256"
|
|
else
|
|
URL="https://pkgs.tailscale.com/unstable/tailscale_${RESOLVED_VERSION}_${TS_ARCH}.tgz.sha256"
|
|
fi
|
|
|
|
if [[ "${{ inputs.sha256sum }}" ]]; then
|
|
SHA256SUM="${{ inputs.sha256sum }}"
|
|
else
|
|
SHA256SUM="$(curl -H user-agent:tailscale-github-action -L "${URL}" --fail)"
|
|
fi
|
|
echo "SHA256SUM=$SHA256SUM" >> $GITHUB_ENV
|
|
|
|
- name: Cache Tailscale Binary - Linux
|
|
if: ${{ inputs.use-cache == 'true' && runner.os == 'Linux' }}
|
|
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
|
|
id: cache-tailscale-linux
|
|
with:
|
|
path: tailscale.tgz
|
|
key: ${{ runner.os }}-tailscale-${{ env.RESOLVED_VERSION }}-${{ env.TS_ARCH }}-${{ env.SHA256SUM }}
|
|
|
|
- name: Download Tailscale - Linux
|
|
if: ${{ runner.os == 'Linux' && (inputs.use-cache != 'true' || steps.cache-tailscale-linux.outputs.cache-hit != 'true') }}
|
|
shell: bash
|
|
run: |
|
|
MINOR=$(echo "$RESOLVED_VERSION" | awk -F '.' {'print $2'})
|
|
if [ $((MINOR % 2)) -eq 0 ]; then
|
|
URL="https://pkgs.tailscale.com/stable/tailscale_${RESOLVED_VERSION}_${TS_ARCH}.tgz"
|
|
else
|
|
URL="https://pkgs.tailscale.com/unstable/tailscale_${RESOLVED_VERSION}_${TS_ARCH}.tgz"
|
|
fi
|
|
echo "Downloading $URL"
|
|
curl -H user-agent:tailscale-github-action -L "$URL" -o tailscale.tgz --max-time 300 --fail
|
|
echo "Expected sha256: $SHA256SUM"
|
|
echo "Actual sha256: $(sha256sum tailscale.tgz)"
|
|
echo "$SHA256SUM tailscale.tgz" | sha256sum -c
|
|
|
|
- name: Install Tailscale - Linux
|
|
if: ${{ runner.os == 'Linux' }}
|
|
shell: bash
|
|
run: |
|
|
tar -C /tmp -xzf tailscale.tgz
|
|
TSPATH=/tmp/tailscale_${RESOLVED_VERSION}_${TS_ARCH}
|
|
sudo mv "${TSPATH}/tailscale" "${TSPATH}/tailscaled" /usr/bin
|
|
|
|
- name: Set SHA256 - Windows
|
|
if: ${{ runner.os == 'Windows' }}
|
|
shell: bash
|
|
run: |
|
|
MINOR=$(echo "$RESOLVED_VERSION" | awk -F '.' {'print $2'})
|
|
if [ $((MINOR % 2)) -eq 0 ]; then
|
|
URL="https://pkgs.tailscale.com/stable/tailscale-setup-${RESOLVED_VERSION}-${TS_ARCH}.msi.sha256"
|
|
else
|
|
URL="https://pkgs.tailscale.com/unstable/tailscale-setup-${RESOLVED_VERSION}-${TS_ARCH}.msi.sha256"
|
|
fi
|
|
|
|
if [[ "${{ inputs.sha256sum }}" ]]; then
|
|
SHA256SUM="${{ inputs.sha256sum }}"
|
|
else
|
|
SHA256SUM="$(curl -H user-agent:tailscale-github-action -L "${URL}" --fail)"
|
|
fi
|
|
echo "SHA256SUM=$SHA256SUM" >> $GITHUB_ENV
|
|
|
|
- name: Cache Tailscale Binary - Windows
|
|
if: ${{ inputs.use-cache == 'true' && runner.os == 'Windows' }}
|
|
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
|
|
id: cache-tailscale-windows
|
|
with:
|
|
path: tailscale.msi
|
|
key: ${{ runner.os }}-tailscale-${{ env.RESOLVED_VERSION }}-${{ env.TS_ARCH }}-${{ env.SHA256SUM }}
|
|
|
|
- name: Download Tailscale - Windows
|
|
if: ${{ runner.os == 'Windows' && (inputs.use-cache != 'true' || steps.cache-tailscale-windows.outputs.cache-hit != 'true') }}
|
|
shell: bash
|
|
run: |
|
|
MINOR=$(echo "$RESOLVED_VERSION" | awk -F '.' {'print $2'})
|
|
if [ $((MINOR % 2)) -eq 0 ]; then
|
|
URL="https://pkgs.tailscale.com/stable/tailscale-setup-${RESOLVED_VERSION}-${TS_ARCH}.msi"
|
|
else
|
|
URL="https://pkgs.tailscale.com/unstable/tailscale-setup-${RESOLVED_VERSION}-${TS_ARCH}.msi"
|
|
fi
|
|
echo "Downloading $URL"
|
|
curl -H user-agent:tailscale-github-action -L "$URL" -o tailscale.msi --max-time 300 --fail
|
|
echo "Expected sha256: $SHA256SUM"
|
|
echo "Actual sha256: $(sha256sum tailscale.msi)"
|
|
echo "$SHA256SUM tailscale.msi" | sha256sum -c
|
|
- name: Install Tailscale - Windows
|
|
if: ${{ runner.os == 'Windows' }}
|
|
shell: pwsh
|
|
run: |
|
|
Start-Process "C:\Windows\System32\msiexec.exe" -Wait -ArgumentList @('/quiet', '/l*v tailscale.log', '/i', 'tailscale.msi')
|
|
Add-Content $env:GITHUB_PATH "C:\Program Files\Tailscale\"
|
|
- name: Checkout Tailscale repo - macOS
|
|
id: checkout-tailscale-macos
|
|
if: ${{ runner.os == 'macOS' }}
|
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
|
with:
|
|
repository: tailscale/tailscale
|
|
path: ${{ github.workspace }}/tailscale
|
|
ref: v${{ env.RESOLVED_VERSION }}
|
|
- name: Cache Tailscale - macOS
|
|
if: ${{ inputs.use-cache == 'true' && runner.os == 'macOS' }}
|
|
id: cache-tailscale-macos
|
|
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
|
|
with:
|
|
path: |
|
|
/usr/local/bin/tailscale
|
|
/usr/local/bin/tailscaled
|
|
key: ${{ runner.os }}-tailscale-${{ env.RESOLVED_VERSION }}-${{ runner.arch }}-${{ steps.checkout-tailscale-macos.outputs.commit }}
|
|
- name: Build Tailscale binaries - macOS
|
|
if: ${{ runner.os == 'macOS' && (inputs.use-cache != 'true' || steps.cache-tailscale-macos.outputs.cache-hit != 'true') }}
|
|
shell: bash
|
|
run: |
|
|
cd tailscale
|
|
export TS_USE_TOOLCHAIN=1
|
|
./build_dist.sh ./cmd/tailscale
|
|
./build_dist.sh ./cmd/tailscaled
|
|
sudo mv tailscale tailscaled /usr/local/bin
|
|
- name: Install timeout - macOS
|
|
if: ${{ runner.os == 'macOS' }}
|
|
shell: bash
|
|
run:
|
|
brew install coreutils # for 'timeout'
|
|
- name: Start Tailscale Daemon - non-Windows
|
|
if: ${{ runner.os != 'Windows' }}
|
|
shell: bash
|
|
env:
|
|
ADDITIONAL_DAEMON_ARGS: ${{ inputs.tailscaled-args }}
|
|
STATEDIR: ${{ inputs.statedir }}
|
|
run: |
|
|
if [ "$STATEDIR" == "" ]; then
|
|
STATE_ARGS="--state=mem:"
|
|
else
|
|
STATE_ARGS="--statedir=${STATEDIR}"
|
|
mkdir -p "$STATEDIR"
|
|
fi
|
|
sudo -E tailscaled ${STATE_ARGS} ${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:
|
|
ADDITIONAL_ARGS: ${{ inputs.args }}
|
|
HOSTNAME: ${{ inputs.hostname }}
|
|
TAILSCALE_AUTHKEY: ${{ inputs.authkey }}
|
|
TIMEOUT: ${{ inputs.timeout }}
|
|
run: |
|
|
if [ -z "${HOSTNAME}" ]; then
|
|
if [ "${{ runner.os }}" == "Windows" ]; then
|
|
HOSTNAME="github-$COMPUTERNAME"
|
|
else
|
|
HOSTNAME="github-$(hostname)"
|
|
fi
|
|
fi
|
|
if [ -n "${{ inputs['oauth-secret'] }}" ]; then
|
|
TAILSCALE_AUTHKEY="${{ inputs['oauth-secret'] }}?preauthorized=true&ephemeral=true"
|
|
TAGS_ARG="--advertise-tags=${{ inputs.tags }}"
|
|
fi
|
|
if [ "${{ runner.os }}" != "Windows" ]; then
|
|
MAYBE_SUDO="sudo -E"
|
|
fi
|
|
timeout --verbose --kill-after=1s ${TIMEOUT} ${MAYBE_SUDO} tailscale up ${TAGS_ARG} --authkey=${TAILSCALE_AUTHKEY} --hostname=${HOSTNAME} --accept-routes ${ADDITIONAL_ARGS}
|