Skip to content

Commit fb33734

Browse files
committed
stop pinging hosts as soon as any connectivity is available
Even if we just have DERP connectivity, stop pinging so that action can continue sooner. Updates tailscale/corp#32862 Signed-off-by: Percy Wegmann <percy@tailscale.com>
1 parent 9362fda commit fb33734

3 files changed

Lines changed: 73 additions & 59 deletions

File tree

.github/workflows/test.yml

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ on:
99

1010
jobs:
1111
# Matrix test for all supported platforms and architectures
12-
12+
1313
integration-tests:
1414
name: ${{ matrix.os }} (${{ matrix.arch }}) tailscale-${{ matrix.version }}
1515
strategy:
@@ -34,13 +34,13 @@ jobs:
3434
runner-os: Linux
3535
arch: amd64
3636
version: 1.82.0
37-
37+
3838
# Linux tests (ARM64)
3939
- os: ubuntu-24.04-arm
4040
runner-os: Linux
4141
arch: arm64
4242
version: latest
43-
43+
4444
# Windows tests (AMD64)
4545
- os: windows-latest
4646
runner-os: Windows
@@ -52,46 +52,46 @@ jobs:
5252
runner-os: Windows
5353
arch: amd64
5454
version: unstable
55-
55+
5656
# Windows tests (ARM64)
5757
- os: windows-11-arm
5858
runner-os: Windows
5959
arch: arm64
6060
version: latest
61-
61+
6262
# macOS intel
6363
- os: macos-13
6464
runner-os: macOS
6565
arch: amd64
6666
version: latest
6767
ping: 100.99.0.2 # hostnames aren't resolving on MacOS, just ping IP lax-pve.pineapplefish.ts.net,lax-pve
68-
68+
6969
# macOS ARM
7070
- os: macos-14
7171
runner-os: macOS
7272
arch: arm64
7373
version: latest
74-
74+
7575
runs-on: ${{ matrix.os }}
76-
76+
7777
steps:
7878
- name: Checkout
7979
uses: actions/checkout@v4
80-
80+
8181
- name: Setup Node.js
8282
uses: actions/setup-node@v4
8383
with:
84-
node-version: '20'
85-
cache: 'npm'
86-
84+
node-version: "20"
85+
cache: "npm"
86+
8787
- name: Install Dependencies
8888
run: npm ci
89-
89+
9090
- name: Build Action
9191
run: npm run build
92-
92+
9393
# Test with OAuth authentication
94-
- name: Test Tailscale Setup (OAuth)
94+
- name: Test Action
9595
id: tailscale-oauth
9696
uses: ./
9797
with:
@@ -103,7 +103,7 @@ jobs:
103103
timeout: "5m"
104104
retry: 3
105105
ping: "${{ matrix.ping }}"
106-
106+
107107
# Test Tailscale status command
108108
- name: Check Tailscale Status
109109
if: steps.tailscale-oauth.outcome == 'success'
@@ -119,4 +119,3 @@ jobs:
119119
tailscale version
120120
fi
121121
shell: bash
122-

