Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 37 additions & 7 deletions .github/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,21 +29,27 @@ You can then start the server with `node build`.
<details>
<summary>More Deployment Options</summary>

#### Option 4 - Source: Static
#### Option 4 - GitHub Pages
Fork the repo.<br>
Head to the Actions tab, find the "Deploy to GitHub Pages" workflow, and trigger it.<br>
Then go to Settings > Pages > Source and select the `gh-pages` branch.<br>
Visit `https://<your-username>.github.io/networking-toolbox/` to see your deployed app.

#### Option 5 - Source: Static
Follow the dev steps below.
Then run `npm run build:static` to compile output.<br>
And upload the contents of `./build` to any web server, CDN or static host.

#### Option 5 - Source: Docker
#### Option 6 - Source: Docker
Follow the dev steps below.
Then run `docker build -t networking-toolbox .` to build the image.<br>
You can then start the container with `docker run -p 8080:80 networking-toolbox`.

#### Option 6 - GitHub Pages
Fork the repo.<br>
Head to the Actions tab, find the "Deploy to GitHub Pages" workflow, and trigger it.<br>
Then go to Settings > Pages > Source and select the `gh-pages` branch.<br>
Visit `https://<your-username>.github.io/networking-toolbox/` to see your deployed app.
#### Option 7 - Source: Other Platforms
You can build the app from source for a variety of platforms. This is done via SvelteKit adapters.<br>
First, follow the dev steps below.
Then, simply set the `DEPLOY_ENV` environmental variable, to one of `vercel`, `node`, `docker`, `netlify`, `static` or just `auto`, and build the app<br>
For example: `DEPLOY_ENV='node' npm run build`
</details>

