mirror of
https://github.com/netbirdio/netbird.git
synced 2026-10-26 14:29:08 +01:00
Merge remote-tracking branch 'origin/main' into embedded-vnc
# Conflicts: # client/cmd/up.go # client/internal/engine.go # client/internal/profilemanager/config.go # client/proto/daemon.pb.go # client/server/mdm.go # client/server/server.go # client/status/status.go # client/ui/main.go # client/ui/services/windowmanager.go # management/internals/shared/grpc/conversion.go # management/server/store/sql_store.go # management/server/store/sql_store_test.go # shared/management/networkmap/envelope.go # shared/management/proto/management.pb.go
This commit is contained in:
@@ -52,7 +52,7 @@ jobs:
|
||||
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
|
||||
with:
|
||||
path: /tmp/.buildx-cache
|
||||
key: ${{ runner.os }}-anet-e2e-buildx-${{ hashFiles('go.sum', 'combined/Dockerfile.multistage', 'proxy/Dockerfile.multistage', 'e2e/harness/Dockerfile.client') }}
|
||||
key: ${{ runner.os }}-anet-e2e-buildx-${{ hashFiles('go.sum', 'combined/Dockerfile.multistage', 'proxy/Dockerfile.multistage', 'e2e/harness/Dockerfile.client', 'e2e/harness/Dockerfile.nblink') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-anet-e2e-buildx-
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ jobs:
|
||||
while IFS= read -r dir; do
|
||||
echo "=== Checking $dir ==="
|
||||
# Search for problematic imports, excluding test files
|
||||
RESULTS=$(grep -r "github.com/netbirdio/netbird/\(management\|signal\|relay\|proxy\)" "$dir" --include="*.go" 2>/dev/null | grep -v "_test.go" | grep -v "test_" | grep -v "/test/" | grep -v "tools/idp-migrate/" || true)
|
||||
RESULTS=$(grep -r "github.com/netbirdio/netbird/\(management\|signal\|relay\|proxy\)" "$dir" --include="*.go" 2>/dev/null | grep -v "_test.go" | grep -v "test_" | grep -v "/test/" | grep -v "tools/idp-migrate/" | grep -v "tools/mysql-migrate/" || true)
|
||||
if [ -n "$RESULTS" ]; then
|
||||
echo "❌ Found problematic dependencies:"
|
||||
echo "$RESULTS"
|
||||
@@ -93,7 +93,7 @@ jobs:
|
||||
IMPORTERS=$(go list -json -deps ./... 2>/dev/null | jq -r "select(.Imports[]? == \"$package\") | .ImportPath")
|
||||
|
||||
# Check if any importer is NOT in management/signal/relay
|
||||
BSD_IMPORTER=$(echo "$IMPORTERS" | grep -v "github.com/netbirdio/netbird/\(management\|signal\|relay\|proxy\|combined\|tools/idp-migrate\)" | head -1)
|
||||
BSD_IMPORTER=$(echo "$IMPORTERS" | grep -v "github.com/netbirdio/netbird/\(management\|signal\|relay\|proxy\|combined\|tools/idp-migrate\|tools/mysql-migrate\)" | head -1)
|
||||
|
||||
if [ -n "$BSD_IMPORTER" ]; then
|
||||
echo "❌ $package ($license) is imported by BSD-licensed code: $BSD_IMPORTER"
|
||||
|
||||
@@ -12,6 +12,8 @@ jobs:
|
||||
docs-ack:
|
||||
name: Require docs PR URL or explicit "not needed"
|
||||
runs-on: ubuntu-latest
|
||||
# Crowdin's translation-sync service PRs are auto-generated without the PR template.
|
||||
if: github.event.pull_request.user.login != 'netbirddev'
|
||||
|
||||
steps:
|
||||
- name: Read PR body
|
||||
|
||||
@@ -38,12 +38,12 @@ jobs:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v4
|
||||
uses: actions/setup-node@v7
|
||||
with:
|
||||
node-version: "22"
|
||||
|
||||
- name: Set up pnpm
|
||||
uses: pnpm/action-setup@a3252b78c470c02df07e9d59298aecedc3ccdd6d # v3.0.0
|
||||
uses: pnpm/action-setup@ea17c68df8912ef543352723c149a84f56e3d413 # v6.1.0
|
||||
with:
|
||||
version: 11
|
||||
|
||||
@@ -79,7 +79,7 @@ jobs:
|
||||
run: echo "path=$(pnpm store path --silent)" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Cache pnpm store
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache@v6
|
||||
with:
|
||||
path: ${{ steps.pnpm-store.outputs.path }}
|
||||
key: ${{ runner.os }}-pnpm-${{ hashFiles('client/ui/frontend/pnpm-lock.yaml') }}
|
||||
|
||||
@@ -33,7 +33,7 @@ jobs:
|
||||
with:
|
||||
usesh: true
|
||||
copyback: false
|
||||
release: "15.0"
|
||||
release: "15.1"
|
||||
envs: "GO_VERSION"
|
||||
prepare: |
|
||||
pkg install -y curl pkgconf xorg
|
||||
|
||||
@@ -207,6 +207,43 @@ jobs:
|
||||
# regression test, and need no frontend bundle.
|
||||
run: CGO_ENABLED=1 go test -timeout 5m ./client/ui/authsession/... ./client/ui/i18n/... ./client/ui/preferences/... ./client/ui/services/...
|
||||
|
||||
test_client_pkcs11:
|
||||
name: "Client PKCS#11 / Unit"
|
||||
# The deb and rpm packages ship the client built with the pkcs11 tag, which loads
|
||||
# PKCS#11 modules through purego. The other jobs build without the tag, so this one
|
||||
# compiles that driver and signs with a real SoftHSM token, the build release ships.
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6.5.0
|
||||
with:
|
||||
go-version-file: "go.mod"
|
||||
cache: false
|
||||
|
||||
- name: Install SoftHSM
|
||||
run: sudo apt update && sudo apt install -y -q softhsm2
|
||||
|
||||
- name: Initialise token
|
||||
run: |
|
||||
mkdir -p "$RUNNER_TEMP/softhsm/tokens"
|
||||
printf 'directories.tokendir = %s\nobjectstore.backend = file\n' "$RUNNER_TEMP/softhsm/tokens" > "$RUNNER_TEMP/softhsm/softhsm2.conf"
|
||||
echo "SOFTHSM2_CONF=$RUNNER_TEMP/softhsm/softhsm2.conf" >> "$GITHUB_ENV"
|
||||
SOFTHSM2_CONF="$RUNNER_TEMP/softhsm/softhsm2.conf" softhsm2-util --init-token --free --label netbird --pin 1234 --so-pin 1234
|
||||
|
||||
- name: Vet
|
||||
run: CGO_ENABLED=0 go vet -tags pkcs11 ./client/internal/pkcs11/... ./client/internal/certproof/...
|
||||
|
||||
- name: Test
|
||||
env:
|
||||
NB_TEST_PKCS11_URI: "pkcs11:token=netbird?module-path=/usr/lib/softhsm/libsofthsm2.so&pin-value=1234"
|
||||
NB_TEST_PKCS11_DISPOSABLE: "1"
|
||||
run: CGO_ENABLED=0 go test -tags pkcs11 -timeout 5m ./client/internal/pkcs11/... ./client/internal/certproof/...
|
||||
|
||||
test_client_on_docker:
|
||||
name: "Client (Docker) / Unit"
|
||||
needs: [build-cache]
|
||||
@@ -270,7 +307,7 @@ jobs:
|
||||
sh -c ' \
|
||||
apk update; apk add --no-cache \
|
||||
ca-certificates iptables ip6tables dbus dbus-dev libpcap-dev build-base; \
|
||||
go test -buildvcs=false -tags "devcert privileged" -v -timeout 10m -p 1 $(go list -e -buildvcs=false ./... | grep -v -e /management -e /signal -e /relay -e /proxy -e /combined -e /client/ui -e /upload-server -e /client/testutil/privileged)
|
||||
go test -buildvcs=false -tags "devcert privileged" -v -timeout 10m -p 1 $(go list -e -buildvcs=false ./... | grep -v -e /management -e /signal -e /relay -e /proxy -e /combined -e /client/ui -e /upload-server -e /client/testutil/privileged -e tools/mysql-migrate)
|
||||
'
|
||||
|
||||
test_relay:
|
||||
|
||||
@@ -76,7 +76,7 @@ jobs:
|
||||
# resolve; the Where-Object pipeline then drops the broken package by
|
||||
# path. Without -e, go list aborts with empty stdout.
|
||||
run: |
|
||||
$packages = go list -e ./... | Where-Object { $_ -notmatch '/management' } | Where-Object { $_ -notmatch '/relay' } | Where-Object { $_ -notmatch '/signal' } | Where-Object { $_ -notmatch '/proxy' } | Where-Object { $_ -notmatch '/combined' } | Where-Object { $_ -notmatch '/client/ui$' }
|
||||
$packages = go list -e ./... | Where-Object { $_ -notmatch '/management' } | Where-Object { $_ -notmatch '/relay' } | Where-Object { $_ -notmatch '/signal' } | Where-Object { $_ -notmatch '/proxy' } | Where-Object { $_ -notmatch '/combined' } | Where-Object { $_ -notmatch '/client/ui$' } | Where-Object { $_ -notmatch '/tools/mysql-migrate' }
|
||||
$goExe = "C:\hostedtoolcache\windows\go\${{ steps.go.outputs.go-version }}\x64\bin\go.exe"
|
||||
$cmd = "$goExe test -tags `"devcert privileged`" -timeout 10m -p 1 $($packages -join ' ') > test-out.txt 2>&1"
|
||||
Set-Content -Path "${{ github.workspace }}\run-tests.cmd" -Value $cmd
|
||||
|
||||
@@ -30,7 +30,7 @@ jobs:
|
||||
# segment by codespell and behave the same across versions; the
|
||||
# recursive "**" form did not take effect with the codespell shipped
|
||||
# by this action.
|
||||
skip: go.mod,go.sum,*/proxy/web/*,*pnpm-lock.yaml,*package-lock.json,*/locales/de/*,*/locales/es/*,*/locales/fr/*,*/locales/hu/*,*/locales/it/*,*/locales/pt/*,*/locales/ru/*,*/locales/zh-CN/*,*/i18n/TRANSLATING.md
|
||||
skip: go.mod,go.sum,*/proxy/web/*,*pnpm-lock.yaml,*package-lock.json,*/locales/de/*,*/locales/es/*,*/locales/fr/*,*/locales/gl/*,*/locales/hu/*,*/locales/it/*,*/locales/pt/*,*/locales/ru/*,*/locales/zh-CN/*,*/i18n/TRANSLATING.md
|
||||
golangci:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
@@ -80,3 +80,49 @@ jobs:
|
||||
skip-save-cache: true
|
||||
cache-invalidation-interval: 0
|
||||
args: --timeout=20m
|
||||
|
||||
# Separate job rather than extra rows in the matrix above: those rows pick a
|
||||
# GOOS by picking a runner OS, while android/ios are cross-compiled from
|
||||
# ubuntu — an `include` entry with os: ubuntu-latest would merge into the
|
||||
# Linux row instead of adding one. The package path is restricted because a
|
||||
# whole-repo run under GOOS=android pulls *_linux.go files into packages that
|
||||
# have no android counterpart.
|
||||
golangci-mobile:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- goos: android
|
||||
goarch: arm64
|
||||
packages: ./client/android/...
|
||||
display_name: Android
|
||||
- goos: ios
|
||||
goarch: arm64
|
||||
packages: ./client/ios/...
|
||||
display_name: iOS
|
||||
name: ${{ matrix.display_name }}
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 25
|
||||
env:
|
||||
CGO_ENABLED: 0
|
||||
GOOS: ${{ matrix.goos }}
|
||||
GOARCH: ${{ matrix.goarch }}
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6.5.0
|
||||
with:
|
||||
go-version-file: "go.mod"
|
||||
cache: false
|
||||
- name: golangci-lint
|
||||
uses: golangci/golangci-lint-action@82606bf257cbaff209d206a39f5134f0cfbfd2ee #v9.2.1
|
||||
with:
|
||||
version: latest
|
||||
install-mode: binary
|
||||
skip-cache: true
|
||||
skip-save-cache: true
|
||||
cache-invalidation-interval: 0
|
||||
args: --timeout=20m ${{ matrix.packages }}
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
name: Mobile
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- "release-*"
|
||||
pull_request:
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}-${{ github.head_ref || github.actor_id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
android_build:
|
||||
name: "Android / Build"
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
goarch: [arm64, arm, amd64, "386"]
|
||||
env:
|
||||
CGO_ENABLED: 0
|
||||
GOOS: android
|
||||
GOARCH: ${{ matrix.goarch }}
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6.5.0
|
||||
with:
|
||||
go-version-file: "go.mod"
|
||||
- name: Build Android bridge
|
||||
run: go build ./client/android/...
|
||||
- name: Vet Android bridge
|
||||
if: matrix.goarch == 'arm64'
|
||||
run: go vet ./client/android/...
|
||||
|
||||
ios_build:
|
||||
name: "iOS / Build"
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
goarch: [arm64, amd64]
|
||||
env:
|
||||
CGO_ENABLED: 0
|
||||
GOOS: ios
|
||||
GOARCH: ${{ matrix.goarch }}
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6.5.0
|
||||
with:
|
||||
go-version-file: "go.mod"
|
||||
# No `go vet` counterpart: every ios target requires external (cgo)
|
||||
# linking, which needs an Xcode toolchain the runner does not have.
|
||||
- name: Build iOS SDK
|
||||
run: go build ./client/ios/...
|
||||
@@ -7,6 +7,8 @@ on:
|
||||
jobs:
|
||||
check-title:
|
||||
runs-on: ubuntu-latest
|
||||
# Crowdin's translation-sync service PRs are auto-generated with a fixed title.
|
||||
if: github.event.pull_request.user.login != 'netbirddev'
|
||||
steps:
|
||||
- name: Validate PR title prefix
|
||||
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||||
|
||||
@@ -0,0 +1,207 @@
|
||||
name: Red Hat Certification
|
||||
|
||||
# Certify published UBI images in the Red Hat Ecosystem Catalog. Called by
|
||||
# release.yml on stable tags, or run by hand to (re)certify any released
|
||||
# version. preflight submits every architecture of an image's manifest list
|
||||
# to Pyxis; auto-publish on the component makes it public once certified.
|
||||
#
|
||||
# Each component's Partner Connect ID comes from the REDHAT_CERT_ID_<NAME>
|
||||
# repository variable, e.g. REDHAT_CERT_ID_CLIENT_ROOTLESS. The run fails
|
||||
# before certifying anything if a selected component's variable is not set.
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
component:
|
||||
type: string
|
||||
required: true
|
||||
version:
|
||||
type: string
|
||||
required: true
|
||||
secrets:
|
||||
PYXIS_API_TOKEN:
|
||||
required: true
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
component:
|
||||
description: "Component to certify"
|
||||
type: choice
|
||||
required: true
|
||||
default: all
|
||||
options:
|
||||
- all
|
||||
- client-rootless
|
||||
- reverse-proxy
|
||||
- netbird-server
|
||||
- management
|
||||
- signal
|
||||
- relay
|
||||
version:
|
||||
description: "Released version, e.g. v0.80.0"
|
||||
type: string
|
||||
required: true
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
resolve:
|
||||
name: Resolve components
|
||||
runs-on: ubuntu-24.04
|
||||
outputs:
|
||||
version: ${{ steps.resolve.outputs.version }}
|
||||
matrix: ${{ steps.resolve.outputs.matrix }}
|
||||
steps:
|
||||
- name: Resolve components and images
|
||||
id: resolve
|
||||
env:
|
||||
COMPONENT: ${{ inputs.component }}
|
||||
INPUT_VERSION: ${{ inputs.version }}
|
||||
REPO_VARS: ${{ toJSON(vars) }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
version="${INPUT_VERSION#v}"
|
||||
if [[ ! "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
||||
echo "::error::Only stable x.y.z versions are certified, got '${INPUT_VERSION}'"
|
||||
exit 1
|
||||
fi
|
||||
# name, image repository, tag suffix (must match .goreleaser.yaml).
|
||||
# Keep the names in sync with the workflow_dispatch options above.
|
||||
components=(
|
||||
"client-rootless ghcr.io/netbirdio/netbird -rootless-ubi"
|
||||
"reverse-proxy ghcr.io/netbirdio/reverse-proxy -ubi"
|
||||
"netbird-server ghcr.io/netbirdio/netbird-server -ubi"
|
||||
"management ghcr.io/netbirdio/management -ubi"
|
||||
"signal ghcr.io/netbirdio/signal -ubi"
|
||||
"relay ghcr.io/netbirdio/relay -ubi"
|
||||
)
|
||||
matrix="[]"
|
||||
missing=()
|
||||
for c in "${components[@]}"; do
|
||||
read -r name repo suffix <<< "$c"
|
||||
[[ "$COMPONENT" == all || "$COMPONENT" == "$name" ]] || continue
|
||||
var="REDHAT_CERT_ID_${name^^}"; var="${var//-/_}"
|
||||
id="$(jq -r --arg v "$var" '.[$v] // empty' <<< "$REPO_VARS")"
|
||||
if [[ -z "$id" ]]; then
|
||||
missing+=("$var")
|
||||
continue
|
||||
fi
|
||||
matrix="$(jq -c --arg n "$name" --arg t "${version}${suffix}" --arg r "${repo}:${version}${suffix}" --arg i "$id" \
|
||||
'. + [{component: $n, tag: $t, ref: $r, component_id: $i}]' <<< "$matrix")"
|
||||
done
|
||||
if (( ${#missing[@]} )); then
|
||||
echo "::error::Set these repository variables to the Partner Connect component IDs: ${missing[*]}"
|
||||
exit 1
|
||||
fi
|
||||
if [[ "$matrix" == "[]" ]]; then
|
||||
echo "::error::No component to certify for '${COMPONENT}'"
|
||||
exit 1
|
||||
fi
|
||||
echo "Components to certify: ${matrix}"
|
||||
echo "version=${version}" >> "$GITHUB_OUTPUT"
|
||||
echo "matrix=${matrix}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
certify:
|
||||
name: "Certify ${{ matrix.component }} UBI image"
|
||||
needs: resolve
|
||||
runs-on: ubuntu-24.04
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include: ${{ fromJSON(needs.resolve.outputs.matrix) }}
|
||||
env:
|
||||
PREFLIGHT_VERSION: "1.21.0"
|
||||
# sha256 of preflight-linux-amd64 from the 1.21.0 GitHub release.
|
||||
# Red Hat publishes no checksum file, so the value is pinned here.
|
||||
PREFLIGHT_SHA256: "5e653135503c72f8702bbe31d7643197d12937c68086879133dd6b9650a9a449"
|
||||
steps:
|
||||
- name: Verify the multi-arch image is on ghcr.io
|
||||
env:
|
||||
IMAGE_REF: ${{ matrix.ref }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
docker buildx imagetools inspect "$IMAGE_REF" --raw > manifest.json
|
||||
for arch in amd64 arm64; do
|
||||
if ! jq -e --arg a "$arch" '.manifests[] | select(.platform.architecture == $a)' manifest.json > /dev/null; then
|
||||
echo "::error::${IMAGE_REF} has no ${arch} manifest"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
echo "Manifest list for ${IMAGE_REF}:"
|
||||
jq -r '.manifests[] | "\(.platform.os)/\(.platform.architecture) \(.digest)"' manifest.json
|
||||
|
||||
- name: Install preflight
|
||||
run: |
|
||||
set -euo pipefail
|
||||
curl -fsSL --proto '=https' --proto-redir '=https' -o preflight \
|
||||
"https://github.com/redhat-openshift-ecosystem/openshift-preflight/releases/download/${PREFLIGHT_VERSION}/preflight-linux-amd64"
|
||||
echo "${PREFLIGHT_SHA256} preflight" | sha256sum -c -
|
||||
chmod +x preflight
|
||||
./preflight --version
|
||||
|
||||
- name: Run preflight checks and submit to Red Hat
|
||||
env:
|
||||
IMAGE_REF: ${{ matrix.ref }}
|
||||
PFLT_PYXIS_API_TOKEN: ${{ secrets.PYXIS_API_TOKEN }}
|
||||
PFLT_CERTIFICATION_COMPONENT_ID: ${{ matrix.component_id }}
|
||||
PFLT_ARTIFACTS: artifacts
|
||||
PFLT_LOGFILE: artifacts/preflight.log
|
||||
PFLT_LOGLEVEL: info
|
||||
PFLT_JUNIT: "true"
|
||||
run: |
|
||||
set -euo pipefail
|
||||
# No --platform: preflight walks the manifest list and submits every
|
||||
# architecture in one run, grouped under one manifest-list digest.
|
||||
# preflight does not create the PFLT_LOGFILE directory, and --submit
|
||||
# fails if the log file is missing.
|
||||
mkdir -p artifacts
|
||||
./preflight check container "$IMAGE_REF" --submit
|
||||
|
||||
- name: Fail if any check did not pass
|
||||
run: |
|
||||
set -euo pipefail
|
||||
shopt -s nullglob globstar
|
||||
results=(artifacts/**/results.json)
|
||||
if [[ ${#results[@]} -eq 0 ]]; then
|
||||
echo "::error::preflight produced no results.json"
|
||||
exit 1
|
||||
fi
|
||||
status=0
|
||||
for f in "${results[@]}"; do
|
||||
arch="$(basename "$(dirname "$f")")"
|
||||
passed="$(jq -r '.passed' "$f")"
|
||||
failed="$(jq -r '[.results.failed[]?.name] | join(", ")' "$f")"
|
||||
echo "${arch}: passed=${passed} ${failed:+failed checks: ${failed}}"
|
||||
[[ "$passed" == "true" ]] || status=1
|
||||
done
|
||||
exit $status
|
||||
|
||||
- name: Upload preflight artifacts
|
||||
if: always()
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: redhat-preflight-${{ matrix.component }}-${{ needs.resolve.outputs.version }}
|
||||
path: artifacts/
|
||||
retention-days: 30
|
||||
|
||||
- name: Wait for Pyxis to mark both architectures certified
|
||||
env:
|
||||
TAG: ${{ matrix.tag }}
|
||||
COMPONENT_ID: ${{ matrix.component_id }}
|
||||
PFLT_PYXIS_API_TOKEN: ${{ secrets.PYXIS_API_TOKEN }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
# Filter on the tag server-side so older versions are found past the first page.
|
||||
url="https://catalog.redhat.com/api/containers/v1/projects/certification/id/${COMPONENT_ID}/images?filter=repositories.tags.name==${TAG}&page_size=100"
|
||||
for attempt in $(seq 1 20); do
|
||||
certified="$(curl -fsS --proto '=https' --proto-redir '=https' -H "X-API-KEY: ${PFLT_PYXIS_API_TOKEN}" "$url" \
|
||||
| jq -r --arg t "$TAG" '[.data[] | select(.repositories[]?.tags[]?.name == $t) | select(.certified == true) | .architecture] | unique | join(",")')"
|
||||
echo "attempt ${attempt}: certified architectures for ${TAG}: ${certified:-none}"
|
||||
if [[ "$certified" == "amd64,arm64" ]]; then
|
||||
echo "Both architectures certified. Auto-publish is enabled on the component, so the catalog updates on its own."
|
||||
exit 0
|
||||
fi
|
||||
sleep 30
|
||||
done
|
||||
echo "::error::Pyxis has not marked both architectures certified after 10 minutes. Check https://connect.redhat.com/component/view/${COMPONENT_ID}/images"
|
||||
exit 1
|
||||
+112
-22
@@ -23,8 +23,50 @@ concurrency:
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
freebsd_port_trigger:
|
||||
name: "FreeBSD Port / Trigger"
|
||||
runs-on: ubuntu-22.04
|
||||
outputs:
|
||||
run: ${{ steps.decide.outputs.run }}
|
||||
version: ${{ steps.decide.outputs.version }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Decide whether the port job runs
|
||||
id: decide
|
||||
env:
|
||||
BASE_SHA: ${{ github.event.pull_request.base.sha }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
run=false
|
||||
case "$GITHUB_EVENT_NAME" in
|
||||
push)
|
||||
if [[ "$GITHUB_REF" == "refs/heads/main" ]]; then
|
||||
run=true
|
||||
elif [[ "$GITHUB_REF" == refs/tags/* && "$GITHUB_REF_NAME" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
||||
# The port tracks stable releases only, so a canary or rc tag has nothing to submit.
|
||||
run=true
|
||||
echo "version=${GITHUB_REF_NAME#v}" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
;;
|
||||
pull_request)
|
||||
git fetch --depth=1 origin "$BASE_SHA"
|
||||
if git diff --name-only "$BASE_SHA" HEAD | \
|
||||
grep -qE '^(release_files/freebsd-port-.*\.sh|\.github/workflows/release\.yml)$'; then
|
||||
run=true
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
echo "run=$run" >> "$GITHUB_OUTPUT"
|
||||
echo "FreeBSD port job runs: $run"
|
||||
|
||||
release_freebsd_port:
|
||||
name: "FreeBSD Port / Build & Test"
|
||||
needs: freebsd_port_trigger
|
||||
if: needs.freebsd_port_trigger.outputs.run == 'true'
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Checkout
|
||||
@@ -33,18 +75,19 @@ jobs:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Generate FreeBSD port diff
|
||||
run: bash -x release_files/freebsd-port-diff.sh
|
||||
|
||||
- name: Generate FreeBSD port issue body
|
||||
run: bash -x release_files/freebsd-port-issue-body.sh
|
||||
env:
|
||||
TARGET_VERSION: ${{ needs.freebsd_port_trigger.outputs.version }}
|
||||
run: bash -x release_files/freebsd-port-diff.sh "$TARGET_VERSION"
|
||||
|
||||
- name: Check if diff was generated
|
||||
id: check_diff
|
||||
run: |
|
||||
if ls netbird-*.diff 1> /dev/null 2>&1; then
|
||||
echo "diff_exists=true" >> $GITHUB_OUTPUT
|
||||
shopt -s nullglob
|
||||
diffs=(netbird-*.diff)
|
||||
if [[ ${#diffs[@]} -gt 0 ]]; then
|
||||
echo "diff_exists=true" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "diff_exists=false" >> $GITHUB_OUTPUT
|
||||
echo "diff_exists=false" >> "$GITHUB_OUTPUT"
|
||||
echo "No diff file generated (port may already be up to date)"
|
||||
fi
|
||||
|
||||
@@ -52,10 +95,18 @@ jobs:
|
||||
if: steps.check_diff.outputs.diff_exists == 'true'
|
||||
id: version
|
||||
run: |
|
||||
VERSION=$(ls netbird-*.diff | sed 's/netbird-\(.*\)\.diff/\1/')
|
||||
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
||||
diffs=(netbird-*.diff)
|
||||
VERSION="${diffs[0]#netbird-}"
|
||||
VERSION="${VERSION%.diff}"
|
||||
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
|
||||
echo "Generated files for version: $VERSION"
|
||||
cat netbird-*.diff
|
||||
cat "${diffs[0]}"
|
||||
|
||||
- name: Generate FreeBSD port issue body
|
||||
if: steps.check_diff.outputs.diff_exists == 'true'
|
||||
env:
|
||||
TARGET_VERSION: ${{ steps.version.outputs.version }}
|
||||
run: bash -x release_files/freebsd-port-issue-body.sh "" "$TARGET_VERSION"
|
||||
|
||||
- name: Read Go version from go.mod
|
||||
id: goversion
|
||||
@@ -69,7 +120,7 @@ jobs:
|
||||
with:
|
||||
usesh: true
|
||||
copyback: false
|
||||
release: "15.0"
|
||||
release: "15.1"
|
||||
envs: "GO_VERSION"
|
||||
prepare: |
|
||||
# Install required packages
|
||||
@@ -191,6 +242,17 @@ jobs:
|
||||
# requires a changelog. Generated, not committed (see .gitignore).
|
||||
# chglog is a go.mod tool directive, so go.sum pins it and its deps.
|
||||
run: bash release_files/rpm-changelog.sh
|
||||
- name: Fill the RPM ISA provide version
|
||||
# nfpm cannot emit rpmbuild's ISA provide and GoReleaser cannot template it.
|
||||
run: bash release_files/rpm-provides.sh
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
|
||||
with:
|
||||
node-version: '22'
|
||||
- name: Install proxy web dependencies for license collection
|
||||
# release_files/collect-licenses.sh -w reads the proxy UI's license terms from node_modules.
|
||||
working-directory: proxy/web
|
||||
run: npm ci --ignore-scripts
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@06116385d9baf250c9f4dcb4858b16962ea869c3 #v4.1.0
|
||||
- name: Set up Docker Buildx
|
||||
@@ -230,14 +292,18 @@ jobs:
|
||||
uses: goreleaser/goreleaser-action@5daf1e915a5f0af01ddbcd89a43b8061ff4f1a89 # v7.2.2
|
||||
with:
|
||||
version: ${{ env.GORELEASER_VER }}
|
||||
args: release --clean ${{ env.flags }}
|
||||
args: release --config .goreleaser.generated.yaml --clean ${{ env.flags }}
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
HOMEBREW_TAP_GITHUB_TOKEN: ${{ secrets.HOMEBREW_TAP_GITHUB_TOKEN }}
|
||||
UPLOAD_DEBIAN_SECRET: ${{ secrets.PKG_UPLOAD_SECRET }}
|
||||
UPLOAD_YUM_SECRET: ${{ secrets.PKG_UPLOAD_SECRET }}
|
||||
GPG_RPM_KEY_FILE: ${{ env.GPG_RPM_KEY_FILE }}
|
||||
NFPM_NETBIRD_RPM_PASSPHRASE: ${{ secrets.GPG_RPM_PASSPHRASE }}
|
||||
# One per nfpm id: GoReleaser looks the passphrase up as NFPM_<ID>_PASSPHRASE.
|
||||
NFPM_NETBIRD_RPM_AMD64_PASSPHRASE: ${{ secrets.GPG_RPM_PASSPHRASE }}
|
||||
NFPM_NETBIRD_RPM_ARM64_PASSPHRASE: ${{ secrets.GPG_RPM_PASSPHRASE }}
|
||||
NFPM_NETBIRD_RPM_ARM_PASSPHRASE: ${{ secrets.GPG_RPM_PASSPHRASE }}
|
||||
NFPM_NETBIRD_RPM_386_PASSPHRASE: ${{ secrets.GPG_RPM_PASSPHRASE }}
|
||||
SKIP_PUBLISH: ${{ env.SKIP_PUBLISH }}
|
||||
SKIP_DOCKER_PUSH: ${{ env.SKIP_DOCKER_PUSH }}
|
||||
- name: Verify RPM signatures
|
||||
@@ -294,10 +360,12 @@ jobs:
|
||||
tag_and_push() {
|
||||
local src="$1" img_name tag dst variant=""
|
||||
img_name="${src%%:*}"
|
||||
# Client variants share a repository, so keep their tag suffixes.
|
||||
# Variants share a repository with their default image, so keep
|
||||
# their tag suffixes. Order matters: the first matching pattern wins.
|
||||
case "$src" in
|
||||
*-rootless-ubi-amd64) variant="-rootless-ubi" ;;
|
||||
*-rootless-amd64) variant="-rootless" ;;
|
||||
*-ubi-amd64) variant="-ubi" ;;
|
||||
esac
|
||||
for tag in $(resolve_tags); do
|
||||
dst="${img_name}:${tag}${variant}"
|
||||
@@ -346,7 +414,11 @@ jobs:
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a #v7.0.1
|
||||
with:
|
||||
name: linux-packages
|
||||
path: dist/netbird_linux**
|
||||
path: |
|
||||
dist/netbird_linux**
|
||||
dist/netbird-pkcs11_linux**
|
||||
dist/netbird-deb-32bit_linux**
|
||||
dist/netbird-rpm-*_linux**
|
||||
retention-days: 7
|
||||
- name: upload windows packages
|
||||
id: upload_windows_packages
|
||||
@@ -363,6 +435,24 @@ jobs:
|
||||
path: dist/netbird_darwin**
|
||||
retention-days: 7
|
||||
|
||||
# Certify the UBI images in the Red Hat Ecosystem Catalog on stable tags.
|
||||
# See redhat-certify.yml, which can also be run by hand for any released version.
|
||||
redhat_certification:
|
||||
name: "Red Hat"
|
||||
needs: release
|
||||
if: |
|
||||
github.repository == 'netbirdio/netbird' &&
|
||||
startsWith(github.ref, 'refs/tags/v') &&
|
||||
!contains(github.ref_name, '-')
|
||||
permissions:
|
||||
contents: read
|
||||
uses: ./.github/workflows/redhat-certify.yml
|
||||
with:
|
||||
component: all
|
||||
version: ${{ github.ref_name }}
|
||||
secrets:
|
||||
PYXIS_API_TOKEN: ${{ secrets.PYXIS_API_TOKEN }}
|
||||
|
||||
release_ui:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
@@ -417,12 +507,12 @@ jobs:
|
||||
run: git --no-pager diff --exit-code
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v4
|
||||
uses: actions/setup-node@v7
|
||||
with:
|
||||
node-version: '22'
|
||||
|
||||
- name: Set up pnpm
|
||||
uses: pnpm/action-setup@a3252b78c470c02df07e9d59298aecedc3ccdd6d # v3.0.0
|
||||
uses: pnpm/action-setup@ea17c68df8912ef543352723c149a84f56e3d413 # v6.1.0
|
||||
with:
|
||||
version: 11
|
||||
|
||||
@@ -554,12 +644,12 @@ jobs:
|
||||
run: git --no-pager diff --exit-code
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
|
||||
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
|
||||
with:
|
||||
node-version: '22'
|
||||
|
||||
- name: Set up pnpm
|
||||
uses: pnpm/action-setup@a3252b78c470c02df07e9d59298aecedc3ccdd6d # v3.0.0
|
||||
uses: pnpm/action-setup@ea17c68df8912ef543352723c149a84f56e3d413 # v6.1.0
|
||||
with:
|
||||
version: 11
|
||||
|
||||
@@ -651,11 +741,11 @@ jobs:
|
||||
- name: check git status
|
||||
run: git --no-pager diff --exit-code
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v4
|
||||
uses: actions/setup-node@v7
|
||||
with:
|
||||
node-version: '22'
|
||||
- name: Set up pnpm
|
||||
uses: pnpm/action-setup@a3252b78c470c02df07e9d59298aecedc3ccdd6d # v3.0.0
|
||||
uses: pnpm/action-setup@ea17c68df8912ef543352723c149a84f56e3d413 # v6.1.0
|
||||
with:
|
||||
version: 11
|
||||
- name: Install wails3 CLI
|
||||
@@ -774,7 +864,7 @@ jobs:
|
||||
run: 7z x -o"${{ github.workspace }}/NSIS_Plugins" "${{ github.workspace }}/ShellExecAsUser_amd64-Unicode.7z"
|
||||
|
||||
- name: Set up Go for wails3 CLI
|
||||
uses: actions/setup-go@v5
|
||||
uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version-file: "go.mod"
|
||||
cache: false
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
name: Reverse Proxy E2E
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- '.github/workflows/reverse-proxy-e2e.yml'
|
||||
- '**/*.go'
|
||||
- 'e2e/**'
|
||||
- 'shared/management/**'
|
||||
- 'combined/Dockerfile*'
|
||||
- 'proxy/Dockerfile*'
|
||||
- '.dockerignore'
|
||||
- 'go.mod'
|
||||
- 'go.sum'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
reverse-proxy:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
|
||||
with:
|
||||
go-version-file: go.mod
|
||||
|
||||
- name: Set up Buildx
|
||||
uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0
|
||||
|
||||
- name: Cache Docker layers
|
||||
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
|
||||
with:
|
||||
path: /tmp/.reverse-proxy-buildx-cache
|
||||
key: ${{ runner.os }}-reverse-proxy-e2e-${{ hashFiles('go.sum', 'combined/Dockerfile.multistage', 'proxy/Dockerfile.multistage') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-reverse-proxy-e2e-
|
||||
|
||||
- name: Run reverse-proxy E2E
|
||||
env:
|
||||
NB_E2E_BUILDX_CACHE: /tmp/.reverse-proxy-buildx-cache
|
||||
run: go test -tags e2e -timeout 25m -v ./e2e/reverseproxy/...
|
||||
@@ -0,0 +1,46 @@
|
||||
name: Test Homebrew cask
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- "client/ui/netbird-ui.rb.tmpl"
|
||||
- ".github/scripts/test-homebrew-cask.sh"
|
||||
- ".github/workflows/test-homebrew-cask.yml"
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}-${{ github.head_ref || github.actor_id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
install-uninstall:
|
||||
runs-on: macos-latest
|
||||
timeout-minutes: 20
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Clone the Homebrew tap
|
||||
run: git clone https://github.com/netbirdio/homebrew-tap.git .homebrew-cask-tap
|
||||
|
||||
- name: Update Homebrew and install gomplate
|
||||
# The runner image disables auto-update; the cask steps DSL needs Homebrew 6.0.20 or newer.
|
||||
run: |
|
||||
brew update
|
||||
brew install gomplate
|
||||
|
||||
- name: Install and uninstall the cask
|
||||
run: .github/scripts/test-homebrew-cask.sh
|
||||
|
||||
- name: Upload logs
|
||||
if: always()
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a #v7.0.1
|
||||
with:
|
||||
name: homebrew-cask-results
|
||||
path: ${{ runner.temp }}/homebrew-cask/results
|
||||
if-no-files-found: ignore
|
||||
@@ -258,6 +258,18 @@ jobs:
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Verify enterprise Traefik tag validation
|
||||
run: bash infrastructure_files/tests/test-getting-started-enterprise.sh
|
||||
|
||||
- name: Verify community Traefik image validation
|
||||
run: bash infrastructure_files/tests/test-getting-started.sh
|
||||
|
||||
- name: Verify community Compose network scoping
|
||||
run: bash infrastructure_files/tests/test-getting-started-networks.sh
|
||||
|
||||
- name: Verify migration Compose network scoping
|
||||
run: bash infrastructure_files/tests/test-getting-started-networks.sh --migration
|
||||
|
||||
- name: Verify fresh-install session cookie key hardening
|
||||
run: |
|
||||
grep -Fxq ' SESSION_COOKIE_ENCRYPTION_KEY=$(openssl rand -base64 32)' infrastructure_files/getting-started.sh
|
||||
|
||||
@@ -32,11 +32,12 @@ jobs:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v4
|
||||
uses: actions/setup-node@v7
|
||||
with:
|
||||
node-version: "22"
|
||||
|
||||
# English (en) is the source of truth for translation keys; every other
|
||||
# locale declared in _index.json must carry the exact same key set.
|
||||
# English (en) is the source of truth for translation keys. Locales declared
|
||||
# in _index.json fail on orphaned keys or placeholder mismatches; missing
|
||||
# keys only warn, since they fall back to English at runtime.
|
||||
- name: Check translation key parity
|
||||
run: node client/ui/i18n/check-translations.mjs
|
||||
|
||||
Reference in New Issue
Block a user