Skip to content

Release v2.1.0

Choose a tag to compare

@github-actions github-actions released this 27 May 20:06
b2d33b0

Since v2.0.0 (2024-05-06)

Features

  • Markdown challenge text (#62, #63, #64) — challenge description, hint, and details now flow through as Markdown end-to-end. HTML islands are detected with net/html and converted via html-to-markdown v2; LaTeX passes through cleanly. Templated metadata ({{ ... }}) uses custom delimiters so it survives the Markdown round-trip.
  • Concurrent instance launches (#44) — replaced the port-assignment mutex with a semaphore, allowing two instances to launch in parallel and pipelining work against the Docker daemon.
  • Atomic SQLite port reservations (part of #20) — port allocation now happens inside a single SQL transaction, eliminating races under concurrent launches.
  • Autoprune for lingering instances (#19) — instance rows orphaned by external container reaping are now pruned on each launch (configurable via PRUNE_AGE), preventing port-exhaustion spirals.
  • User-supplied env vars on container launch (#14) — cmgrd now accepts a required user_id and an optional env-var map, propagated equally to every container in a multi-container challenge.
  • LINUX_IMMUTABLE capability (#6) — opt-in via challenge metadata.

Performance

Bundled in #20 (numbers below are pre-launch pre-compute time):

DB size Before #19 With #19 With #20
20 0.31 ms 0.32 ms 0.33 ms
200 0.44 ms 0.42 ms 0.29 ms
20 000 24.91 ms 26.27 ms 12.43 ms
50 000 60.51 ms 64.76 ms 31.43 ms
  • SQLite WAL mode enabled by default, with _synchronous=NORMAL and _busy_timeout=50ms DSN tuning.
  • Replaced the in-memory port map with a compact bitset in getFreePort.
  • Added indexes for cascade deletes and portAssignments(port).
  • Fixed an N+1 query pattern in lookupBuildInstances (batched via JOIN, wrapped in a read-only transaction).

Fixes

  • On-demand challenge rebuilds (#17) — rebuilds previously restarted on-demand instances with nil env vars, silently dropping injected values like CMGR_USER_ID. They are now torn down on rebuild and must be Start()ed again with proper env.
  • InstanceMetadata.CreatedAt is now *time.Time so JSON output is RFC3339.
  • Migration ALTER TABLE guarded by PRAGMA table_info (idempotent migration on re-run).
  • Periodic prune log demoted from info to debug.
  • Errors in the migration block are no longer swallowed.

Build & CI

  • Docker module v25 → v29 (#12, #42) — adapted to breaking v29 API changes (network.ParsePort with error handling, netip.ParseAddr error checks, pushResp close fix).
  • Go 1.26 in CI; go build runs only on master push.
  • macOS-latest runners used for arm64 builds.
  • GitHub Actions pinned to commit SHAs with a cooldown window for security.
  • Dependabot enabled (weekly).

Testing

  • Comprehensive unit test suite added (#16) — covers autoprune (Prune/checkPrune), lookupBuildInstances, usedPortBitset/getFreePort, cache isolation for lookupBuildMetadata / lookupChallengeMetadata, concurrent port reservations, HTML-island boundaries, and LaTeX passthrough.

Documentation

  • README and Swagger updated for the env-var launch feature; new examples/runtime_env_vars challenge.
  • Documented that env vars broadcast equally to all containers in a multi-container challenge.
  • CLI usage info for PRUNE_AGE.

Dependencies

Routine bumps via Dependabot: docker/cli, moby/moby/client, mattn/go-sqlite3, yuin/goldmark, jmoiron/sqlx, containerd/containerd, go.opentelemetry.io/otel, golang.org/x/net.