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
14 changes: 14 additions & 0 deletions .github/workflows/ci-main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,9 @@ jobs:
- uses: actions/checkout@v4
with:
submodules: recursive
# Full history + tags so `git describe --tags` can version the image
# (bare tag on release commits, tag-distance-sha on snapshots).
fetch-depth: 0

- name: Download bookworm moxygen tarball
env:
Expand Down Expand Up @@ -380,11 +383,22 @@ jobs:
echo "short=$SHORT" >> "$GITHUB_OUTPUT"
echo "rolling=${LABEL}-latest" >> "$GITHUB_OUTPUT"

- name: Resolve build version
id: version
run: |
# Baked into the binary and emitted as an OCI label. Matching only
# v-prefixed tags is required: the repo carries moving tags that are
# not versions, and an unfiltered describe returns one of those.
V="$(git describe --tags --match 'v[0-9]*' --always)"
echo "version=$V" >> "$GITHUB_OUTPUT"
echo "==> build version: $V"

- name: Build Docker image
run: |
IMAGE="ghcr.io/${{ github.repository }}"
ARCH="${{ matrix.arch }}"
docker build -f docker/Dockerfile \
--build-arg MOQX_VERSION_STRING="${{ steps.version.outputs.version }}" \
-t "${IMAGE}:${{ steps.tags.outputs.short }}-${ARCH}" \
-t "${IMAGE}:${{ steps.tags.outputs.rolling }}-${ARCH}" \
.
Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/version-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -324,8 +324,11 @@ jobs:
# path. Combined with the bundle step below this produces a
# self-contained tarball that runs on noble / RHEL 9 / AL2023
# without needing distro-specific packages installed.
# Pass the tag explicitly: the checkout is shallow and the tag may
# not exist yet, so git describe would yield a bare sha.
cmake -S . -B _build -G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DMOQX_VERSION_STRING="${{ needs.validate.outputs.tag }}" \
-DCMAKE_PREFIX_PATH="$(cat .scratch/cmake_prefix_path.txt)" \
-DCMAKE_MODULE_PATH="${GITHUB_WORKSPACE}/cmake;${GITHUB_WORKSPACE}/deps/moxygen/build/fbcode_builder/CMake" \
-DCMAKE_C_FLAGS="${{ matrix.cxx_flags }}" \
Expand Down
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Build outputs
/build/
/build-*/
/_build/
/cmake-build-*/
/CMakeFiles/
CMakeCache.txt
Expand Down Expand Up @@ -39,3 +40,6 @@ docker/cloudflare.ini
# gh-pages dashboard (lives on gh-pages branch, not main)
/gh-pages/
docker/grafana/provisioning/dashboards/archive/

# Version stamp for source trees with no .git (cmake/MoqxVersion.cmake).
/VERSION
9 changes: 8 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "" FORCE)
endif()

# Defines MOQX_VERSION_STRING and the moqx_version interface target.
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/MoqxVersion.cmake)

option(MOQX_BUILD_TESTS "Build tests" ON)
option(MOQX_BUILD_BENCHMARKS "Build benchmarks" OFF)
option(MOQX_ENABLE_SANITIZERS "Enable ASAN/UBSAN (non-Release)" OFF)
Expand Down Expand Up @@ -202,7 +205,8 @@ target_link_libraries(moqx_core PUBLIC
)

target_compile_options(moqx_core PRIVATE -Wall -Wextra -Wpedantic)
target_compile_definitions(moqx_core PRIVATE MOQX_VERSION="${PROJECT_VERSION}")
# PUBLIC so dependents can include moqx/Version.h.
target_link_libraries(moqx_core PUBLIC moqx_version)

# --- Config types (resolved Config structs, header-only, no rfl dependency) ---
# Library consumers that only need the Config API link this.
Expand Down Expand Up @@ -319,3 +323,6 @@ endif()
include(${PROJECT_SOURCE_DIR}/cmake/Lint.cmake)

install(TARGETS moqx moqx-issuer moqx_core moqx_config_loader)

