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
12 changes: 12 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
version: 2
updates:
# Keep the SHA-pinned GitHub Actions current (Dependabot rewrites the pin and its
# version comment). Grouped so all bumps arrive in a single PR.
- package-ecosystem: github-actions
directory: /
schedule:
interval: weekly
groups:
github-actions:
patterns:
- "*"
129 changes: 100 additions & 29 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,36 @@ on:
push:
branches:
- main
# Release flavor is derived from the tag suffix in the deploy job:
tags:
- '*.*.*' # semver, will override latest
- '*-preview' # preview, won't override latest
- '*.*.*' # stable semver (e.g. 1.2.3): published and marked "Latest"
- '*-preview' # pre-release (e.g. 1.2.3-preview): published, never "Latest"
- '*-draft' # draft (e.g. 1.2.3-draft): unpublished for review, never "Latest"
pull_request:
branches:
- main
workflow_dispatch: # Allow manual trigger

# Least privilege by default; jobs that need more elevate it explicitly (see deploy).
permissions:
contents: write
packages: write
contents: read

# Cancel superseded runs on the same ref, but only for pull requests — never abort an
# in-flight push to main or a tag (which may be mid-release).
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}

jobs:
lint:
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false

- uses: actions/setup-node@v4
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version-file: .nvmrc
cache: npm
Expand All @@ -38,20 +48,20 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
fetch-depth: 0
fetch-depth: 0 # SonarCloud needs the full history for blame/coverage
persist-credentials: false

- uses: actions/setup-node@v4
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version-file: .nvmrc
cache: npm


- name: Setup Go environment
uses: actions/setup-go@v5
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version: stable
go-version-file: go.mod

- run: npm ci

Expand All @@ -63,7 +73,7 @@ jobs:
make coverage

- name: SonarCloud Scan
uses: sonarsource/sonarcloud-github-action@master
uses: SonarSource/sonarqube-scan-action@22918119ff8e1ca75a623e15c8296b6ea4fbe28f # v8.2.1
continue-on-error: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Expand All @@ -73,20 +83,22 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false

- id: extract_ref
run: echo "GIT_REF=${GITHUB_REF##*/}" >> "$GITHUB_OUTPUT"

- uses: actions/setup-node@v4
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version-file: .nvmrc
cache: npm

- name: Setup Go environment
uses: actions/setup-go@v5
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version: stable
go-version-file: go.mod

- run: npm ci

Expand All @@ -97,7 +109,7 @@ jobs:
make VERSION=${{ steps.extract_ref.outputs.GIT_REF }} start-docker

- if: startsWith(github.ref, 'refs/tags/')
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: smocker-bin
path: ./build/smocker.tar.gz
Expand All @@ -106,17 +118,19 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false

- uses: actions/setup-node@v4
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version-file: .nvmrc
cache: npm

- name: Setup Go environment
uses: actions/setup-go@v5
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version: stable
go-version-file: go.mod

- run: npm ci

Expand All @@ -126,42 +140,99 @@ jobs:
- name: Run Playwright non-regression suite
run: make test-e2e

security:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false

- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version-file: .nvmrc
cache: npm

- name: Setup Go environment
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version-file: go.mod

# Audit only the dependencies that ship in the client bundle (dev tooling isn't
# served), and fail only on high/critical advisories.
- name: Audit frontend dependencies (npm)
run: npm audit --omit=dev --audit-level=high

# govulncheck reports only vulnerabilities actually reachable from the code, so it's
# low-noise and safe to gate on.
- name: Scan backend dependencies (govulncheck)
run: go run golang.org/x/vuln/cmd/govulncheck@latest ./...

deploy:
needs: [lint, test, build, e2e]
needs: [lint, test, build, e2e, security]
if: startsWith(github.ref, 'refs/tags/')
runs-on: ubuntu-latest
timeout-minutes: 10
# Elevated only here: push the image to GHCR and publish the GitHub release.
permissions:
contents: write
packages: write
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false

- id: extract_ref
run: echo "GIT_REF=${GITHUB_REF##*/}" >> "$GITHUB_OUTPUT"

- uses: actions/download-artifact@v4
- id: release_flags
name: Derive the release flavor from the tag suffix
run: |
ref="${GITHUB_REF##*/}"
draft=false
prerelease=false
make_latest=true
if [[ "$ref" == *-draft ]]; then
draft=true # unpublished, editable on GitHub before release
make_latest=false
elif [[ "$ref" == *-* ]]; then
prerelease=true # e.g. -preview / -rc: published but never "Latest"
make_latest=false
fi
{
echo "draft=$draft"
echo "prerelease=$prerelease"
echo "make_latest=$make_latest"
} >> "$GITHUB_OUTPUT"

- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: smocker-bin
path: ./build

- run: cd build && tar -xvf smocker.tar.gz

- name: Docker login
uses: docker/login-action@v3
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4.4.0
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Set up QEMU
uses: docker/setup-qemu-action@v3
uses: docker/setup-qemu-action@96fe6ef7f33517b61c61be40b68a1882f3264fb8 # v4.2.0

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0

- name: Deploy on Docker registry
run: make VERSION=${{ steps.extract_ref.outputs.GIT_REF }} deploy-docker

- name: Deploy on GitHub releases
uses: softprops/action-gh-release@v2
uses: softprops/action-gh-release@3d0d9888cb7fd7b750713d6e236d1fcb99157228 # v3.0.2
with:
files: build/smocker.tar.gz
token: ${{ secrets.GITHUB_TOKEN }}
draft: ${{ steps.release_flags.outputs.draft }}
prerelease: ${{ steps.release_flags.outputs.prerelease }}
make_latest: ${{ steps.release_flags.outputs.make_latest }}
86 changes: 47 additions & 39 deletions client/components/App.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { GithubFilled, ReadOutlined } from "@ant-design/icons";
import { Layout } from "antd";
import { App as AntdApp, Layout, Tooltip } from "antd";
import "antd/dist/reset.css";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { BrowserRouter, Navigate, Route, Routes } from "react-router-dom";
Expand All @@ -24,47 +24,55 @@ const App = () => (
<QueryClientProvider client={queryClient}>
<SessionProvider>
<BrowserRouter basename={window.basePath}>
<Layout className="layout">
<Navbar />
{/* component={false} so the message/notification context adds no wrapper element that
would break the height:100% layout chain. */}
<AntdApp component={false}>
<Layout className="layout">
<Sidebar />
<Layout className="scrollable layout">
<Layout.Content className="not-scrollable">
<Routes>
<Route path="/pages/history" element={<History />} />
<Route path="/pages/mocks" element={<Mocks />} />
<Route path="/pages/mocks/:mock_id" element={<Mocks />} />
<Route path="/pages/visualize" element={<Visualize />} />
<Route
path="*"
element={<Navigate to="/pages/history" replace />}
/>
</Routes>
</Layout.Content>
<Layout.Footer style={{ textAlign: "center" }}>
Smocker version {window.version} &ndash; MIT Licensed
<br />
<a
href="https://github.com/smocker-dev/smocker"
title="Smocker on GitHub"
target="_blank"
rel="noreferrer"
>
<GithubFilled />
</a>
&nbsp;
<a
href="https://smocker.dev"
title="Smocker Documentation"
target="_blank"
rel="noreferrer"
>
<ReadOutlined />
</a>
</Layout.Footer>
<Navbar />
<Layout className="layout">
<Sidebar />
<Layout className="scrollable layout">
<Layout.Content className="not-scrollable">
<Routes>
<Route path="/pages/history" element={<History />} />
<Route path="/pages/mocks" element={<Mocks />} />
<Route path="/pages/mocks/:mock_id" element={<Mocks />} />
<Route path="/pages/visualize" element={<Visualize />} />
<Route
path="*"
element={<Navigate to="/pages/history" replace />}
/>
</Routes>
</Layout.Content>
<Layout.Footer style={{ textAlign: "center" }}>
Smocker version {window.version} &ndash; MIT Licensed
<br />
<Tooltip title="Smocker on GitHub">
<a
href="https://github.com/smocker-dev/smocker"
aria-label="Smocker on GitHub"
target="_blank"
rel="noreferrer"
>
<GithubFilled />
</a>
</Tooltip>
&nbsp;
<Tooltip title="Smocker documentation">
<a
href="https://smocker.dev"
aria-label="Smocker documentation"
target="_blank"
rel="noreferrer"
>
<ReadOutlined />
</a>
</Tooltip>
</Layout.Footer>
</Layout>
</Layout>
</Layout>
</Layout>
</AntdApp>
</BrowserRouter>
</SessionProvider>
</QueryClientProvider>
Expand Down
14 changes: 14 additions & 0 deletions client/components/History.scss
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,20 @@
}
}

.toolbar {
gap: 1em;

.list-search {
max-width: 320px;
}

.pagination {
display: flex;
align-items: center;
gap: 0.5em;
}
}

.action.buttons {
button {
margin-left: 0.5em;
Expand Down
Loading
Loading