Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
bdb7fd4
chore(global): flatten monorepo and ignore legacy ci configs
netanelC Apr 26, 2026
b64e298
docs(global): add missing README files for container images
netanelC Apr 26, 2026
387a3c4
refactor: remove helms and order the repo
netanelC Apr 26, 2026
058c08c
docs(sftpgo): add missing README file
netanelC Apr 26, 2026
56c06ee
feat: add sftpgo
netanelC Apr 26, 2026
e544c24
feat: add lint
netanelC Apr 26, 2026
136c0a8
ci: pull request workflow
netanelC Apr 27, 2026
f4bd240
refactor: use docker hadolint
netanelC Apr 27, 2026
6929d52
ci(global): add commitlint
netanelC Apr 27, 2026
64a4432
feat(global): add release please
netanelC Apr 27, 2026
65a3eab
docs(global): add README
netanelC Apr 27, 2026
233fa6e
chore(global): remove PRD file
netanelC Apr 27, 2026
a2f64e0
style: empty line at eof
netanelC Apr 27, 2026
edb1275
Merge branch 'initial-repo' into add-lint
netanelC Apr 27, 2026
bab4452
refactor: migrate images to a dedicated folder and add script for lint
netanelC Apr 29, 2026
4484d24
ci: set ruff version
netanelC Apr 29, 2026
42dedb2
Merge branch 'master' of https://github.com/MapColonies/shared-images…
netanelC Apr 29, 2026
a491b61
style: run prettier
netanelC Apr 29, 2026
ed61512
fix: remove root images folders
netanelC Apr 29, 2026
f56fee9
Merge branch 'add-lint' of https://github.com/MapColonies/shared-imag…
netanelC Apr 29, 2026
500c5fa
refactor(global): images folder
netanelC Apr 29, 2026
b79350f
Merge branch 'add-commitlint' of https://github.com/MapColonies/share…
netanelC Apr 29, 2026
e0b4015
Merge branch 'master' of https://github.com/MapColonies/shared-images…
netanelC Apr 29, 2026
7e21f85
ci(global): add cache
netanelC Apr 29, 2026
96122e5
refactor(global): add mega linter
netanelC May 3, 2026
61331fb
ci(global): fix step
netanelC May 3, 2026
d99d602
chore(global): add package-lock to megalinter ignore
netanelC May 3, 2026
77e9dc8
ci(global): use docker cache action
netanelC May 3, 2026
748ed21
revert(global): enable yaml
netanelC May 7, 2026
058cffb
Merge branch 'master' of https://github.com/MapColonies/shared-images…
netanelC May 7, 2026
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
7 changes: 7 additions & 0 deletions .cspell.json
Comment thread
ronenkapelian marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"ignorePaths": ["**/node_modules/**", "**/vscode-extension/**", "**/.git/**", ".vscode", "megalinter", "package-lock.json", "report"],
"language": "en",
"noConfigSearch": true,
"words": ["megalinter", "oxsecurity"],
"version": "0.2"
}
21 changes: 11 additions & 10 deletions .github/workflows/pr-checks.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,17 @@ name: PR Checks

on: pull_request

permissions: read-all

jobs:
lint-and-format:
name: Code Quality (Prettier, Ruff & Hadolint)
mega-lint:
name: Code Quality (MegaLinter)
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v6
with:
fetch-depth: 0

- name: Set up Node.js
uses: actions/setup-node@v6
Expand All @@ -22,15 +26,12 @@ jobs:
run: npm ci
working-directory: .

- name: Install Ruff
env:
RUFF_VERSION: 0.15.12
run: python3 -m pip install ruff==${{ env.RUFF_VERSION }}

- name: Check Formatting (Prettier & Ruff)
run: npm run format:check
- name: Cache Docker images
uses: ScribeMD/docker-cache@0.5.0
with:
key: docker-${{ runner.os }}-megalinter-v9

- name: Lint Code (Ruff & Docker)
- name: Lint Code (MegaLinter)
run: npm run lint

validate-ownership:
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/release-please.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ jobs:
COMPONENT=$(basename "${{ matrix.path }}")
TEAM=$(jq -r ".\"$COMPONENT\"" ownership.json)

echo "VERSION=$VERSION" >> $GITHUB_ENV
echo "IMAGE_BASE=${{ secrets.ACR_URL }}/$TEAM/$COMPONENT" >> $GITHUB_ENV
echo "VERSION=$VERSION" >> "$GITHUB_ENV"
echo "IMAGE_BASE=${{ secrets.ACR_URL }}/$TEAM/$COMPONENT" >> "$GITHUB_ENV"

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
Expand Down
6 changes: 1 addition & 5 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -142,8 +142,4 @@ vite.config.js.timestamp-*
vite.config.ts.timestamp-*
.vite/