# Identifies an unpacked tarball without running the binary.
install(FILES ${CMAKE_BINARY_DIR}/VERSION DESTINATION .)
95 changes: 95 additions & 0 deletions cmake/MoqxVersion.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
# Build identifier compiled into the binary (/info, --version, log banner) and
# written to ${CMAKE_BINARY_DIR}/VERSION for packaging.
#
# Format is git describe output keeping the tag's "v" prefix, e.g. v0.2.1,
# v0.2.1-14-gabc1234, v0.2.1-14-gabc1234-dirty, or a bare sha when no v* tag is
# reachable. Resolution order:
#
# 1. -DMOQX_VERSION_STRING explicit (CI, docker --build-arg)
# 2. git describe any clone, including local dev builds
# 3. <source root>/VERSION for trees with no .git (source tarballs)
# 4. v${PROJECT_VERSION}
#
# git outranks the VERSION file because that file is gitignored: a stale one
# left in a working tree would silently pin every later build.
#
# Only v-prefixed numeric tags are matched — the repo carries moving tags that
# are not versions, and an unfiltered describe would return one of those.
#
# Resolution runs at configure time, so a dev who commits without re-running
# cmake keeps the previous string until the next configure.

function(_moqx_version_from_git out_var)
set(${out_var} "" PARENT_SCOPE)

find_package(Git QUIET)
if(NOT GIT_FOUND)
return()
endif()

# A worktree's .git is a file, not a directory.
if(NOT EXISTS "${PROJECT_SOURCE_DIR}/.git")
return()
endif()

execute_process(
COMMAND "${GIT_EXECUTABLE}" describe --tags --match "v[0-9]*" --always
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}"
OUTPUT_VARIABLE _described
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_QUIET
RESULT_VARIABLE _rc
)
if(NOT _rc EQUAL 0 OR NOT _described)
return()
endif()

# describe --dirty only inspects tracked files; status also reports untracked
# ones, so a tree with new files is not mistaken for a clean commit. Ignored
# paths (build dirs, VERSION) are excluded by default.
execute_process(
COMMAND "${GIT_EXECUTABLE}" status --porcelain
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}"
OUTPUT_VARIABLE _status
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_QUIET
)
if(_status)
set(_described "${_described}-dirty")
endif()

set(${out_var} "${_described}" PARENT_SCOPE)
endfunction()

if(MOQX_VERSION_STRING)
set(_moqx_version_source "explicit -DMOQX_VERSION_STRING")
else()
_moqx_version_from_git(MOQX_VERSION_STRING)
if(MOQX_VERSION_STRING)
set(_moqx_version_source "git describe")
elseif(EXISTS "${PROJECT_SOURCE_DIR}/VERSION")
file(READ "${PROJECT_SOURCE_DIR}/VERSION" MOQX_VERSION_STRING)
string(STRIP "${MOQX_VERSION_STRING}" MOQX_VERSION_STRING)
set(_moqx_version_source "VERSION file")
else()
set(MOQX_VERSION_STRING "v${PROJECT_VERSION}")
set(_moqx_version_source "project() fallback")
endif()
endif()

message(STATUS "moqx version: ${MOQX_VERSION_STRING} (from ${_moqx_version_source})")

set(MOQX_VERSION_HEADER_DIR "${CMAKE_BINARY_DIR}/generated")
configure_file(
"${PROJECT_SOURCE_DIR}/cmake/Version.h.in"
"${MOQX_VERSION_HEADER_DIR}/moqx/Version.h"
@ONLY
)

# Interface target so any binary can include moqx/Version.h.
add_library(moqx_version INTERFACE)
target_include_directories(moqx_version INTERFACE "${MOQX_VERSION_HEADER_DIR}")

# Shipped in the install tree: identifies an unpacked tarball without running
# the binary. Images carry OCI labels instead.
file(WRITE "${CMAKE_BINARY_DIR}/VERSION" "${MOQX_VERSION_STRING}\n")
25 changes: 25 additions & 0 deletions cmake/Version.h.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* Copyright (c) OpenMOQ contributors.
* This source code is licensed under the Apache 2.0 license found in the
* LICENSE file in the root directory of this source tree.
*
* GENERATED FILE — do not edit. Source template: cmake/Version.h.in,
* derivation: cmake/MoqxVersion.cmake.
*/

#pragma once

#include <string_view>

// Macro form: usable in string-literal concatenation (e.g. the admin /info
// JSON body). Prefer openmoq::moqx::kVersion in new code.
#define MOQX_VERSION "@MOQX_VERSION_STRING@"