dist/index.js

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -41123,6 +41123,7 @@ const fs = __importStar(__nccwpck_require__(79896));
4112341123
const http = __importStar(__nccwpck_require__(58611));
4112441124
const os = __importStar(__nccwpck_require__(70857));
4112541125
const path = __importStar(__nccwpck_require__(16928));
41126+
const promises_1 = __nccwpck_require__(16460);
4112641127
const cmdTailscale = "tailscale";
4112741128
const cmdTailscaleFullPath = "/usr/local/bin/tailscale";
4112841129
const cmdTailscaled = "tailscaled";
@@ -41241,7 +41242,7 @@ async function run() {
4124141242
core.debug(`Tailscale status: ${JSON.stringify(status)}`);
4124241243
if (status.BackendState === "Running") {
4124341244
core.info("✅ Tailscale is running and connected!");
41244-
pingHostsIfNecessary(config);
41245+
await pingHostsIfNecessary(config);
4124541246
// Explicitly exit to prevent hanging
4124641247
process.exit(0);
4124741248
}
@@ -41254,7 +41255,7 @@ async function run() {
4125441255
core.warning(`Failed to get Tailscale status: ${err}`);
4125541256
// Still exit successfully since the main connection worked
4125641257
core.info("✅ Tailscale daemon is connected!");
41257-
pingHostsIfNecessary(config);
41258+
await pingHostsIfNecessary(config);
4125841259
// Explicitly exit to prevent hanging
4125941260
process.exit(0);
4126041261
}
@@ -41264,31 +41265,33 @@ async function run() {
4126441265
}
4126541266
}
4126641267
async function pingHostsIfNecessary(config) {
41267-
const directConnectionWarning = "direct connection not established";
4126841268
if (config.pingHosts.length == 0) {
4126941269
return;
4127041270
}
41271-
core.info(`Will ping hosts ${config.pingHosts.join(",")} up to 3 minutes in order to check connectivity`);
41271+
core.info(`Will ping hosts ${config.pingHosts.join(",")} up to 3 minutes each in order to check connectivity`);
4127241272
for (const host of config.pingHosts) {
41273-
core.info(`Pinging host ${host}`);
41274-
let result = await exec.getExecOutput(cmdTailscale, [
41275-
"ping",
41276-
"-c",
41277-
"36",
41278-
host,
41279-
]);
41280-
if (result.exitCode === 0) {
41281-
core.info(`✅ Ping host ${host} responded!`);
41273+
await pingHost(host);
41274+
}
41275+
}
41276+
async function pingHost(host) {
41277+
core.info(`Pinging host ${host}`);
41278+
for (let i = 0; i <= 36; i++) {
41279+
if (i < 0) {
41280+
// wait 5 seconds before pinging
41281+
(0, promises_1.setTimeout)(5000);
4128241282
}
41283-
else if (result.stderr.includes(directConnectionWarning) ||
41284-
result.stdout.includes(directConnectionWarning)) {
41285-
core.warning(`⚠️ Ping host ${host} reachable only via DERP, not direct connection.`);
41283+
let result = await exec.getExecOutput(cmdTailscale, ["ping", "-c", "1", host], { ignoreReturnCode: true });
41284+
if (result.exitCode === 0) {
41285+
core.info(`✅ Ping host ${host} reachable via direct connection!`);
41286+
return;
4128641287
}
41287-
else {
41288-
core.setFailed(`❌ Ping host ${host} did not respond`);
41289-
process.exit(1);
41288+
else if (result.stderr.includes("direct connection not established")) {
41289+
core.info(`✅ Ping host ${host} reachable via DERP!`);
41290+
return;
4129041291
}
4129141292
}
41293+
core.setFailed(`❌ Ping host ${host} did not respond`);
41294+
process.exit(1);
4129241295
}
4129341296
async function getInputs() {
4129441297
let ping = core.getInput("ping");
@@ -42006,6 +42009,14 @@ module.exports = require("timers");
4200642009

4200742010
/***/ }),
4200842011

42012+
/***/ 16460:
42013+
/***/ ((module) => {
42014+
42015+
"use strict";
42016+
module.exports = require("timers/promises");
42017+
42018+
/***/ }),
42019+
4200942020
/***/ 64756:
4201042021
/***/ ((module) => {
4201142022

src/main.ts

Lines changed: 27 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import * as fs from "fs";
88
import * as http from "http";
99
import * as os from "os";
1010
import * as path from "path";
11+
import { setTimeout as wait } from "timers/promises";
1112

1213
const cmdTailscale = "tailscale";
1314
const cmdTailscaleFullPath = "/usr/local/bin/tailscale";
@@ -167,7 +168,7 @@ async function run(): Promise<void> {
167168
core.debug(`Tailscale status: ${JSON.stringify(status)}`);
168169
if (status.BackendState === "Running") {
169170
core.info("✅ Tailscale is running and connected!");
170-
pingHostsIfNecessary(config);
171+
await pingHostsIfNecessary(config);
171172
// Explicitly exit to prevent hanging
172173
process.exit(0);
173174
} else {
@@ -178,7 +179,7 @@ async function run(): Promise<void> {
178179
core.warning(`Failed to get Tailscale status: ${err}`);
179180
// Still exit successfully since the main connection worked
180181
core.info("✅ Tailscale daemon is connected!");
181-
pingHostsIfNecessary(config);
182+
await pingHostsIfNecessary(config);
182183
// Explicitly exit to prevent hanging
183184
process.exit(0);
184185
}
@@ -188,39 +189,42 @@ async function run(): Promise<void> {
188189
}
189190

190191
async function pingHostsIfNecessary(config: TailscaleConfig): Promise<void> {
191-
const directConnectionWarning = "direct connection not established";
192-
193192
if (config.pingHosts.length == 0) {
194193
return;
195194
}
196195

197196
core.info(
198197
`Will ping hosts ${config.pingHosts.join(
199198
","
200-
)} up to 3 minutes in order to check connectivity`
199+
)} up to 3 minutes each in order to check connectivity`
201200
);
202201
for (const host of config.pingHosts) {
203-
core.info(`Pinging host ${host}`);
204-
let result = await exec.getExecOutput(cmdTailscale, [
205-
"ping",
206-
"-c",
207-
"36",
208-
host,
209-
]);
202+
await pingHost(host);
203+
}
204+
}
205+
206+
async function pingHost(host: string): Promise<void> {
207+
core.info(`Pinging host ${host}`);
208+
for (let i = 0; i <= 36; i++) {
209+
if (i < 0) {
210+
// wait 5 seconds before pinging
211+
wait(5000);
212+
}
213+
let result = await exec.getExecOutput(
214+
cmdTailscale,
215+
["ping", "-c", "1", host],
216+
{ ignoreReturnCode: true }
217+
);
210218
if (result.exitCode === 0) {
211-
core.info(`✅ Ping host ${host} responded!`);
212-
} else if (
213-
result.stderr.includes(directConnectionWarning) ||
214-
result.stdout.includes(directConnectionWarning)
215-
) {
216-
core.warning(
217-
`⚠️ Ping host ${host} reachable only via DERP, not direct connection.`
218-
);
219-
} else {
220-
core.setFailed(`❌ Ping host ${host} did not respond`);
221-
process.exit(1);
219+
core.info(`✅ Ping host ${host} reachable via direct connection!`);
220+
return;
221+
} else if (result.stderr.includes("direct connection not established")) {
222+
core.info(`✅ Ping host ${host} reachable via DERP!`);
223+
return;
222224
}
223225
}
226+
core.setFailed(`❌ Ping host ${host} did not respond`);
227+
process.exit(1);
224228
}
225229

226230
async function getInputs(): Promise<TailscaleConfig> {

0 commit comments

Comments
 (0)