# Legacy CI/CD configuration files
.gitlab-ci.yml
Jenkinsfile
.travis.yml
.circleci/
megalinter-reports/
38 changes: 38 additions & 0 deletions .mega-linter.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Configuration file for MegaLinter
#
# See all available variables at https://megalinter.io/latest/config-file/ and in
# linters documentation
---
# all, none, or list of linter keys
APPLY_FIXES: none

DISABLE_LINTERS:
- PYTHON_PYRIGHT
- JSON_V8R
- REPOSITORY_DUSTILOCK
- REPOSITORY_KINGFISHER
- REPOSITORY_KICS
- REPOSITORY_DEVSKIM
- SPELL_CSPELL

# Uncomment if you want MegaLinter to detect errors but not block CI to pass
# DISABLE_ERRORS: true

SHOW_ELAPSED_TIME: true
SHOW_SKIPPED_LINTERS: false
PRINT_ALPACA: false
FLAVOR_SUGGESTIONS: false
VALIDATE_ALL_CODEBASE: false

PYTHON_FLAKE8_ARGUMENTS:
- --max-line-length=160

PYTHON_PYLINT_ARGUMENTS:
- --disable=unrecognized-option,import-error

PYTHON_BANDIT_ARGUMENTS:
- -s ,B104,B310
Comment thread
ronenkapelian marked this conversation as resolved.

YAML_YAMLLINT_CONFIG_FILE: .yamllint.yaml
Comment thread
ronenkapelian marked this conversation as resolved.
JAVASCRIPT_DEFAULT_STYLE: prettier
FILTER_REGEX_EXCLUDE: (package-lock\.json)$
1 change: 1 addition & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ package-lock.json
README.md
node_modules
.release-please-manifest.json
.ruff_cache/
2 changes: 2 additions & 0 deletions .trivyignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# We rely on external orchestrator probes, so Docker HEALTHCHECK is unnecessary
DS-0026
2 changes: 2 additions & 0 deletions .yamllint.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
ignore: |
.github/
11 changes: 10 additions & 1 deletion images/elastic-alertmanager-connector/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
FROM python:3.9-slim

RUN groupadd -r appuser && useradd -r -g appuser appuser

WORKDIR /app
COPY . /app

COPY --chown=appuser:appuser . /app

RUN pip install --no-cache-dir -r requirements.txt

EXPOSE 8080
ENV PYTHONUNBUFFERED=1

USER appuser

CMD ["gunicorn", "--bind", "0.0.0.0:8080", "app:app"]
2 changes: 1 addition & 1 deletion images/elastic-alertmanager-connector/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ The application runs using Gunicorn on port `8080`.
The application is configured using the following environment variables:

| Variable | Default | Description |
| ----------------- | ------------------------------------------------- | -------------------------------------------------------- |
|-------------------|---------------------------------------------------|----------------------------------------------------------|
| `INDEX_NAME` | `webhook-data` | The Elasticsearch index where alerts are stored. |
| `ES_HOST` | `http://localhost:9200` | The URL of the Elasticsearch cluster. |
| `ES_USERNAME` | _(optional)_ | Username for Elasticsearch authentication. |
Expand Down
8 changes: 5 additions & 3 deletions images/elastic-alertmanager-connector/app.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import os
from flask import Flask, request, jsonify
from elasticsearch import Elasticsearch
from datetime import datetime

from elasticsearch import Elasticsearch
from flask import Flask, jsonify, request

PORT = 8080
INDEX_NAME = os.getenv("INDEX_NAME", "webhook-data")
ES_HOST = os.getenv("ES_HOST", "http://localhost:9200")
Expand Down Expand Up @@ -53,4 +54,5 @@ def webhook():


if __name__ == "__main__":
app.run(debug=True, host="0.0.0.0", port=PORT)
debug_mode = os.getenv("FLASK_DEBUG", "false").lower() == "true"
app.run(debug=debug_mode, host="0.0.0.0", port=PORT)
4 changes: 2 additions & 2 deletions images/elastic-alertmanager-connector/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Flask==2.2.5
Flask==3.1.3
elasticsearch==8.5.0
Werkzeug==3.0.6
Werkzeug==3.1.6
gunicorn==23.0.0
2 changes: 2 additions & 0 deletions images/hoppscotch/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,5 @@ RUN chgrp -R 0 /site && \