namespace openmoq::moqx {

// Canonical build identifier: a git describe string with the "v" tag prefix
// retained (v0.2.1, v0.2.1-14-gabc1234, v0.2.1-14-gabc1234-dirty), or a bare
// commit sha when no v* tag is reachable.
inline constexpr std::string_view kVersion{MOQX_VERSION};

} // namespace openmoq::moqx
15 changes: 15 additions & 0 deletions docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,13 @@ COPY src/ src/
COPY deps/catapult/ deps/catapult/
COPY deps/moxygen/build/fbcode_builder/CMake deps/moxygen/build/fbcode_builder/CMake

# The build context excludes .git, so cmake cannot derive the version here;
# CI passes it in. Empty falls back to the static project version.
ARG MOQX_VERSION_STRING=""

RUN cmake -S . -B _build --preset default \
-DCMAKE_PREFIX_PATH=/opt/moxygen \
-DMOQX_VERSION_STRING="${MOQX_VERSION_STRING}" \
-DBUILD_TESTING=OFF -DMOQX_BUILD_TESTS=OFF \
&& cmake --build _build -j$(nproc) \
&& cmake --install _build --prefix /install
Expand All @@ -36,6 +41,16 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
curl gettext-base \
&& rm -rf /var/lib/apt/lists/*

# Same value the binary reports, as image metadata: `docker inspect` and
# registry UIs can identify an image without pulling or running it.
# ARGs do not cross stages, so it is redeclared here.
ARG MOQX_VERSION_STRING=""
LABEL org.opencontainers.image.title="moqx" \
org.opencontainers.image.description="MoQ relay" \
org.opencontainers.image.version="${MOQX_VERSION_STRING}" \
org.opencontainers.image.source="https://github.com/openmoq/moqx" \
org.opencontainers.image.licenses="Apache-2.0"

COPY --from=builder /install/bin/moqx /usr/local/bin/moqx
COPY --from=builder /install/bin/moqx-issuer /usr/local/bin/moqx-issuer
COPY docker/entrypoint.sh /usr/local/bin/entrypoint.sh
Expand Down
854 changes: 532 additions & 322 deletions docker/grafana/provisioning/dashboards/moqx-overview.json

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions docker/prometheus/prometheus.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,11 @@ scrape_configs:
static_configs:
- targets: ['localhost:9090']

# Relay build info (version label for the host banner), via json_exporter
# scraping the admin /info. Effectively static — scraped coarsely.
# Relay build info for the banner badge. Cheap endpoint, so it is
# scraped often enough that a redeploy shows up promptly.
- job_name: moqx-info
metrics_path: /probe
scrape_interval: 60s
scrape_interval: 30s
params:
module: [moqx_info]
static_configs:
Expand Down
1 change: 1 addition & 0 deletions src/admin/BuiltinRoutes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <proxygen/lib/http/HTTPMessage.h>

#include "admin/AdminServer.h"
#include "moqx/Version.h"

namespace openmoq::moqx::admin {

Expand Down
6 changes: 6 additions & 0 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "bpf/QuicReuseportSteering.h"
#include "config/loader/ConfigInit.h"
#include "logging/LogSetup.h"
#include "moqx/Version.h"
#include "stats/StatsRegistry.h"

#include <csignal>
Expand Down Expand Up @@ -76,6 +77,8 @@ int main(int argc, char* argv[]) {
" serve Start the relay (default)\n" +
cfg::configSubcommandUsage() + "\nUsage: moqx [subcommand] --config <path>"
);
// gflags handles --version inside folly::Init, before any config load.
google::SetVersionString(MOQX_VERSION);
// MOQX_LOGGING is the moqx-namespaced alias for folly's own FOLLY_LOGGING env
// var (folly::Init reads FOLLY_LOGGING). Promote it here — before folly::Init
// — so the knob works for any launch method (docker, systemd, bare metal)
Expand All @@ -89,6 +92,9 @@ int main(int argc, char* argv[]) {
combineLoggingArgs(argc, argv);
folly::Init init(&argc, &argv, true);

// Attributes the log stream to an exact build.
XLOG(INFO) << "moqx " << kVersion << " starting";

std::string_view subcommand = kServeCommand;
if (argc > 1) {
subcommand = argv[1];
Expand Down
Loading