mirror of
https://github.com/projectdiscovery/nuclei.git
synced 2026-11-09 04:09:43 -10:00
Compare commits
16
Commits
dev
...
ci-faster-checks
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
41665ef78f | ||
|
|
672730567e | ||
|
|
e9f854161b | ||
|
|
c020a69f4e | ||
|
|
c8a98159ab | ||
|
|
6594a4e9d9 | ||
|
|
eddbded1d4 | ||
|
|
79ab2eff84 | ||
|
|
4a59c20833 | ||
|
|
8dd8ee9f9e | ||
|
|
2b04783ed1 | ||
|
|
7dbf468972 | ||
|
|
d2af651ca5 | ||
|
|
e8c96ed4a0 | ||
|
|
81a72c4f8a | ||
|
|
28e8f47c6e |
No files matched your search
@@ -54,6 +54,17 @@ jobs:
|
||||
misc-packages: 'false'
|
||||
docker-images: 'false'
|
||||
tools-cache: 'false'
|
||||
# Windows Defender's real-time scan of Go's many small build artifacts is a
|
||||
# heavy tax on the runner; exclude the build/module caches, the workspace,
|
||||
# and the Go toolchain processes so compile/test I/O isn't scanned.
|
||||
- name: "Defender exclusions (Windows Go speedup)"
|
||||
if: runner.os == 'Windows'
|
||||
shell: pwsh
|
||||
run: |
|
||||
$paths = @("$(go env GOCACHE)", "$(go env GOMODCACHE)", "$env:GITHUB_WORKSPACE", "$env:RUNNER_TEMP")
|
||||
Add-MpPreference -ExclusionPath $paths -ErrorAction SilentlyContinue
|
||||
Add-MpPreference -ExclusionProcess "go.exe","compile.exe","link.exe","cgo.exe","gcc.exe","git.exe","nuclei.exe","nuclei.test.exe","python.exe" -ErrorAction SilentlyContinue
|
||||
Write-Host "Defender exclusions applied (best-effort)"
|
||||
- run: make build
|
||||
# The data-race detector is OS-independent, so we only pay its ~2-3x cost
|
||||
# on ubuntu; windows/macOS run the same suite without instrumentation.
|
||||
@@ -85,7 +96,7 @@ jobs:
|
||||
|
||||
sdk:
|
||||
name: "Run example SDK"
|
||||
needs: ["tests"]
|
||||
needs: ["lint"]
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
GITHUB_TOKEN: "${{ github.token }}"
|
||||
@@ -106,9 +117,12 @@ jobs:
|
||||
|
||||
integration:
|
||||
name: "Integration tests"
|
||||
needs: ["tests"]
|
||||
needs: ["lint"]
|
||||
env:
|
||||
GITHUB_TOKEN: "${{ github.token }}"
|
||||
# The suite semaphore defaults to min(GOMAXPROCS,4); integration cases are
|
||||
# I/O-bound (loopback servers), so oversubscribe to speed the slow cells.
|
||||
PARALLELISM: "8"
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
@@ -119,6 +133,14 @@ jobs:
|
||||
- uses: projectdiscovery/actions/setup/python@v1
|
||||
- uses: projectdiscovery/actions/setup/go@v1
|
||||
- uses: projectdiscovery/nuclei-action/cache@v3
|
||||
- name: "Defender exclusions (Windows Go speedup)"
|
||||
if: runner.os == 'Windows'
|
||||
shell: pwsh
|
||||
run: |
|
||||
$paths = @("$(go env GOCACHE)", "$(go env GOMODCACHE)", "$env:GITHUB_WORKSPACE", "$env:RUNNER_TEMP")
|
||||
Add-MpPreference -ExclusionPath $paths -ErrorAction SilentlyContinue
|
||||
Add-MpPreference -ExclusionProcess "go.exe","compile.exe","link.exe","cgo.exe","gcc.exe","git.exe","nuclei.exe","nuclei.test.exe","python.exe" -ErrorAction SilentlyContinue
|
||||
Write-Host "Defender exclusions applied (best-effort)"
|
||||
- run: make integration
|
||||
env:
|
||||
PDCP_API_KEY: "${{ secrets.PDCP_API_KEY }}"
|
||||
@@ -126,9 +148,12 @@ jobs:
|
||||
|
||||
functional:
|
||||
name: "Functional tests"
|
||||
needs: ["tests"]
|
||||
needs: ["lint"]
|
||||
env:
|
||||
GITHUB_TOKEN: "${{ github.token }}"
|
||||
# Functional cases honor FUNCTIONAL_PARALLELISM/PARALLELISM (see
|
||||
# functional_test.go), so oversubscribe like the integration job.
|
||||
PARALLELISM: "8"
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
@@ -139,6 +164,14 @@ jobs:
|
||||
- uses: projectdiscovery/actions/setup/python@v1
|
||||
- uses: projectdiscovery/actions/setup/go@v1
|
||||
- uses: projectdiscovery/nuclei-action/cache@v3
|
||||
- name: "Defender exclusions (Windows Go speedup)"
|
||||
if: runner.os == 'Windows'
|
||||
shell: pwsh
|
||||
run: |
|
||||
$paths = @("$(go env GOCACHE)", "$(go env GOMODCACHE)", "$env:GITHUB_WORKSPACE", "$env:RUNNER_TEMP")
|
||||
Add-MpPreference -ExclusionPath $paths -ErrorAction SilentlyContinue
|
||||
Add-MpPreference -ExclusionProcess "go.exe","compile.exe","link.exe","cgo.exe","gcc.exe","git.exe","nuclei.exe","nuclei.test.exe","python.exe" -ErrorAction SilentlyContinue
|
||||
Write-Host "Defender exclusions applied (best-effort)"
|
||||
- uses: projectdiscovery/nuclei-action@v3
|
||||
with:
|
||||
version: latest
|
||||
@@ -147,7 +180,7 @@ jobs:
|
||||
|
||||
validate:
|
||||
name: "Template validate"
|
||||
needs: ["tests"]
|
||||
needs: ["lint"]
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
GITHUB_TOKEN: "${{ github.token }}"
|
||||
@@ -159,7 +192,7 @@ jobs:
|
||||
|
||||
codeql:
|
||||
name: "CodeQL analysis"
|
||||
needs: ["tests"]
|
||||
needs: ["lint"]
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
actions: read
|
||||
@@ -201,21 +234,27 @@ jobs:
|
||||
|
||||
release:
|
||||
name: "Release test"
|
||||
needs: ["tests"]
|
||||
needs: ["lint"]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- uses: projectdiscovery/actions/setup/go@v1
|
||||
with:
|
||||
go-version: "stable"
|
||||
- uses: projectdiscovery/actions/goreleaser@v1
|
||||
# PR compile smoke only: `build` (no archives/docker) over one target per OS
|
||||
# via the snapshot config — fast on a standard runner. The full multi-arch
|
||||
# build + docker + PGO runs on tags via release.yaml.
|
||||
- uses: goreleaser/goreleaser-action@v7
|
||||
with:
|
||||
version: "~> v2"
|
||||
args: build --snapshot --clean --config .goreleaser.snapshot.yml
|
||||
|
||||
flamegraph:
|
||||
name: "Flamegraph"
|
||||
needs: ["tests"]
|
||||
needs: ["lint"]
|
||||
uses: ./.github/workflows/flamegraph.yaml
|
||||
|
||||
# perf-regression:
|
||||
# name: "Performance regression"
|
||||
# needs: ["tests"]
|
||||
# needs: ["lint"]
|
||||
# uses: ./.github/workflows/perf-regression.yaml
|
||||
@@ -0,0 +1,24 @@
|
||||
version: 2
|
||||
|
||||
# CI-only config for the PR "Release test". It's a fast goreleaser compile smoke
|
||||
# over the main platforms (one per OS) that verifies the goreleaser build path
|
||||
# and that nuclei still cross-compiles, without paying for all 8 targets + the
|
||||
# multi-arch docker build on a standard runner. The authoritative full build
|
||||
# (every goos/goarch + docker + PGO) is .goreleaser.yml and runs on tags via
|
||||
# .github/workflows/release.yaml. Keep the build block in sync with that file.
|
||||
builds:
|
||||
- main: cmd/nuclei/main.go
|
||||
binary: nuclei
|
||||
id: nuclei-cli
|
||||
env:
|
||||
- CGO_ENABLED=0
|
||||
- GOEXPERIMENT=greenteagc
|
||||
targets:
|
||||
- linux_amd64
|
||||
- windows_amd64
|
||||
- darwin_arm64
|
||||
flags:
|
||||
- -trimpath
|
||||
ldflags:
|
||||
- -s
|
||||
- -w
|
||||
+47
-9
@@ -3,9 +3,11 @@ package customtemplates
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/projectdiscovery/gologger"
|
||||
"github.com/projectdiscovery/gologger/levels"
|
||||
@@ -26,17 +28,53 @@ func TestDownloadCustomTemplatesFromGitHub(t *testing.T) {
|
||||
|
||||
options := testutils.DefaultOptions
|
||||
options.GitHubTemplateRepo = []string{"projectdiscovery/nuclei-templates-test"}
|
||||
// Authenticate the GitHub API repo lookup when a token is available (CI sets
|
||||
// GITHUB_TOKEN). The unauthenticated API is capped at 60 req/hr per IP, which
|
||||
// the shared CI egress exhausts and is the main source of this test's flake;
|
||||
// an authenticated call gets 5000/hr and resolves reliably.
|
||||
options.GitHubToken = os.Getenv("GITHUB_TOKEN")
|
||||
|
||||
ctm, err := NewCustomTemplatesManager(options)
|
||||
require.Nil(t, err, "could not create custom templates manager")
|
||||
clonedDir := filepath.Join(templatesDirectory, "github", "projectdiscovery", "nuclei-templates-test")
|
||||
|
||||
ctm.Download(context.Background())
|
||||
|
||||
// Check if output contains rate limit error and skip test if so
|
||||
output := outputBuffer.String()
|
||||
if strings.Contains(output, "API rate limit exceeded") {
|
||||
t.Skip("GitHub API rate limit exceeded, skipping test")
|
||||
// The lookup + clone hit the live repo, so a transient GitHub/network hiccup
|
||||
// must not fail CI. Recreate the manager (re-resolving the repo) and retry a
|
||||
// few times; if it still fails only because of a transient remote error,
|
||||
// skip instead of failing. The captured log is NOT reset between attempts so
|
||||
// a rate-limit/API error logged at manager creation is still detectable.
|
||||
var cloned bool
|
||||
for attempt := 1; attempt <= 3; attempt++ {
|
||||
_ = os.RemoveAll(clonedDir) // force a real re-clone on retry
|
||||
ctm, err := NewCustomTemplatesManager(options)
|
||||
require.Nil(t, err, "could not create custom templates manager")
|
||||
ctm.Download(context.Background())
|
||||
if _, statErr := os.Stat(clonedDir); statErr == nil {
|
||||
cloned = true
|
||||
break
|
||||
}
|
||||
time.Sleep(time.Duration(attempt) * time.Second)
|
||||
}
|
||||
|
||||
require.DirExists(t, filepath.Join(templatesDirectory, "github", "projectdiscovery", "nuclei-templates-test"), "cloned directory does not exists")
|
||||
if !cloned && isTransientRemoteError(outputBuffer.String()) {
|
||||
t.Skipf("skipping: transient GitHub error cloning test repo:\n%s", outputBuffer.String())
|
||||
}
|
||||
|
||||
require.True(t, cloned, "cloned directory does not exist:\n%s", outputBuffer.String())
|
||||
}
|
||||
|
||||
// isTransientRemoteError reports whether the captured log output indicates a
|
||||
// transient network/GitHub failure (as opposed to a real regression), so the
|
||||
// test can be skipped rather than failed on flaky CI networking.
|
||||
func isTransientRemoteError(output string) bool {
|
||||
lower := strings.ToLower(output)
|
||||
for _, needle := range []string{
|
||||
"api rate limit exceeded",
|
||||
"timeout", "timed out", "deadline exceeded", "i/o timeout",
|
||||
"connection reset", "connection refused", "no such host",
|
||||
"tls handshake", "eof", "temporary failure", "dial tcp",
|
||||
} {
|
||||
if strings.Contains(lower, needle) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
@@ -98,7 +98,9 @@ func requireDurationField(t *testing.T, event output.InternalEvent, key string)
|
||||
|
||||
value, ok := event[key].(float64)
|
||||
require.Truef(t, ok, "expected %s to be a float64 duration", key)
|
||||
require.Greater(t, value, float64(0))
|
||||
// A sub-millisecond lookup can measure as exactly 0 on low-resolution
|
||||
// clocks (notably Windows), so only require a non-negative duration.
|
||||
require.GreaterOrEqual(t, value, float64(0))
|
||||
require.Less(t, value, float64(60))
|
||||
}
|
||||
|
||||
|
||||
@@ -56,6 +56,8 @@ func requireDurationField(t *testing.T, event output.InternalEvent, key string)
|
||||
|
||||
value, ok := event[key].(float64)
|
||||
require.Truef(t, ok, "expected %s to be a float64 duration", key)
|
||||
require.Greater(t, value, float64(0))
|
||||
// A sub-millisecond lookup can measure as exactly 0 on low-resolution
|
||||
// clocks (notably Windows), so only require a non-negative duration.
|
||||
require.GreaterOrEqual(t, value, float64(0))
|
||||
require.Less(t, value, float64(60))
|
||||
}
|
||||
@@ -396,6 +396,8 @@ func requireWebsocketDurationField(t *testing.T, event output.InternalEvent, key
|
||||
|
||||
value, ok := event[key].(float64)
|
||||
require.Truef(t, ok, "expected %s to be a float64 duration", key)
|
||||
require.Greater(t, value, float64(0))
|
||||
// A sub-millisecond lookup can measure as exactly 0 on low-resolution
|
||||
// clocks (notably Windows), so only require a non-negative duration.
|
||||
require.GreaterOrEqual(t, value, float64(0))
|
||||
require.Less(t, value, float64(60))
|
||||
}
|
||||
@@ -119,6 +119,8 @@ func requireWhoisDurationField(t *testing.T, event output.InternalEvent, key str
|
||||
|
||||
value, ok := event[key].(float64)
|
||||
require.Truef(t, ok, "expected %s to be a float64 duration", key)
|
||||
require.Greater(t, value, float64(0))
|
||||
// A sub-millisecond lookup can measure as exactly 0 on low-resolution
|
||||
// clocks (notably Windows), so only require a non-negative duration.
|
||||
require.GreaterOrEqual(t, value, float64(0))
|
||||
require.Less(t, value, float64(60))
|
||||
}
|
||||
Reference in new issue
Block a user