RUN chgrp -R 0 /dist/backend && \
chmod -R g+rwX /dist/backend

USER 1001
11 changes: 8 additions & 3 deletions images/scaler/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ FROM python:3.11-slim

# Install dependencies
RUN apt-get update && \
apt-get install -y --no-install-recommends && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*

Expand All @@ -10,13 +11,17 @@ WORKDIR /app

# Copy requirements and install Python dependencies
COPY requirements.txt /app/requirements.txt
RUN pip install --no-cache-dir -r requirements.txt

# Copy the Python script
COPY scaler.py /app/scaler.py

# Make the script executable
RUN chmod +x /app/scaler.py
# Install pip deps, make script executable, create user, and set permissions
RUN pip install --no-cache-dir -r requirements.txt && \
chmod +x /app/scaler.py && \
useradd -m appuser && \
chown -R appuser:appuser /app

USER appuser

# Set the entrypoint
ENTRYPOINT ["python3", "/app/scaler.py"]
2 changes: 1 addition & 1 deletion images/scaler/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ RBAC note: the service account must be able to get/list/patch Deployments/Statef

Entry: `python3 /app/scaler.py`

```
```shell
python3 scaler.py {up,down} \
--namespace <ns> [--namespace <ns> ...] \
[--release <name>] [--all] [--dry-run] [--debug] \
Expand Down
33 changes: 18 additions & 15 deletions images/scaler/scaler.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,25 @@
"""

import argparse
import os
import json
import logging
import os
import sys
import time
from urllib import request as urlrequest, error as urlerror
from typing import Any, Dict, List, Optional, Set
from urllib import error as urlerror
from urllib import request as urlrequest

from kubernetes import client, config
from kubernetes.client import ApiException
from kubernetes import client, config # type: ignore[import-untyped]
from kubernetes.client import ApiException # type: ignore[import-untyped]


class OpenShiftScaler:
def __init__(self, namespace: str = "monitoring"):
def __init__(self, namespace: str = "monitoring") -> None:
self.namespace = namespace
self.logger = self._setup_logging()
self.apps = None # type: Optional[client.AppsV1Api]
self.core = None # type: Optional[client.CoreV1Api]
self.apps: Any = None
self.core: Any = None

def _setup_logging(self) -> logging.Logger:
"""Setup logging configuration."""
Expand Down Expand Up @@ -126,12 +127,12 @@ def discover_releases(self) -> Dict[str, Any]:
"""Discover all release labels (including duplicates) and provide counts.
Returns a dictionary with totals and lists for diagnostics/dry-run.
"""
totals = {
totals: Dict[str, Any] = {
"deployments_total": 0,
"deployments_labeled": 0,
"statefulsets_total": 0,
"statefulsets_labeled": 0,
"all_releases": [], # type: List[str]
"all_releases": [],
}
all_labels: List[str] = []

Expand Down Expand Up @@ -530,16 +531,16 @@ def scale_all(self, action: str) -> Dict[str, Any]:

# ------------------------- Actions -------------------------

def scale_down(self, target_release: Optional[str] = None):
def scale_down(self, target_release: Optional[str] = None) -> Dict[str, Any]:
"""Wrapper for scaling down using the unified handler."""
return self.scale("down", target_release=target_release)

def scale_up(self, target_release: Optional[str] = None):
def scale_up(self, target_release: Optional[str] = None) -> Dict[str, Any]:
"""Wrapper for scaling up using the unified handler."""
return self.scale("up", target_release=target_release)


def main():
def main() -> None:
parser = argparse.ArgumentParser(
description="Kubernetes Resource Scaler (Python client)"
)
Expand Down Expand Up @@ -679,9 +680,11 @@ def main():
if slack_url:
# Use a temporary scaler to reuse Slack notification helper
temp_scaler = OpenShiftScaler(
namespace=namespaces_processed[0]
if namespaces_processed
else "monitoring"
namespace=(
namespaces_processed[0]
if namespaces_processed
else "monitoring"
)
)
temp_scaler._notify_slack(slack_url, final_summary)
except Exception as e:
Expand Down
8 changes: 7 additions & 1 deletion images/sftpgo-node-exporter/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ ENV TEXT_FILES_ROOT="${NODE_EXPORTER_ROOT}/textfile_collector"
ENV TEXT_FILES_SCRIPTS_ROOT="${NODE_EXPORTER_ROOT}/script"

# Install necessary packages
RUN apt-get update && apt-get install --no-install-recommends cron="3.*" curl="7.*" -y && \
RUN apt-get update && apt-get install -y --no-install-recommends cron="3.*" curl="7.*" && \
# Download Node Exporter
curl -LO https://github.com/prometheus/node_exporter/releases/download/v${NODE_EXPORTER_VERSION}/node_exporter-${NODE_EXPORTER_VERSION}.linux-amd64.tar.gz && \
# Extract and move the binary
Expand All @@ -27,6 +27,12 @@ RUN chmod 755 ${TEXT_FILES_SCRIPTS_ROOT}/subdir_sizes.sh

COPY ./entrypoint.sh /usr/local/bin/entrypoint.sh

# Create non-root user and assign permissions
RUN useradd -r -s /bin/false exporter_user && \
chown -R exporter_user:exporter_user ${NODE_EXPORTER_ROOT} /usr/local/bin/entrypoint.sh

USER exporter_user

# Expose the default port for Node Exporter
EXPOSE 9100
ENTRYPOINT [ "/usr/local/bin/entrypoint.sh" ]
3 changes: 1 addition & 2 deletions images/sftpgo-node-exporter/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
#!/bin/bash

echo "Running ${TEXT_FILES_SCRIPTS_ROOT}/subdir_sizes.sh..."
nohup ${TEXT_FILES_SCRIPTS_ROOT}/subdir_sizes.sh > /dev/stdout 2>&1 &
nohup "${TEXT_FILES_SCRIPTS_ROOT}"/subdir_sizes.sh >/dev/stdout 2>&1 &
# ${TEXT_FILES_SCRIPTS_ROOT}/subdir_sizes.sh &
SUBDIRS_PID="$!"
echo "SUBDIRS_PID=$SUBDIRS_PID"


echo "Running node exporter..."
exec /usr/local/bin/node_exporter "$@"
36 changes: 18 additions & 18 deletions images/sftpgo-node-exporter/subdir_sizes.sh
Original file line number Diff line number Diff line change
Expand Up @@ -13,25 +13,25 @@ TMP_FILE="${OUTPUT_FILE}.tmp"
touch "$LOG_FILE"

while true; do
# Generate metrics
echo "# HELP subdir_size_bytes Size of subdirectories in bytes" > "$TMP_FILE"
echo "# TYPE subdir_size_bytes gauge" >> "$TMP_FILE"
echo "Script executed at $(date)" > "$LOG_FILE"
echo "PARENT_DIR=$PARENT_DIR" >> "$LOG_FILE"
echo "OUTPUT_FILE=$OUTPUT_FILE" >> "$LOG_FILE"
# Generate metrics
echo "# HELP subdir_size_bytes Size of subdirectories in bytes" >"$TMP_FILE"
echo "# TYPE subdir_size_bytes gauge" >>"$TMP_FILE"
echo "Script executed at $(date)" >"$LOG_FILE"
echo "PARENT_DIR=$PARENT_DIR" >>"$LOG_FILE"
echo "OUTPUT_FILE=$OUTPUT_FILE" >>"$LOG_FILE"

parent_dir_name=$(basename "$PARENT_DIR")
parent_dir_size=$(du -sb "$PARENT_DIR" | awk '{print $1}')
echo "subdir_size_bytes{directory=\"$parent_dir_name\",subdir=\"false\"} $parent_dir_size" >> "$TMP_FILE"
parent_dir_name=$(basename "$PARENT_DIR")
parent_dir_size=$(du -sb "$PARENT_DIR" | awk '{print $1}')
echo "subdir_size_bytes{directory=\"$parent_dir_name\",subdir=\"false\"} $parent_dir_size" >>"$TMP_FILE"

for dir in "$PARENT_DIR"/*/; do
if [ -d "$dir" ]; then
size=$(du -sb "$dir" | awk '{print $1}')
name=$(basename "$dir")
echo "subdir_size_bytes{directory=\"$name\",subdir=\"true\"} $size" >> "$TMP_FILE"
fi
done
for dir in "$PARENT_DIR"/*/; do
if [ -d "$dir" ]; then
size=$(du -sb "$dir" | awk '{print $1}')
name=$(basename "$dir")
echo "subdir_size_bytes{directory=\"$name\",subdir=\"true\"} $size" >>"$TMP_FILE"
fi
done

mv "$TMP_FILE" "$OUTPUT_FILE"
sleep "$SLEEP_TIME"
mv "$TMP_FILE" "$OUTPUT_FILE"
sleep "$SLEEP_TIME"
done
Empty file modified images/sftpgo/entrypoint.sh
100644 → 100755
Empty file.
Loading
Loading