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
122 changes: 115 additions & 7 deletions .github/workflows/build-images.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,20 @@ on:
- master
- main
workflow_dispatch:
inputs:
component:
description: Component to publish
required: true
type: choice
options:
- server-e2e
- agent
- server
- web
tag:
description: Version-prefixed image tag with a suffix (e.g. 7.0.0-e2e.1)
required: true
type: string

env:
REGISTRY: ghcr.io
Expand All @@ -26,7 +40,7 @@ jobs:

strategy:
matrix:
component: [agent, server, server-e2e, web]
component: ${{ github.event_name == 'workflow_dispatch' && fromJSON(format('["{0}"]', inputs.component)) || fromJSON('["agent","server","server-e2e","web"]') }}

steps:
- name: Checkout repository
Expand All @@ -51,16 +65,39 @@ jobs:
echo "netxms_version=${NETXMS_VERSION}" >> $GITHUB_OUTPUT
echo "package_version=${NETXMS_PACKAGE_VERSION}" >> $GITHUB_OUTPUT

- name: Validate manual publish
if: github.event_name == 'workflow_dispatch'
env:
PUBLISH_TAG: ${{ inputs.tag }}
NETXMS_VERSION: ${{ steps.version.outputs.netxms_version }}
SELECTED_COMPONENT: ${{ inputs.component }}
BUILD_COMPONENT: ${{ matrix.component }}
run: |
case "$SELECTED_COMPONENT" in
agent|server|server-e2e|web) ;;
*) echo "::error::Unknown component"; exit 1 ;;
esac
if [[ "$SELECTED_COMPONENT" != "$BUILD_COMPONENT" ]]; then
echo "::error::Manual publish must build only the selected component"
exit 1
fi
if [[ "$PUBLISH_TAG" != "$NETXMS_VERSION"-?* || ! "$PUBLISH_TAG" =~ ^[A-Za-z0-9_][A-Za-z0-9_.-]{0,127}$ ]]; then
echo "::error::Tag must be a valid Docker tag starting with $NETXMS_VERSION- and a nonempty suffix"
exit 1
fi

- name: Generate metadata
id: meta
uses: docker/metadata-action@v6
with:
images: ${{ env.IMAGE_PREFIX }}/${{ matrix.component }}
flavor: latest=${{ github.event_name == 'workflow_dispatch' && 'false' || 'auto' }}
tags: |
type=match,pattern=release-(\d+\.\d+\.\d+)$,group=1
type=match,pattern=release-(\d+\.\d+)\.\d+$,group=1
type=raw,value=${{ steps.version.outputs.netxms_version }},enable=${{ startsWith(github.ref, 'refs/tags/release-') }}
type=raw,value=latest,enable={{is_default_branch}}
type=match,pattern=release-(\d+\.\d+\.\d+)$,group=1,enable=${{ github.event_name != 'workflow_dispatch' }}
type=match,pattern=release-(\d+\.\d+)\.\d+$,group=1,enable=${{ github.event_name != 'workflow_dispatch' }}
type=raw,value=${{ steps.version.outputs.netxms_version }},enable=${{ github.event_name != 'workflow_dispatch' && startsWith(github.ref, 'refs/tags/release-') }}
type=raw,value=latest,enable=${{ github.event_name != 'workflow_dispatch' && github.ref == format('refs/heads/{0}', github.event.repository.default_branch) }}
type=raw,value=${{ inputs.tag || 'manual' }},enable=${{ github.event_name == 'workflow_dispatch' }}

- name: Download NetXMS web archive
if: matrix.component == 'web'
Expand All @@ -76,6 +113,7 @@ jobs:
./pin-package-version ${{ matrix.component }}/files/netxms-pin ${{ steps.version.outputs.package_version }}

- name: Build and push Docker image
if: matrix.component != 'server-e2e'
uses: docker/build-push-action@v7
with:
context: ./${{ matrix.component }}
Expand All @@ -89,6 +127,76 @@ jobs:
cache-from: type=gha
cache-to: type=gha,mode=max

- name: Build and load e2e image
if: matrix.component == 'server-e2e'
uses: docker/build-push-action@v7
with:
context: ./server-e2e
platforms: linux/amd64
load: true
push: false
provenance: false
tags: netxms-server-e2e:smoke
labels: ${{ steps.meta.outputs.labels }}
build-args: |
NETXMS_VERSION=${{ steps.version.outputs.netxms_version }}
NETXMS_PACKAGE_VERSION=${{ steps.version.outputs.package_version }}
cache-from: type=gha
cache-to: type=gha,mode=max

- name: Smoke test e2e image
if: matrix.component == 'server-e2e'
timeout-minutes: 3
run: |
NX_API_KEY=$(sed -n 's/^NX_API_KEY=//p' README.md)
if [[ ! "$NX_API_KEY" =~ ^[a-z2-7]{32}$ ]]; then
echo "::error::README must contain one public fixture API key"
exit 1
fi
docker run --detach --platform linux/amd64 --network none --name netxms-e2e-smoke netxms-server-e2e:smoke
deadline=$((SECONDS + 120))
while (( SECONDS < deadline )); do
if [[ "$(docker inspect --format '{{.State.Running}}' netxms-e2e-smoke)" != true ]]; then
echo "::error::NetXMS exited before the WebAPI became ready"
exit 1
fi
if docker exec netxms-e2e-smoke curl --fail --silent --show-error --connect-timeout 1 --max-time 2 --output /dev/null --header "Authorization: Bearer $NX_API_KEY" http://127.0.0.1:8000/v1/server-info; then
exit 0
fi
sleep 1
done
echo "::error::NetXMS WebAPI did not become ready within 120 seconds"
exit 1

