mirror of
https://github.com/netbirdio/dashboard.git
synced 2026-09-23 00:30:43 -07:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e167afb06b |
No files matched your search
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"extends": ["next/core-web-vitals","prettier"],
|
||||
"plugins": ["simple-import-sort"],
|
||||
"rules": {
|
||||
"simple-import-sort/imports": [
|
||||
"warn",
|
||||
{
|
||||
"groups": [["^\\u0000", "^@?\\w", "^[^.]", "^\\."]]
|
||||
}
|
||||
],
|
||||
"simple-import-sort/exports": "warn"
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
## Issue ticket number and link
|
||||
|
||||
## Documentation
|
||||
Select exactly one:
|
||||
|
||||
- [ ] I added/updated documentation for this change
|
||||
- [ ] Documentation is **not needed** for this change (explain why)
|
||||
|
||||
### Docs PR URL (required if "docs added" is checked)
|
||||
Paste the PR link from https://github.com/netbirdio/docs here:
|
||||
|
||||
https://github.com/netbirdio/docs/pull/__
|
||||
|
||||
## E2E tests
|
||||
Optional: override the image tags used by the Playwright e2e workflow.
|
||||
Defaults to `main` when omitted.
|
||||
|
||||
management-cloud-tag: main
|
||||
reverse-proxy-tag: main
|
||||
@@ -2,31 +2,25 @@ name: build and push
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "feature/**"
|
||||
- main
|
||||
tags:
|
||||
- "**"
|
||||
pull_request:
|
||||
|
||||
# Cancel in-progress runs on the same ref (PR or branch) when a new commit
|
||||
# arrives, so we don't waste CI building superseded commits.
|
||||
concurrency:
|
||||
group: build-and-push-${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
DOCKERHUB_IMAGE: netbirdio/dashboard
|
||||
GHCR_IMAGE: ghcr.io/netbirdio/dashboard-cloud
|
||||
IMAGE_NAME: netbirdio/dashboard
|
||||
|
||||
jobs:
|
||||
build_n_push:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: setup-node
|
||||
uses: actions/setup-node@v5
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: '20'
|
||||
node-version: '18'
|
||||
cache: 'npm'
|
||||
|
||||
- name: Install dependencies
|
||||
@@ -34,96 +28,34 @@ jobs:
|
||||
|
||||
- run: echo '{}' > .local-config.json
|
||||
|
||||
- name: Download IronRDP release TS files
|
||||
uses: robinraju/release-downloader@v1.7
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
repository: netbirdio/IronRDP
|
||||
tag: v0.0.2
|
||||
fileName: "*.ts"
|
||||
out-file-path: 'public/ironrdp-pkg'
|
||||
|
||||
- name: Download IronRDP release JS files
|
||||
uses: robinraju/release-downloader@v1.7
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
repository: netbirdio/IronRDP
|
||||
tag: v0.0.2
|
||||
fileName: "*.js"
|
||||
out-file-path: 'public/ironrdp-pkg'
|
||||
|
||||
- name: Download IronRDP release WASM file
|
||||
uses: robinraju/release-downloader@v1.7
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
repository: netbirdio/IronRDP
|
||||
tag: v0.0.2
|
||||
fileName: "ironrdp_web_bg.wasm"
|
||||
out-file-path: 'public/ironrdp-pkg'
|
||||
|
||||
- name: Get version from tag
|
||||
id: version
|
||||
run: |
|
||||
if [[ "${{ github.ref }}" == refs/tags/* ]]; then
|
||||
echo "version=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "version=development" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Build
|
||||
run: npm run build
|
||||
env:
|
||||
NEXT_PUBLIC_DASHBOARD_VERSION: ${{ steps.version.outputs.version }}
|
||||
-
|
||||
name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
uses: docker/setup-qemu-action@v2
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
uses: docker/setup-buildx-action@v2
|
||||
-
|
||||
name: Docker meta
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
uses: docker/metadata-action@v4
|
||||
with:
|
||||
images: |
|
||||
${{ env.DOCKERHUB_IMAGE }}
|
||||
${{ env.GHCR_IMAGE }}
|
||||
flavor: |
|
||||
latest=false
|
||||
tags: |
|
||||
type=schedule
|
||||
type=ref,event=branch
|
||||
type=ref,event=tag
|
||||
type=raw,value=latest,enable=${{ startsWith(github.ref, 'refs/tags/') }}
|
||||
type=ref,event=pr
|
||||
type=sha
|
||||
|
||||
- name: Log in to Docker Hub
|
||||
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository
|
||||
uses: docker/login-action@v3
|
||||
images: ${{ env.IMAGE_NAME }}
|
||||
-
|
||||
name: Login to DockerHub
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.NB_DOCKER_USER }}
|
||||
password: ${{ secrets.NB_DOCKER_TOKEN }}
|
||||
|
||||
- name: Log in to the GitHub Container registry
|
||||
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build and push Docker image
|
||||
uses: docker/build-push-action@v5
|
||||
-
|
||||
name: Docker build and push
|
||||
uses: docker/build-push-action@v3
|
||||
with:
|
||||
context: .
|
||||
file: docker/Dockerfile
|
||||
push: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository }}
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
platforms: linux/amd64,linux/arm64,linux/arm
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
|
||||
- if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository
|
||||
run: |
|
||||
echo '### Pushed tags' >> $GITHUB_STEP_SUMMARY
|
||||
echo '${{ steps.meta.outputs.tags }}' >> $GITHUB_STEP_SUMMARY
|
||||
@@ -1,81 +0,0 @@
|
||||
name: Bump netbird wasm client
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
tag:
|
||||
description: 'NetBird release tag (e.g. v0.78.0)'
|
||||
required: true
|
||||
type: string
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ inputs.tag }}
|
||||
cancel-in-progress: false
|
||||
|
||||
jobs:
|
||||
bump:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: main
|
||||
token: ${{ secrets.NETBIRD_DEV_BOT_GITHUB_TOKEN }}
|
||||
|
||||
- name: Configure git
|
||||
run: |
|
||||
git config --global user.email "dev@netbird.io"
|
||||
git config --global user.name "netbirddev"
|
||||
|
||||
# The tag rides in env and is validated before use, so a crafted dispatch
|
||||
# input cannot expand into shell source or reach the sed expression.
|
||||
- name: Update the default wasm path
|
||||
id: bump
|
||||
env:
|
||||
TAG: ${{ inputs.tag }}
|
||||
run: |
|
||||
if [[ ! "$TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
||||
echo "Refusing tag '$TAG': expected vMAJOR.MINOR.PATCH"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
sed -i "s|https://pkgs.netbird.io/wasm/client/v[0-9.]*|https://pkgs.netbird.io/wasm/client/${TAG}|" src/utils/config.ts
|
||||
|
||||
branch="bump-netbird-wasm-${TAG#v}"
|
||||
echo "branch=${branch}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
# The branch name is derived from the tag, so a re-dispatch of the
|
||||
# same release would collide with the branch and pull request an
|
||||
# earlier run left behind.
|
||||
if git ls-remote --exit-code --heads origin "${branch}" >/dev/null 2>&1; then
|
||||
echo "skip=true" >> "$GITHUB_OUTPUT"
|
||||
echo "Branch ${branch} already exists, ${TAG} was handled by an earlier run"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
git checkout -b "${branch}"
|
||||
git add src/utils/config.ts
|
||||
if git diff --cached --quiet; then
|
||||
echo "skip=true" >> "$GITHUB_OUTPUT"
|
||||
echo "Default wasm path already at ${TAG}, nothing to do"
|
||||
exit 0
|
||||
fi
|
||||
echo "skip=false" >> "$GITHUB_OUTPUT"
|
||||
git commit -m "Bump the WASM client to ${TAG}"
|
||||
git push --set-upstream origin "${branch}"
|
||||
|
||||
- name: Create pull request
|
||||
if: steps.bump.outputs.skip != 'true'
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.NETBIRD_DEV_BOT_GITHUB_TOKEN }}
|
||||
TAG: ${{ inputs.tag }}
|
||||
BRANCH: ${{ steps.bump.outputs.branch }}
|
||||
run: |
|
||||
gh pr create \
|
||||
--base main \
|
||||
--head "$BRANCH" \
|
||||
--title "Bump the WASM client to ${TAG}" \
|
||||
--body "Automated wasm path bump triggered by netbird release ${TAG}."
|
||||
@@ -1,105 +0,0 @@
|
||||
name: Docs Acknowledgement
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, edited, synchronize]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: read
|
||||
|
||||
jobs:
|
||||
docs-ack:
|
||||
name: Require docs PR URL or explicit "not needed"
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Read PR body
|
||||
id: body
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
BODY_B64=$(jq -r '.pull_request.body // "" | @base64' "$GITHUB_EVENT_PATH")
|
||||
{
|
||||
echo "body_b64=$BODY_B64"
|
||||
} >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Validate checkbox selection
|
||||
id: validate
|
||||
shell: bash
|
||||
env:
|
||||
BODY_B64: ${{ steps.body.outputs.body_b64 }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
if ! body="$(printf '%s' "$BODY_B64" | base64 -d)"; then
|
||||
echo "::error::Failed to decode PR body from base64. Data may be corrupted or missing."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
added_checked=$(printf '%s' "$body" | grep -Ei '^[[:space:]]*-\s*\[x\]\s*I added/updated documentation' | wc -l | tr -d '[:space:]' || true)
|
||||
noneed_checked=$(printf '%s' "$body" | grep -Ei '^[[:space:]]*-\s*\[x\]\s*Documentation is \*\*not needed\*\*' | wc -l | tr -d '[:space:]' || true)
|
||||
|
||||
total=$((added_checked + noneed_checked))
|
||||
if [ "$total" -ne 1 ]; then
|
||||
echo "::error::You must check exactly one docs option in the PR template (either 'docs added' OR 'not needed')."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$added_checked" -eq 1 ]; then
|
||||
echo "mode=added" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "mode=noneed" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
||||
- name: Extract docs PR URL (when 'docs added')
|
||||
if: steps.validate.outputs.mode == 'added'
|
||||
id: extract
|
||||
shell: bash
|
||||
env:
|
||||
BODY_B64: ${{ steps.body.outputs.body_b64 }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
body="$(printf '%s' "$BODY_B64" | base64 -d)"
|
||||
|
||||
# Strictly require HTTPS and that it's a PR in netbirdio/docs
|
||||
# e.g., https://github.com/netbirdio/docs/pull/1234
|
||||
url="$(printf '%s' "$body" | grep -Eo 'https://github\.com/netbirdio/docs/pull/[0-9]+' | head -n1 || true)"
|
||||
|
||||
if [ -z "${url:-}" ]; then
|
||||
echo "::error::You checked 'docs added' but didn't include a valid HTTPS PR link to netbirdio/docs (e.g., https://github.com/netbirdio/docs/pull/1234)."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
pr_number="$(printf '%s' "$url" | sed -E 's#.*/pull/([0-9]+)$#\1#')"
|
||||
{
|
||||
echo "url=$url"
|
||||
echo "pr_number=$pr_number"
|
||||
} >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Verify docs PR exists (and is open or merged)
|
||||
if: steps.validate.outputs.mode == 'added'
|
||||
uses: actions/github-script@v7
|
||||
id: verify
|
||||
env:
|
||||
PR_NUMBER: ${{ steps.extract.outputs.pr_number }}
|
||||
with:
|
||||
script: |
|
||||
const prNumber = parseInt(process.env.PR_NUMBER, 10);
|
||||
const { data } = await github.rest.pulls.get({
|
||||
owner: 'netbirdio',
|
||||
repo: 'docs',
|
||||
pull_number: prNumber
|
||||
});
|
||||
|
||||
// Allow open or merged PRs
|
||||
const ok = data.state === 'open' || data.merged === true;
|
||||
core.setOutput('state', data.state);
|
||||
core.setOutput('merged', String(!!data.merged));
|
||||
if (!ok) {
|
||||
core.setFailed(`Docs PR #${prNumber} exists but is neither open nor merged (state=${data.state}, merged=${data.merged}).`);
|
||||
}
|
||||
result-encoding: string
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: All good
|
||||
run: echo "Documentation requirement satisfied ✅"
|
||||
@@ -1,206 +0,0 @@
|
||||
name: Playwright E2E Tests
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
pull_request:
|
||||
# `edited` is included so that updating the PR description (e.g. to set
|
||||
# `management-cloud-tag: <tag>` or `reverse-proxy-tag: <tag>`) re-triggers
|
||||
# the e2e run with the new tag.
|
||||
types: [opened, synchronize, reopened, edited]
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
management-cloud-tag:
|
||||
description: 'Management Cloud image tag'
|
||||
required: true
|
||||
type: string
|
||||
default: 'main'
|
||||
reverse-proxy-tag:
|
||||
description: 'Reverse Proxy image tag'
|
||||
required: true
|
||||
type: string
|
||||
default: 'main'
|
||||
|
||||
env:
|
||||
REGISTRY: ghcr.io
|
||||
|
||||
jobs:
|
||||
playwright-run:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha || github.ref }}
|
||||
fetch-depth: 0
|
||||
|
||||
- name: setup-node
|
||||
uses: actions/setup-node@v5
|
||||
with:
|
||||
node-version: '20'
|
||||
cache: 'npm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm install
|
||||
|
||||
- name: Install Playwright browsers
|
||||
run: npx playwright install --with-deps chromium
|
||||
|
||||
- name: Log in to the Container registry
|
||||
uses: docker/login-action@v4
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.CI_DOCKER_PULL_GITHUB_TOKEN }}
|
||||
|
||||
- run: echo '{}' > .local-config.json
|
||||
|
||||
- name: Install jq
|
||||
run: sudo apt-get install jq
|
||||
|
||||
- name: Resolve management-cloud image tag
|
||||
id: management_tag
|
||||
env:
|
||||
INPUT_TAG: ${{ inputs.management-cloud-tag }}
|
||||
PR_BODY: ${{ github.event.pull_request.body }}
|
||||
run: |
|
||||
# Use workflow_dispatch input if provided, otherwise parse PR body.
|
||||
# Falls back to `main` when not specified.
|
||||
if [ -n "$INPUT_TAG" ]; then
|
||||
TAG="$INPUT_TAG"
|
||||
else
|
||||
TAG=$(printf '%s' "$PR_BODY" \
|
||||
| grep -iE '^[[:space:]]*management-cloud-tag:[[:space:]]*[A-Za-z0-9._-]+[[:space:]]*$' \
|
||||
| head -n1 \
|
||||
| sed -E 's/^[[:space:]]*[Mm]anagement-cloud-tag:[[:space:]]*([A-Za-z0-9._-]+)[[:space:]]*$/\1/' \
|
||||
|| true)
|
||||
if [ -z "$TAG" ]; then
|
||||
TAG="main"
|
||||
fi
|
||||
fi
|
||||
echo "Using management-cloud tag: $TAG"
|
||||
echo "tag=$TAG" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Resolve reverse-proxy image tag
|
||||
id: reverse_proxy_tag
|
||||
env:
|
||||
INPUT_TAG: ${{ inputs.reverse-proxy-tag }}
|
||||
PR_BODY: ${{ github.event.pull_request.body }}
|
||||
run: |
|
||||
if [ -n "$INPUT_TAG" ]; then
|
||||
TAG="$INPUT_TAG"
|
||||
else
|
||||
TAG=$(printf '%s' "$PR_BODY" \
|
||||
| grep -iE '^[[:space:]]*reverse-proxy-tag:[[:space:]]*[A-Za-z0-9._-]+[[:space:]]*$' \
|
||||
| head -n1 \
|
||||
| sed -E 's/^[[:space:]]*[Rr]everse-proxy-tag:[[:space:]]*([A-Za-z0-9._-]+)[[:space:]]*$/\1/' \
|
||||
|| true)
|
||||
if [ -z "$TAG" ]; then
|
||||
TAG="main"
|
||||
fi
|
||||
fi
|
||||
echo "Using reverse-proxy tag: $TAG"
|
||||
echo "tag=$TAG" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Restore geolocation database cache
|
||||
id: geo-cache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: e2e/environment/geo-cache
|
||||
key: geolite-dbs-v1
|
||||
|
||||
- name: Build dashboard and set up test environment
|
||||
env:
|
||||
MANAGEMENT_IMAGE_TAG: ${{ steps.management_tag.outputs.tag }}
|
||||
REVERSE_PROXY_IMAGE_TAG: ${{ steps.reverse_proxy_tag.outputs.tag }}
|
||||
# The docker environment (image pulls, Zitadel bootstrap) is
|
||||
# network-bound and the Next build is CPU-bound, so they overlap.
|
||||
# The build reads .test-config.json via the @/config/test alias,
|
||||
# and create-test-env.sh renders that file only after the Zitadel
|
||||
# bootstrap — so the build waits for it before starting.
|
||||
run: |
|
||||
(cd ./e2e/environment && bash create-test-env.sh) > env-setup.log 2>&1 &
|
||||
ENV_PID=$!
|
||||
until [ -s .test-config.json ] && jq empty .test-config.json 2>/dev/null; do
|
||||
if ! kill -0 "$ENV_PID" 2>/dev/null; then break; fi
|
||||
sleep 2
|
||||
done
|
||||
if ! [ -s .test-config.json ]; then
|
||||
echo "::error::create-test-env.sh exited before rendering .test-config.json"
|
||||
cat env-setup.log
|
||||
exit 1
|
||||
fi
|
||||
# Lowest CPU priority: the containers must win the scheduler, or
|
||||
# the build can starve management past the proxy-registration wait.
|
||||
if ! nice -n 19 env APP_ENV=test npx next build; then
|
||||
kill "$ENV_PID" 2>/dev/null || true
|
||||
exit 1
|
||||
fi
|
||||
if ! wait "$ENV_PID"; then
|
||||
echo "::error::Test environment setup failed"
|
||||
cat env-setup.log
|
||||
exit 1
|
||||
fi
|
||||
cat env-setup.log
|
||||
|
||||
# Saved right after env setup rather than in a post step, so a later
|
||||
# test failure doesn't lose the cache.
|
||||
- name: Save geolocation database cache
|
||||
if: always() && steps.geo-cache.outputs.cache-hit != 'true' && hashFiles('e2e/environment/geo-cache/**') != ''
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: e2e/environment/geo-cache
|
||||
key: geolite-dbs-v1
|
||||
|
||||
- name: Run Playwright tests
|
||||
id: playwright
|
||||
run: |
|
||||
set -o pipefail
|
||||
npx playwright test --config=e2e/playwright.config.ts 2>&1 | tee playwright-output.log
|
||||
|
||||
- name: Append Playwright summary to job summary
|
||||
if: always() && hashFiles('e2e/test-results/results.json') != ''
|
||||
run: |
|
||||
if [ -f e2e/test-results/results.json ]; then
|
||||
passed=$(jq '.stats.expected // 0' e2e/test-results/results.json)
|
||||
failed=$(jq '.stats.unexpected // 0' e2e/test-results/results.json)
|
||||
skipped=$(jq '.stats.skipped // 0' e2e/test-results/results.json)
|
||||
duration=$(jq '.stats.duration // 0' e2e/test-results/results.json)
|
||||
{
|
||||
echo '### Playwright results'
|
||||
echo ''
|
||||
echo "| Passed | Failed | Skipped | Duration |"
|
||||
echo "|--------|--------|---------|----------|"
|
||||
echo "| $passed | $failed | $skipped | ${duration}ms |"
|
||||
} >> "$GITHUB_STEP_SUMMARY"
|
||||
fi
|
||||
|
||||
- name: Collect container logs
|
||||
if: failure()
|
||||
run: |
|
||||
cd e2e/environment
|
||||
docker compose logs management --tail=500 --no-color > management.log 2>&1 || true
|
||||
docker compose logs reverse-proxy --tail=500 --no-color > reverse-proxy.log 2>&1 || true
|
||||
|
||||
- uses: actions/upload-artifact@v7
|
||||
if: ${{ !cancelled() }}
|
||||
with:
|
||||
name: playwright-report
|
||||
path: e2e/playwright-report/
|
||||
|
||||
- uses: actions/upload-artifact@v7
|
||||
if: ${{ failure() }}
|
||||
with:
|
||||
name: playwright-traces
|
||||
path: e2e/test-results/
|
||||
|
||||
- uses: actions/upload-artifact@v7
|
||||
if: ${{ failure() }}
|
||||
with:
|
||||
name: management-logs
|
||||
path: e2e/environment/management.log
|
||||
|
||||
- uses: actions/upload-artifact@v7
|
||||
if: ${{ failure() }}
|
||||
with:
|
||||
name: reverse-proxy-logs
|
||||
path: e2e/environment/reverse-proxy.log
|
||||
@@ -1,34 +0,0 @@
|
||||
name: Sync deploy templates to S3
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
paths:
|
||||
- "templates/reverse-proxy/**"
|
||||
|
||||
permissions:
|
||||
id-token: write
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
sync:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- uses: aws-actions/configure-aws-credentials@v4
|
||||
with:
|
||||
role-to-assume: ${{ secrets.DEPLOY_TEMPLATES_ROLE_ARN }}
|
||||
aws-region: eu-central-1
|
||||
|
||||
- name: Validate CloudFormation template
|
||||
run: |
|
||||
aws cloudformation validate-template \
|
||||
--template-body file://templates/reverse-proxy/netbird-proxy-cfn.yaml
|
||||
|
||||
- name: Upload CloudFormation template
|
||||
run: |
|
||||
aws s3 cp templates/reverse-proxy/netbird-proxy-cfn.yaml \
|
||||
s3://netbird-deploy-templates/templates/netbird-proxy-cfn.yaml
|
||||
@@ -1,78 +0,0 @@
|
||||
name: Test cloud deploy config
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- "docker/init_react_envs.sh"
|
||||
- "templates/reverse-proxy/**"
|
||||
- "src/modules/reverse-proxy/clusters/ClusterCloudDeploy.tsx"
|
||||
- ".github/workflows/test-cloud-deploy.yml"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
csp-connect-src:
|
||||
name: CSP allows cloud provider APIs
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install nginx
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y nginx gettext-base
|
||||
|
||||
- name: Prepare nginx layout expected by the init script
|
||||
run: |
|
||||
sudo mkdir -p /etc/nginx/http.d /usr/share/nginx/html
|
||||
echo 'add_header Content-Security-Policy "placeholder" always;' | sudo tee /etc/nginx/http.d/default.conf
|
||||
sudo touch /usr/share/nginx/html/OidcTrustedDomains.js.tmpl
|
||||
sudo systemctl start nginx
|
||||
|
||||
- name: Run init script with production-like env
|
||||
env:
|
||||
AUTH_AUTHORITY: https://auth.example.com
|
||||
AUTH_CLIENT_ID: test-client
|
||||
AUTH_AUDIENCE: test-audience
|
||||
AUTH_SUPPORTED_SCOPES: openid profile email
|
||||
USE_AUTH0: "false"
|
||||
NETBIRD_MGMT_API_ENDPOINT: https://api.example.com
|
||||
run: sudo -E bash docker/init_react_envs.sh
|
||||
|
||||
- name: Assert provider APIs are in connect-src
|
||||
run: |
|
||||
CSP=$(grep -o 'Content-Security-Policy "[^"]*"' /etc/nginx/http.d/default.conf)
|
||||
echo "Generated CSP: $CSP"
|
||||
CONNECT_SRC=$(echo "$CSP" | sed 's/.*connect-src \([^;]*\);.*/\1/')
|
||||
echo "connect-src: $CONNECT_SRC"
|
||||
status=0
|
||||
for origin in https://api.hetzner.cloud https://api.digitalocean.com; do
|
||||
if echo "$CONNECT_SRC" | grep -qF "$origin"; then
|
||||
echo "OK: $origin"
|
||||
else
|
||||
echo "MISSING in connect-src: $origin"
|
||||
status=1
|
||||
fi
|
||||
done
|
||||
exit $status
|
||||
|
||||
cfn-template-url:
|
||||
name: CloudFormation template URL is live
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Extract template URL from component and check it
|
||||
run: |
|
||||
URL=$(grep -o 'https://[^"]*netbird-proxy-cfn\.yaml' src/modules/reverse-proxy/clusters/ClusterCloudDeploy.tsx)
|
||||
echo "CFN_TEMPLATE_URL: $URL"
|
||||
test -n "$URL"
|
||||
# Non-blocking: the template is published by sync-deploy-templates on
|
||||
# the default branch, so it may not exist yet for a PR that only edits
|
||||
# the URL. Warn instead of failing the check.
|
||||
if curl -sfI "$URL" >/dev/null; then
|
||||
echo "OK: template URL is live"
|
||||
else
|
||||
echo "::warning::CloudFormation template URL is not reachable yet: $URL"
|
||||
fi
|
||||
@@ -1,32 +0,0 @@
|
||||
name: Unit Tests
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
|
||||
# Cancel superseded runs on the same ref so a new push doesn't queue behind an
|
||||
# outdated one (mirrors build_and_push.yml).
|
||||
concurrency:
|
||||
group: unit-tests-${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
vitest:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: setup-node
|
||||
uses: actions/setup-node@v5
|
||||
with:
|
||||
node-version: '20'
|
||||
cache: 'npm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Run unit tests
|
||||
run: npm run test:unit
|
||||
+1
-14
@@ -36,21 +36,8 @@ yarn-error.log*
|
||||
next-env.d.ts
|
||||
|
||||
# config
|
||||
.local*config*.json
|
||||
.test-config.json
|
||||
e2e/playwright.env.json
|
||||
e2e/fixtures/auth/*.json
|
||||
e2e/test-results/
|
||||
e2e/playwright-report/
|
||||
/test-results/
|
||||
/playwright-report/
|
||||
playwright-report*.zip
|
||||
.local-config.json
|
||||
.configs/.local-config.zitadel.json
|
||||
.configs/.staging-config.json
|
||||
.configs/.temp-config.json
|
||||
.configs
|
||||
|
||||
/public/ironrdp-pkg/
|
||||
/public/netbird.wasm
|
||||
.idea
|
||||
src/.local-config*
|
||||
@@ -1,3 +1,3 @@
|
||||
Mikhail Bragin (https://github.com/braginini)
|
||||
Maycon Santos (https://github.com/mlsmaycon)
|
||||
NetBird GmbH
|
||||
Wiretrustee UG (haftungsbeschränkt)
|
||||
@@ -1,64 +0,0 @@
|
||||
## Contributor License Agreement
|
||||
|
||||
This Contributor License Agreement (referred to as the "Agreement") is entered into by the individual
|
||||
submitting this Agreement and NetBird GmbH, Brunnenstraße 196, 10119 Berlin, Germany,
|
||||
referred to as "NetBird" (collectively, the "Parties"). The Agreement outlines the terms and conditions
|
||||
under which NetBird may utilize software contributions provided by the Contributor for inclusion in
|
||||
its software development projects. By submitting this Agreement, the Contributor confirms their acceptance
|
||||
of the terms and conditions outlined below. The Contributor further represents that they are authorized to
|
||||
complete this process as described herein.
|
||||
|
||||
|
||||
## 1 Preamble
|
||||
In order to clarify the IP Rights situation with regard to Contributions from any person or entity, NetBird
|
||||
must have a contributor license agreement on file to be signed by each Contributor, containing the license
|
||||
terms below. This license serves as protection for both the Contributor as well as NetBird and its software users;
|
||||
it does not change Contributor’s rights to use his/her own Contributions for any other purpose.
|
||||
|
||||
## 2 Definitions
|
||||
2.1 “IP Rights” shall mean all industrial and intellectual property rights, whether registered or not registered, whether created by Contributor or acquired by Contributor from third parties, and similar rights, including (but not limited to) semiconductor property rights, design rights, copyrights (including in the form of database rights and rights to software), all neighbouring rights (Leistungsschutzrechte), trademarks, service marks, titles, internet domain names, trade names and other labelling rights, rights deriving from corresponding applications and registrations of such rights as well as any licenses (Nutzungsrechte) under and entitlements to any such intellectual and industrial property rights.
|
||||
|
||||
2.2 "Contribution" shall mean any original work of authorship, including any modifications or additions to an existing work, that is or previously has been intentionally Submitted by Contributor to NetBird for inclusion in, or documentation of any Work.
|
||||
|
||||
2.3 "Contributor" shall mean the copyright owner or legal entity authorized by the copyright owner that is concluding this Agreement with NetBird. For legal entities, the entity making a Contribution and all other entities that control, are controlled by, or are under common control with that entity are considered to be a single Contributor. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
2.4 "Submitted" shall mean any form of electronic, verbal, or written communication sent to NetBird or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, NetBird for the purpose of discussing and improving the Work, but excluding communication that is marked or otherwise designated in writing by Contributor as "Not a Contribution".
|
||||
|
||||
2.5 "Work" means any of the products owned or managed by NetBird, in particular, but not exclusively, software.
|
||||
|
||||
## 3 Licenses
|
||||
3.1 Subject to the terms and conditions of this agreement, Contributor hereby grants to NetBird and to recipients of software distributed by NetBird a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable license to reproduce by any means and in any form, in whole or in part, permanently or temporarily, the Contributions (including loading, displaying, executing, transmitting or storing works for the purpose of executing and processing data or transferring them to video, audio and other data carriers), including the right to distribute, display and present such Contributions and make them available to the public (e.g. via the internet) and to transmit and display such Contributions by any means. The license also includes the right to modify, translate, adapt, edit and otherwise alter the Contributions and to use these results in the same manner as the original Contributions and derivative works. Except for licenses in patents acc. to Sec. 3, such license refers to any IP Rights in the Contributions and derivative works. The Contributor acknowledges that NetBird is not required to credit them by name for their Contribution and agrees to waive any moral rights associated with their Contribution in relation to NetBird or its sublicensees.
|
||||
|
||||
3.2 Subject to the terms and conditions of this agreement, Contributor hereby grants to NetBird and to recipients of software distributed by NetBird a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license in the Contributions to make, have made, use, sell, offer to sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by the Contributor which are necessarily infringed by Contributor‘s Contribution(s) alone or by combination of Contributor’s Contribution(s) with the Work to which such Contribution(s) was Submitted.
|
||||
|
||||
3.3 NetBird hereby accepts such licenses.
|
||||
|
||||
## 4 Contributor’s Representations
|
||||
4.1 Contributor represents that Contributor is legally entitled to grant the above license. If Contributor’s employer has IP Rights to Contributor’s Contributions, Contributor represent that he/she has received permission to make Contributions on behalf of such employer, that such employer has waived such IP Rights to the Contributions of Contributor to NetBird, or that such employer has executed a separate contributor license agreement with NetBird.
|
||||
|
||||
4.2 Contributor represents that any Contribution is his/her original creation.
|
||||
|
||||
4.3 Contributor represents to his/her best knowledge that any Contribution does not violate any third party IP Rights.
|
||||
|
||||
4.4 Contributor represents that any Contribution submission includes complete details of any third-party license or other restriction (including, but not limited to, related patents and trademarks) of which Contributor is personally aware and which are associated with any part of the Contribution.
|
||||
|
||||
4.5 The Contributor represents that their Contribution does not include any work distributed under a copyleft license.
|
||||
|
||||
## 5 Information obligation
|
||||
Contributor agrees to notify NetBird of any facts or circumstances of which Contributor become aware that would make these representations inaccurate in any respect.
|
||||
|
||||
## 6 Submission of Third-Party works
|
||||
Should Contributor wish to submit work that is not Contributor’s original creation, Contributor may submit it to NetBird separately from any Contribution, identifying the complete details of its source and of any license or other restriction (including, but not limited to, related patents, trademarks, and license agreements) of which Contributor are personally aware, and conspicuously marking the work as "Submitted on behalf of a third-party: [named here]".
|
||||
|
||||
## 7 No Consideration
|
||||
Unless compensation is mandatory under statutory law, no compensation for any license under this agreement shall be payable.
|
||||
|
||||
## 8 Final Provisions
|
||||
8.1 Laws. This Agreement is governed by the laws of the Federal Republic of Germany.
|
||||
|
||||
8.2 Venue. Place of jurisdiction shall, to the extent legally permissible, be Berlin, Germany.
|
||||
|
||||
8.3 Severability. If any provision in this agreement is unlawful, invalid or ineffective, it shall not affect the enforceability or effectiveness of the remainder of this agreement. The parties agree to replace any unlawful, invalid or ineffective provision with a provision that comes as close as possible to the commercial intent and purpose of the original provision. This section also applies accordingly to any gaps in the contract.
|
||||
|
||||
8.4 Variations. Any variations, amendments or supplements to this Agreement must be in writing. This also applies to any variation of this Section 8.4.
|
||||
|
||||
@@ -10,7 +10,6 @@ See [NetBird repo](https://github.com/netbirdio/netbird)
|
||||
|
||||
The purpose of this project is simple - make it easy to manage VPN built with [NetBird](https://github.com/netbirdio/netbird).
|
||||
The dashboard makes it possible to:
|
||||
|
||||
- track the status of your peers
|
||||
- remove peers
|
||||
- manage Setup Keys (to authenticate new peers)
|
||||
@@ -18,25 +17,23 @@ The dashboard makes it possible to:
|
||||
- define access controls
|
||||
|
||||
## Some Screenshots
|
||||
|
||||
<img src="./src/assets/screenshots/peers.png" alt="peers"/>
|
||||
<img src="./src/assets/screenshots/add-peer.png" alt="add-peer"/>
|
||||
|
||||
|
||||
## Technologies Used
|
||||
|
||||
- NextJS
|
||||
- ReactJS
|
||||
- Tailwind CSS
|
||||
- [React Flow](https://reactflow.dev/) for the Control Center
|
||||
- Auth0
|
||||
- Nginx
|
||||
- Docker
|
||||
- Let's Encrypt
|
||||
|
||||
## How to run
|
||||
|
||||
Disclaimer. We believe that proper user management system is not a trivial task and requires quite some effort to make it right. Therefore we decided to
|
||||
use Auth0 service that covers all our needs (user management, social login, JWT for the management API).
|
||||
use Auth0 service that covers all our needs (user management, social login, JTW for the management API).
|
||||
Auth0 so far is the only 3rd party dependency that can't be really self-hosted.
|
||||
|
||||
1. Install [Docker](https://docs.docker.com/get-docker/)
|
||||
@@ -45,9 +42,9 @@ Auth0 so far is the only 3rd party dependency that can't be really self-hosted.
|
||||
|
||||
`AUTH0_DOMAIN` `AUTH0_CLIENT_ID` `AUTH0_AUDIENCE`
|
||||
|
||||
To obtain these, please use [Auth0 React SDK Guide](https://auth0.com/docs/quickstart/spa/react) up until "Configure Allowed Web Origins"
|
||||
To obtain these, please use [Auth0 React SDK Guide](https://auth0.com/docs/quickstart/spa/react/01-login#configure-auth0) up until "Configure Allowed Web Origins"
|
||||
|
||||
4. NetBird UI Dashboard uses NetBird's Management Service HTTP API, so setting `NETBIRD_MGMT_API_ENDPOINT` is required. Most likely it will be `http://localhost:33071` if you are hosting Management API on the same server.
|
||||
4. NetBird UI Dashboard uses NetBirds Management Service HTTP API, so setting `NETBIRD_MGMT_API_ENDPOINT` is required. Most likely it will be `http://localhost:33071` if you are hosting Management API on the same server.
|
||||
5. Run docker container without SSL (Let's Encrypt):
|
||||
|
||||
```shell
|
||||
@@ -56,10 +53,9 @@ Auth0 so far is the only 3rd party dependency that can't be really self-hosted.
|
||||
-e AUTH0_DOMAIN=<SET YOUR AUTH DOMAIN> \
|
||||
-e AUTH0_CLIENT_ID=<SET YOUR CLIENT ID> \
|
||||
-e AUTH0_AUDIENCE=<SET YOUR AUDIENCE> \
|
||||
-e NETBIRD_MGMT_API_ENDPOINT=<SET YOUR MANAGEMENT API URL> \
|
||||
-e NETBIRD_MGMT_API_ENDPOINT=<SET YOUR MANAGEMETN API URL> \
|
||||
netbirdio/dashboard:main
|
||||
```
|
||||
|
||||
6. Run docker container with SSL (Let's Encrypt):
|
||||
|
||||
```shell
|
||||
@@ -71,7 +67,7 @@ Auth0 so far is the only 3rd party dependency that can't be really self-hosted.
|
||||
-e AUTH0_DOMAIN=<SET YOUR AUTH DOMAIN> \
|
||||
-e AUTH0_CLIENT_ID=<SET YOUR CLEITN ID> \
|
||||
-e AUTH0_AUDIENCE=<SET YOUR AUDIENCE> \
|
||||
-e NETBIRD_MGMT_API_ENDPOINT=<SET YOUR MANAGEMENT API URL> \
|
||||
-e NETBIRD_MGMT_API_ENDPOINT=<SET YOUR MANAGEMETN API URL> \
|
||||
netbirdio/dashboard:main
|
||||
```
|
||||
|
||||
@@ -87,11 +83,11 @@ Open [http://localhost:3000](http://localhost:3000) with your browser to see the
|
||||
You can start editing by modifying the code inside `src/..`
|
||||
The page auto-updates as you edit the file.
|
||||
|
||||
## How to migrate from old dashboard (v1)
|
||||
## How to migrate from old dashboard (v1)
|
||||
|
||||
The new dashboard comes with a new docker image `netbirdio/dashboard:main`.
|
||||
To migrate from the old dashboard (v1) `wiretrustee/dashboard:main` to the new one, please follow the steps below.
|
||||
|
||||
1. Stop the dashboard container `docker compose down dashboard`
|
||||
2. Replace the docker image name in your `docker-compose.yml` with `netbirdio/dashboard:main`
|
||||
3. Recreate the dashboard container `docker compose up -d --force-recreate dashboard`
|
||||
3. Recreate the dashboard container `docker compose up -d --force-recreate dashboard`
|
||||
@@ -1,12 +0,0 @@
|
||||
[
|
||||
{
|
||||
"tag": "New",
|
||||
"text": "The new NetBird desktop app is here - now available in the v0.75 release.",
|
||||
"link": "https://netbird.io/knowledge-hub/netbird-v0-75-new-desktop-app",
|
||||
"linkText": "Learn more",
|
||||
"variant": "important",
|
||||
"isExternal": true,
|
||||
"closeable": true,
|
||||
"isCloudOnly": false
|
||||
}
|
||||
]
|
||||
@@ -1,77 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Build the netbird-dashboard Docker image for linux/amd64 and export it as a
|
||||
# portable tarball that can be loaded and run on a remote server.
|
||||
#
|
||||
# The dashboard image is nginx serving a Next.js *static export*: the Dockerfile
|
||||
# only COPYs the pre-built out/ directory, so we build out/ on the host first
|
||||
# (the static files are arch-independent) and then assemble the amd64 image.
|
||||
#
|
||||
# Usage:
|
||||
# ./build.sh # build + export netbird-dashboard.tar.gz
|
||||
# IMAGE_TAG=v1 ./build.sh # override the image tag
|
||||
# SKIP_BUILD=1 ./build.sh # reuse an existing out/ (skip npm build)
|
||||
#
|
||||
set -euo pipefail
|
||||
|
||||
# Always run relative to this script's directory (the project root).
|
||||
cd "$(dirname "$0")"
|
||||
|
||||
IMAGE_NAME="${IMAGE_NAME:-netbird-dashboard}"
|
||||
IMAGE_TAG="${IMAGE_TAG:-amd64}"
|
||||
IMAGE="${IMAGE_NAME}:${IMAGE_TAG}"
|
||||
OUTPUT="${OUTPUT:-${IMAGE_NAME}.tar.gz}"
|
||||
|
||||
# Build the static export (out/) unless told to reuse an existing one. Next 16
|
||||
# no longer runs ESLint during `next build`; types are checked by the build via
|
||||
# tsc (verify separately with `npx tsc --noEmit`).
|
||||
if [[ "${SKIP_BUILD:-0}" != "1" ]]; then
|
||||
if [[ ! -d node_modules ]]; then
|
||||
echo "==> Installing dependencies (npm ci)"
|
||||
npm ci
|
||||
fi
|
||||
echo "==> Building static export (next build) into out/"
|
||||
npx next build
|
||||
fi
|
||||
|
||||
if [[ ! -d out ]]; then
|
||||
echo "ERROR: out/ not found — the static export did not build." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# The .dockerignore lives under docker/, but Docker reads it from the build
|
||||
# context root. Stage it for the duration of the build so node_modules/.next
|
||||
# don't get shipped into the build context.
|
||||
cleanup() { rm -f .dockerignore; }
|
||||
trap cleanup EXIT
|
||||
cp docker/.dockerignore .dockerignore
|
||||
|
||||
echo "==> Building ${IMAGE} for linux/amd64"
|
||||
docker build \
|
||||
--platform linux/amd64 \
|
||||
-f docker/Dockerfile \
|
||||
-t "${IMAGE}" \
|
||||
.
|
||||
|
||||
echo "==> Exporting ${IMAGE} to ${OUTPUT}"
|
||||
docker save "${IMAGE}" | gzip > "${OUTPUT}"
|
||||
|
||||
echo "==> Done: ${OUTPUT} ($(du -h "${OUTPUT}" | cut -f1))"
|
||||
echo
|
||||
echo "Copy and run on the server:"
|
||||
echo " scp ${OUTPUT} user@your-server:/tmp/"
|
||||
echo " docker load < /tmp/${OUTPUT}"
|
||||
echo
|
||||
echo "Run (nginx serves on container port 80). Set the runtime env vars the"
|
||||
echo "dashboard templates at startup — for the Agent Network onboarding test,"
|
||||
echo "flip NETBIRD_AGENT_NETWORK_ONLY=true:"
|
||||
echo " docker run -d --name ${IMAGE_NAME} --restart unless-stopped \\"
|
||||
echo " -p 8080:80 \\"
|
||||
echo " -e NETBIRD_MGMT_API_ENDPOINT=https://your-mgmt:443 \\"
|
||||
echo " -e AUTH_AUTHORITY=https://your-idp/realms/netbird \\"
|
||||
echo " -e AUTH_CLIENT_ID=netbird-dashboard \\"
|
||||
echo " -e AUTH_AUDIENCE=netbird-dashboard \\"
|
||||
echo " -e AUTH_SUPPORTED_SCOPES='openid profile email' \\"
|
||||
echo " -e USE_AUTH0=false \\"
|
||||
echo " -e NETBIRD_AGENT_NETWORK_ONLY=true \\"
|
||||
echo " ${IMAGE}"
|
||||
+2
-13
@@ -13,16 +13,5 @@
|
||||
"dragQueryParams": "$NETBIRD_DRAG_QUERY_PARAMS",
|
||||
"hotjarTrackID": "$NETBIRD_HOTJAR_TRACK_ID",
|
||||
"googleAnalyticsID": "$NETBIRD_GOOGLE_ANALYTICS_ID",
|
||||
"googleTagManagerID": "$NETBIRD_GOOGLE_TAG_MANAGER_ID",
|
||||
"authServiceUrl": "$NETBIRD_AUTH_SERVICE_URL",
|
||||
"wasmPath": "$NETBIRD_WASM_PATH",
|
||||
"licensed": "$NETBIRD_LICENSED",
|
||||
"cloud": "$NETBIRD_CLOUD",
|
||||
"agentNetworkOnly": "$NETBIRD_AGENT_NETWORK_ONLY",
|
||||
"agentNetworkEnabled": "$NETBIRD_AGENT_NETWORK_ENABLED",
|
||||
"hubspotPortalId": "$NETBIRD_HUBSPOT_PORTAL_ID",
|
||||
"hubspotSignupFormId": "$NETBIRD_HUBSPOT_SIGNUP_FORM_ID",
|
||||
"hubspotOnboardingFormId": "$NETBIRD_HUBSPOT_ONBOARDING_FORM_ID",
|
||||
"hubspotSurveyFormId": "$NETBIRD_HUBSPOT_SURVEY_FORM_ID",
|
||||
"analyticsExcludedEmails": "$NETBIRD_ANALYTICS_EXCLUDED_EMAILS"
|
||||
}
|
||||
"authServiceUrl": "$NETBIRD_AUTH_SERVICE_URL"
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
import { defineConfig } from "cypress";
|
||||
|
||||
export default defineConfig({
|
||||
e2e: {
|
||||
baseUrl: "http://localhost:3000",
|
||||
},
|
||||
component: {
|
||||
devServer: {
|
||||
framework: "next",
|
||||
bundler: "webpack",
|
||||
},
|
||||
},
|
||||
viewportWidth: 1920,
|
||||
viewportHeight: 1080,
|
||||
});
|
||||
@@ -0,0 +1,13 @@
|
||||
describe("Click all tabs in peer modal", () => {
|
||||
it("passes", () => {
|
||||
cy.visit("/install");
|
||||
cy.get("div").contains("Linux").click();
|
||||
cy.get("[data-cy=copy-to-clipboard]").click();
|
||||
cy.get("div").contains("Windows").click();
|
||||
cy.get("[data-cy=copy-to-clipboard]").click();
|
||||
cy.get("div").contains("Android").click();
|
||||
cy.get("[data-cy=copy-to-clipboard]").click();
|
||||
cy.get("div").contains("Docker").click();
|
||||
cy.get("[data-cy=copy-to-clipboard]").click();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"name": "Using fixtures to represent data",
|
||||
"email": "hello@cypress.io",
|
||||
"body": "Fixtures are a great way to mock data for responses to routes"
|
||||
}
|
||||
Loaded 20 of 1174 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user