feat: reserved CI port range 10000-10099, document convention

This commit is contained in:
Jarian Cottingham 2026-07-07 23:27:12 +00:00 committed by Jarian
parent 24d42ed0b8
commit cc6c9c6957
3 changed files with 57 additions and 9 deletions

View File

@ -114,17 +114,18 @@ jobs:
id: port
run: |
sleep 2
# Read shifted port from container logs (entrypoint prints [ci-port-shift])
# CI port range 10000-10099: port = 10000 + CI_PORT_OFFSET
# NewsArchiverV2 uses offset 1, so port = 10001
CI_LOG=$(docker logs newsarchiver-e2e 2>&1 | grep "\[ci-port-shift\]" || echo "")
if [ -n "$CI_LOG" ]; then
APP_PORT=$(echo "$CI_LOG" | grep -oP 'to \K[0-9]+')
echo "app_port=${APP_PORT}" >> $GITHUB_OUTPUT
echo "$CI_LOG"
# Re-publish port now that we know the shifted port
echo "Discovered port ${APP_PORT} from CI logs"
else
echo "app_port=5000" >> $GITHUB_OUTPUT
echo "No CI port shift detected, using default 5000"
# Fallback: compute from offset
OFFSET=${CI_PORT_OFFSET:-1}
echo "app_port=$((10000 + OFFSET))" >> $GITHUB_OUTPUT
echo "No CI port shift in logs, computed port $((10000 + OFFSET))"
fi
- name: Seed test data

45
AGENTS.md Normal file
View File

@ -0,0 +1,45 @@
# CI Port Convention
## Reserved Range: 10000-10099
CI jobs never use production ports. Each service gets a fixed offset (1-99) within the 10000-10099 range.
**Formula:** `CI_PORT = 10000 + CI_PORT_OFFSET`
## Port Assignments
| Offset | CI Port | Service |
|--------|---------|---------|
| 1 | 10001 | NewsArchiverV2 |
| 2 | 10002 | paste-bin |
| 3-99 | 10003-10099 | Reserved for future services |
## Usage
**CI workflow:**
```yaml
docker run -d --name myapp-e2e \
--network test-network \
-e CI=true \
-e CI_PORT_OFFSET=1 \
myapp:test \
python main.py --serve --port 5000
# App auto-shifts to port 10001
```
**App code (any service):**
```python
if os.environ.get("CI") == "true" and os.environ.get("SKIP_PORT_SHIFT") != "1":
offset = int(os.environ.get("CI_PORT_OFFSET", "1"))
args.port = 10000 + offset
print(f"[ci-port-shift] Port shifted from {original} to {args.port}")
```
**Production:** Never sets `CI=true` or `CI_PORT_OFFSET`. Ports stay unchanged.
## Rules
1. CI jobs always set `CI=true` and the service's `CI_PORT_OFFSET`
2. Port discovery via log parsing: `docker logs | grep "\[ci-port-shift\]"`
3. Container-to-container traffic uses Docker networks, never host port publish
4. Production containers never have `CI=true`

View File

@ -256,12 +256,14 @@ Examples:
args = parser.parse_args()
# CI port shift: detect CI env, shift port to avoid conflicts with production
# CI port shift: detect CI env, map to reserved CI port range 10000-10099
# CI_PORT_OFFSET (1-99) maps to 10001-10099. Each service gets a fixed offset.
# NewsArchiverV2=1, paste-bin=2, etc. See AGENTS.md for assignments.
if os.environ.get("CI") == "true" and os.environ.get("SKIP_PORT_SHIFT") != "1":
offset = int(os.environ.get("CI_PORT_OFFSET", "1"))
original_port = args.port
args.port = original_port + offset
print(f"[ci-port-shift] Port shifted from {original_port} to {args.port} (offset: {offset})")
offset = int(os.environ.get("CI_PORT_OFFSET", "1"))
args.port = 10000 + offset
print(f"[ci-port-shift] Port shifted from {original_port} to {args.port} (offset {offset}, CI range: 10000-10099)")
logger = setup_logging(args.verbose)