---
Expand Down Expand Up @@ -71,6 +77,30 @@ Before merging, code must pass all unit and end-to-end tests, as well as linting
yarn test
```

<details>
<summary><h4>Project Commands</h4></summary>

##### Building
- `npm run dev` - Starts the development server with hot reload/HMR
- `npm run build` - Builds the app for production
- Note: choose adapter for platform by setting the `DEPLOY_ENV` var (see above)
- `npm run preview` - Test your build locally (build required first)
- `npm start` - Starts the production app (build required first)

##### Testing
- `npm test` — Run unit tests with Vitest
- `npm run test:api` — Run API tests
- `npm run test:e2e` — Run Playwright end-to-end tests
- `npm run test:coverage` — Generate test coverage

##### Checking
- `npm run check` — SvelteKit checks (types & diagnostics)
- `npm run types` — TypeScript-specific strict checking
- `npm run lint` — ESLint on all TS and Svelte files
- `npm run format` — Format files with Prettier
- `npm run build-check` — Quitley check build works
</details>

---

### Contributing
Expand Down
30 changes: 22 additions & 8 deletions .github/workflows/docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,7 @@ on:
type: boolean

env:
REPO_NAME: 'lissy93/networking-toolbox'
# REPO_NAME: ${{ vars.REPO_NAME || github.repository }}
REPO_NAME: ${{ github.repository }}

jobs:
build:
Expand Down Expand Up @@ -77,23 +76,38 @@ jobs:
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: 📋 Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ghcr.io/${{ env.REPO_NAME }}
tags: |
type=raw,value=${{ steps.tags.outputs.tags }}
labels: |
org.opencontainers.image.title=Networking Toolbox
org.opencontainers.image.description=All-in-one Swiss Army knife for sysadmins and network engineers - a collection of 100+ offline-first essential networking tools in a single, easy-to-use Docker image.
org.opencontainers.image.url=https://github.com/${{ github.repository }}
org.opencontainers.image.source=https://github.com/${{ github.repository }}
org.opencontainers.image.vendor=${{ github.repository_owner }}

- name: 🔨 Build and push
if: steps.tags.outputs.tags != ''
uses: docker/build-push-action@v6
with:
context: .
platforms: linux/amd64,linux/arm64
push: ${{ !inputs.dry_run }}
push: ${{ !inputs.dry_run && github.event_name != 'pull_request' }}
tags: ${{ steps.tags.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
labels: |
org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }}
org.opencontainers.image.revision=${{ github.sha }}
org.opencontainers.image.created=${{ github.event.head_commit.timestamp }}
build-args: |
BUILDTIME=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.created'] }}
VERSION=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.version'] }}
REVISION=${{ github.sha }}

- name: ⚠️ Warning if skipped
if: steps.tags.outputs.tags == ''
Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/mirror.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,5 @@ jobs:
chmod 600 ~/.ssh/id_rsa
ssh-keyscan codeberg.org >> ~/.ssh/known_hosts
git remote add mirror ${{ env.MIRROR_HOST }}:${{ env.MIRROR_USER }}/${{ env.MIRROR_REPO }}.git || true
git push mirror --mirror
git push mirror --all
git push mirror --tags
64 changes: 47 additions & 17 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
name: 🧪 Run Tests

on:
pull_request:
pull_request_target:
types: [opened, synchronize, reopened]
push:
branches: [main]
workflow_dispatch:

concurrency:
group: ci-${{ github.ref }}
Expand All @@ -14,6 +16,12 @@ permissions:
id-token: write # For OIDC with Codecov
checks: write # For test reporting

env:
# PR context helpers for conditional logic
IS_PR: ${{ github.event_name == 'pull_request_target' }}
IS_FORK: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.repo.full_name != github.repository }}
HAS_BOT_TOKEN: ${{ secrets.BOT_TOKEN != '' }}

jobs:
unit-tests:
name: Unit Tests
Expand All @@ -22,7 +30,12 @@ jobs:
NODE_OPTIONS: "--max_old_space_size=8192"

steps:
# Secure checkout for external PRs
- uses: actions/checkout@v4
with:
# For PRs from forks, check out the PR head to prevent token exposure
ref: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.sha || github.ref }}

- uses: actions/setup-node@v4
with:
node-version: 22
Expand All @@ -33,6 +46,7 @@ jobs:
id: test
run: |
npx vitest run \
--coverage \
--reporter=github-actions \
--reporter=verbose \
--reporter=junit \
Expand All @@ -51,7 +65,7 @@ jobs:
path: test-result-unit.txt

- name: Upload coverage to Codecov
if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name == github.repository
if: github.event_name == 'push' || github.event_name == 'workflow_dispatch' || github.event.pull_request.head.repo.full_name == github.repository
uses: codecov/codecov-action@v4
with:
token: ${{ secrets.CODECOV_TOKEN }}
Expand All @@ -64,20 +78,22 @@ jobs:
- name: Unit Test Report
id: unit-test-report
uses: dorny/test-reporter@v1
if: always()
if: always() && (env.IS_FORK != 'true' || env.HAS_BOT_TOKEN == 'true')
with:
name: Unit Tests
path: test-results.xml
reporter: java-junit
fail-on-error: false
token: ${{ env.IS_FORK == 'true' && secrets.BOT_TOKEN || secrets.GITHUB_TOKEN }}
continue-on-error: true

- name: Save unit test report data
if: always()
run: |
echo "passed=${{ steps.unit-test-report.outputs.passed }}" > unit-report-data.txt
echo "failed=${{ steps.unit-test-report.outputs.failed }}" >> unit-report-data.txt
echo "skipped=${{ steps.unit-test-report.outputs.skipped }}" >> unit-report-data.txt
echo "time=${{ steps.unit-test-report.outputs.time }}" >> unit-report-data.txt
echo "passed=${{ steps.unit-test-report.outputs.passed || '0' }}" > unit-report-data.txt
echo "failed=${{ steps.unit-test-report.outputs.failed || '0' }}" >> unit-report-data.txt
echo "skipped=${{ steps.unit-test-report.outputs.skipped || '0' }}" >> unit-report-data.txt
echo "time=${{ steps.unit-test-report.outputs.time || '0' }}" >> unit-report-data.txt

- name: Upload unit test report data
if: always()
Expand All @@ -104,7 +120,12 @@ jobs:
NODE_OPTIONS: "--max_old_space_size=8192"

steps:
# Secure checkout for external PRs
- uses: actions/checkout@v4
with:
# For PRs from forks, check out the PR head to prevent naughty people finding my token
ref: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.sha || github.ref }}

- uses: actions/setup-node@v4
with:
node-version: 22
Expand Down Expand Up @@ -142,20 +163,22 @@ jobs:
- name: API Test Report
id: api-test-report
uses: dorny/test-reporter@v1
if: always()
if: always() && (env.IS_FORK != 'true' || env.HAS_BOT_TOKEN == 'true')
with:
name: API Contract Tests
path: api-test-results.xml
reporter: java-junit
fail-on-error: false
token: ${{ env.IS_FORK == 'true' && secrets.BOT_TOKEN || secrets.GITHUB_TOKEN }}
continue-on-error: true

- name: Save API test report data
if: always()
run: |
echo "passed=${{ steps.api-test-report.outputs.passed }}" > api-report-data.txt
echo "failed=${{ steps.api-test-report.outputs.failed }}" >> api-report-data.txt
echo "skipped=${{ steps.api-test-report.outputs.skipped }}" >> api-report-data.txt
echo "time=${{ steps.api-test-report.outputs.time }}" >> api-report-data.txt
echo "passed=${{ steps.api-test-report.outputs.passed || '0' }}" > api-report-data.txt
echo "failed=${{ steps.api-test-report.outputs.failed || '0' }}" >> api-report-data.txt
echo "skipped=${{ steps.api-test-report.outputs.skipped || '0' }}" >> api-report-data.txt
echo "time=${{ steps.api-test-report.outputs.time || '0' }}" >> api-report-data.txt

- name: Upload API test report data
if: always()
Expand All @@ -175,7 +198,12 @@ jobs:
NODE_OPTIONS: "--max_old_space_size=8192"

steps:
# Secure checkout for external PRs
- uses: actions/checkout@v4
with:
# For PRs from forks, check out the PR head to prevent token exposure
ref: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.sha || github.ref }}

- uses: actions/setup-node@v4
with:
node-version: 22
Expand Down Expand Up @@ -219,20 +247,22 @@ jobs:
- name: E2E Test Report
id: e2e-test-report
uses: dorny/test-reporter@v1
if: always()
if: always() && (env.IS_FORK != 'true' || env.HAS_BOT_TOKEN == 'true')
with:
name: E2E Tests
path: e2e-results.xml
reporter: java-junit
fail-on-error: false
token: ${{ env.IS_FORK == 'true' && secrets.BOT_TOKEN || secrets.GITHUB_TOKEN }}
continue-on-error: true

- name: Save e2e test report data
if: always()
run: |
echo "passed=${{ steps.e2e-test-report.outputs.passed }}" > e2e-report-data.txt
echo "failed=${{ steps.e2e-test-report.outputs.failed }}" >> e2e-report-data.txt
echo "skipped=${{ steps.e2e-test-report.outputs.skipped }}" >> e2e-report-data.txt
echo "time=${{ steps.e2e-test-report.outputs.time }}" >> e2e-report-data.txt
echo "passed=${{ steps.e2e-test-report.outputs.passed || '0' }}" > e2e-report-data.txt
echo "failed=${{ steps.e2e-test-report.outputs.failed || '0' }}" >> e2e-report-data.txt
echo "skipped=${{ steps.e2e-test-report.outputs.skipped || '0' }}" >> e2e-report-data.txt
echo "time=${{ steps.e2e-test-report.outputs.time || '0' }}" >> e2e-report-data.txt

- name: Upload e2e test report data
if: always()
Expand Down
4 changes: 1 addition & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,9 @@
"build:node": "DEPLOY_ENV='node' npm run build",
"build:static": "DEPLOY_ENV='static' npm run build",
"test": "vitest",
"test:ui": "vitest --ui",
"test:coverage": "vitest --coverage",
"test:api": "vitest run --config tests/vitest.api.config.ts",
"test:e2e": "playwright test",
"test:e2e:ui": "playwright test --ui"
"test:e2e": "playwright test"
},
"dependencies": {},
"devDependencies": {
Expand Down
1 change: 1 addition & 0 deletions vitest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export default defineConfig({
'src/hooks.server.ts',
'src/service-worker.ts'
],
reporter: ['text', 'lcov', 'html'],
thresholds: {
global: {
statements: 85,
Expand Down