name: Integration Tests # To debug locally on a branch, and when needing secrets # change this to include `push` so the build is ran on # the main repository. on: [pull_request] concurrency: group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} cancel-in-progress: true jobs: integration-test: runs-on: ubuntu-latest strategy: fail-fast: false matrix: test: - TestACLHostsInNetMapTable - TestACLAllowUser80Dst - TestACLDenyAllPort80 - TestACLAllowUserDst - TestACLAllowStarDst - TestACLNamedHostsCanReachBySubnet - TestACLNamedHostsCanReach - TestACLDevice1CanAccessDevice2 - TestPolicyUpdateWhileRunningWithCLIInDatabase - TestOIDCAuthenticationPingAll - TestOIDCExpireNodesBasedOnTokenExpiry - TestOIDC024UserCreation - TestAuthWebFlowAuthenticationPingAll - TestAuthWebFlowLogoutAndRelogin - TestUserCommand - TestPreAuthKeyCommand - TestPreAuthKeyCommandWithoutExpiry - TestPreAuthKeyCommandReusableEphemeral - TestPreAuthKeyCorrectUserLoggedInCommand - TestApiKeyCommand - TestNodeTagCommand - TestNodeAdvertiseTagCommand - TestNodeCommand - TestNodeExpireCommand - TestNodeRenameCommand - TestNodeMoveCommand - TestPolicyCommand - TestPolicyBrokenConfigCommand - TestDERPVerifyEndpoint - TestResolveMagicDNS - TestValidateResolvConf - TestDERPServerScenario - TestDERPServerWebsocketScenario - TestPingAllByIP - TestPingAllByIPPublicDERP - TestAuthKeyLogoutAndRelogin - TestEphemeral - TestEphemeralInAlternateTimezone - TestEphemeral2006DeletedTooQuickly - TestPingAllByHostname - TestTaildrop - TestUpdateHostnameFromClient - TestExpireNode - TestNodeOnlineStatus - TestPingAllByIPManyUpDown - Test2118DeletingOnlineNodePanics - TestEnablingRoutes - TestHASubnetRouterFailover - TestEnableDisableAutoApprovedRoute - TestAutoApprovedSubRoute2068 - TestSubnetRouteACL - TestHeadscale - TestCreateTailscale - TestTailscaleNodesJoiningHeadcale - TestSSHOneUserToAll - TestSSHMultipleUsersAllToAll - TestSSHNoSSHConfigured - TestSSHIsBlockedInACL - TestSSHUserOnlyIsolation database: [postgres, sqlite] env: # Github does not allow us to access secrets in pull requests, # so this env var is used to check if we have the secret or not. # If we have the secrets, meaning we are running on push in a fork, # there might be secrets available for more debugging. # If TS_OAUTH_CLIENT_ID and TS_OAUTH_SECRET is set, then the job # will join a debug tailscale network, set up SSH and a tmux session. # The SSH will be configured to use the SSH key of the Github user # that triggered the build. HAS_TAILSCALE_SECRET: ${{ secrets.TS_OAUTH_CLIENT_ID }} steps: - uses: actions/checkout@v4 with: fetch-depth: 2 - name: Get changed files id: changed-files uses: dorny/paths-filter@v3 with: filters: | files: - '*.nix' - 'go.*' - '**/*.go' - 'integration_test/' - 'config-example.yaml' - name: Tailscale if: ${{ env.HAS_TAILSCALE_SECRET }} uses: tailscale/github-action@v2 with: oauth-client-id: ${{ secrets.TS_OAUTH_CLIENT_ID }} oauth-secret: ${{ secrets.TS_OAUTH_SECRET }} tags: tag:gh - name: Setup SSH server for Actor if: ${{ env.HAS_TAILSCALE_SECRET }} uses: alexellis/setup-sshd-actor@master - uses: DeterminateSystems/nix-installer-action@main if: steps.changed-files.outputs.files == 'true' - uses: DeterminateSystems/magic-nix-cache-action@main if: steps.changed-files.outputs.files == 'true' - uses: satackey/action-docker-layer-caching@main if: steps.changed-files.outputs.files == 'true' continue-on-error: true - name: Run Integration Test uses: Wandalen/wretry.action@master if: steps.changed-files.outputs.files == 'true' env: USE_POSTGRES: ${{ matrix.database == 'postgres' && '1' || '0' }} with: attempt_limit: 5 command: | nix develop --command -- docker run \ --tty --rm \ --volume ~/.cache/hs-integration-go:/go \ --name headscale-test-suite \ --volume $PWD:$PWD -w $PWD/integration \ --volume /var/run/docker.sock:/var/run/docker.sock \ --volume $PWD/control_logs:/tmp/control \ --env HEADSCALE_INTEGRATION_POSTGRES=${{env.USE_POSTGRES}} \ golang:1 \ go run gotest.tools/gotestsum@latest -- ./... \ -failfast \ -timeout 120m \ -parallel 1 \ -run "^${{ matrix.test }}$" - uses: actions/upload-artifact@v4 if: always() && steps.changed-files.outputs.files == 'true' with: name: ${{ matrix.test }}-${{matrix.database}}-logs path: "control_logs/*.log" - uses: actions/upload-artifact@v4 if: always() && steps.changed-files.outputs.files == 'true' with: name: ${{ matrix.test }}-${{matrix.database}}-pprof path: "control_logs/*.pprof.tar" - name: Setup a blocking tmux session if: ${{ env.HAS_TAILSCALE_SECRET }} uses: alexellis/block-with-tmux-action@master