- name: Push tested e2e image
if: matrix.component == 'server-e2e' && github.event_name != 'pull_request'
env:
IMAGE_TAGS: ${{ steps.meta.outputs.tags }}
run: |
if [[ -z "$IMAGE_TAGS" ]]; then
echo "::error::No e2e image tags were generated"
exit 1
fi
while IFS= read -r tag; do
[[ -n "$tag" ]] || continue
docker tag netxms-server-e2e:smoke "$tag"
docker push "$tag"
done <<< "$IMAGE_TAGS"

- name: E2e container logs
if: failure() && matrix.component == 'server-e2e'
run: |
if docker container inspect netxms-e2e-smoke > /dev/null 2>&1; then
docker logs netxms-e2e-smoke
fi

- name: Clean up e2e container
if: always() && matrix.component == 'server-e2e'
run: |
if docker container inspect netxms-e2e-smoke > /dev/null 2>&1; then
docker rm --force --volumes netxms-e2e-smoke
fi

- name: Clean up pin file
if: matrix.component != 'web' && always()
run: |
Expand Down Expand Up @@ -118,7 +226,7 @@ jobs:
NETXMS_VERSION=${{ steps.version.outputs.netxms_version }}
POSTGRES_DB=netxms
POSTGRES_USER=netxms
POSTGRES_PASSWORD=test_password
POSTGRES_PASSWORD=netxms
EOF

# Use locally built images for testing
Expand Down Expand Up @@ -151,7 +259,7 @@ jobs:
create-release:
runs-on: ubuntu-latest
needs: build
if: startsWith(github.ref, 'refs/tags/release-')
if: github.event_name != 'workflow_dispatch' && startsWith(github.ref, 'refs/tags/release-')

steps:
- name: Checkout repository
Expand Down
5 changes: 3 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@ Important: do not write comments. Do not explain what are you doing. Do NOT comm

## Project Overview

This repository contains Docker containerization for NetXMS (Network Management System), providing three main components:
This repository contains Docker containerization for NetXMS (Network Management System), providing four main components:

- **Server**: NetXMS monitoring server with PostgreSQL database support
- **Agent**: NetXMS monitoring agent for collecting system metrics
- **Web**: Jetty-based web interface for NetXMS management console
- **Server E2E**: Disposable SQLite test server with seeded data, WebAPI, and a public fixture API key

## Build Commands

Expand Down Expand Up @@ -38,7 +39,7 @@ make clean-pin

### Component Structure

- Each component (agent, server, web) has its own Dockerfile and supporting files
- Each component (agent, server, server-e2e, web) has its own Dockerfile and supporting files
- All containers use Debian 12 base (except web which uses Jetty Alpine)
- NetXMS packages are pinned to specific versions via `pin-package-version` script
- Version configuration is centralized in `build.properties`
Expand Down
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,16 @@ Images are also tagged with specific NetXMS versions (e.g., `5.2.3`).

Note: **NEVER** use `:latest` in the production, always pin specific release.

## Server E2E Fixture

The `server-e2e` image bundles a disposable SQLite database with seeded test data and the WebAPI enabled on port 8000. It runs on `linux/amd64`.

The following API key is public and intended only for tests against this fixture. It authenticates as the fixture's `admin` user and expires on 2038-01-01 14:35:32 UTC.

```sh
NX_API_KEY=dsly7ba3yqntvcsj6tkgi53ie4zaez6n
```

## Deployment

### Environment Setup
Expand Down
13 changes: 12 additions & 1 deletion server-e2e/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
FROM debian:13-slim

RUN apt-get update && apt-get install -y ca-certificates
RUN apt-get update && apt-get install -y ca-certificates curl

COPY --chown=root:root files/netxms.list /etc/apt/sources.list.d/
COPY --chown=root:root files/netxms-keyring.gpg /etc/apt/trusted.gpg.d/
Expand All @@ -19,4 +19,15 @@ EXPOSE 8000/tcp
COPY files/db.sqlite3 /tmp/db.sqlite3
COPY files/netxmsd.conf /etc/netxmsd.conf

RUN set -eu; \
nxdbmgr -c /etc/netxmsd.conf upgrade; \
upgrade_output="$(nxdbmgr -c /etc/netxmsd.conf upgrade 2>&1)"; \
printf '%s\n' "$upgrade_output"; \
printf '%s\n' "$upgrade_output" | grep -Fx 'Core database schema is up to date'; \
printf '%s\n' "$upgrade_output" | grep -Fx 'Database upgrade succeeded'; \
nxdbmgr -c /etc/netxmsd.conf background-upgrade; \
background_output="$(nxdbmgr -c /etc/netxmsd.conf background-upgrade 2>&1)"; \
printf '%s\n' "$background_output"; \
printf '%s\n' "$background_output" | grep -Fx 'No pending background upgrades'

ENTRYPOINT [ "/usr/bin/netxmsd", "-c", "/etc/netxmsd.conf", "-q"]
Binary file modified server-e2e/files/db.sqlite3
Binary file not shown.
Loading