From e0e15970376424f56cf4deacc73b59581c519110 Mon Sep 17 00:00:00 2001 From: Zeecka Date: Sun, 18 Jan 2026 14:31:01 +0100 Subject: [PATCH 1/4] Merging main and prod into a single branch --- .env.example | 3 +++ aperisolve/app.py | 21 ++++++++++++++++----- aperisolve/config.py | 19 +++++++++++++++---- aperisolve/templates/base.html | 1 + 4 files changed, 35 insertions(+), 9 deletions(-) diff --git a/.env.example b/.env.example index 21128ef..da7391a 100644 --- a/.env.example +++ b/.env.example @@ -10,6 +10,9 @@ CLEAR_AT_RESTART=1 SKIP_IHDR_FILL=0 REMOVAL_MIN_AGE_SECONDS=300 +GOOGLE_ADS_TXT="google.com, pub-2324718887045017, DIRECT, f08c47fec0942fa0" +CUSTOM_EXTERNAL_SCRIPT="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-2324718887045017" + # Flask configuration FLASK_DEBUG=0 diff --git a/aperisolve/app.py b/aperisolve/app.py index 97a99bc..11158c8 100644 --- a/aperisolve/app.py +++ b/aperisolve/app.py @@ -22,7 +22,13 @@ from .utils.sentry import initialize_sentry initialize_sentry() from .config import ( + CUSTOM_EXTERNAL_SCRIPT, + DB_URI, + FLASK_DEBUG, + GOOGLE_ADS_TXT, IMAGE_EXTENSIONS, + MAX_CONTENT_LENGTH, + PROJECT_VERSION, REMOVAL_MIN_AGE_SECONDS, REMOVED_IMAGES_FOLDER, RESULT_FOLDER, @@ -35,10 +41,11 @@ def create_app() -> Flask: """Create flask application with routes.""" app = Flask(__name__) app.json.sort_keys = False # type: ignore - app.config["SQLALCHEMY_DATABASE_URI"] = os.environ.get("DB_URI") - app.config["PROJECT_VERSION"] = os.getenv("PROJECT_VERSION") + app.config["PROJECT_VERSION"] = PROJECT_VERSION + app.config["CUSTOM_EXTERNAL_SCRIPT"] = CUSTOM_EXTERNAL_SCRIPT + app.config["SQLALCHEMY_DATABASE_URI"] = DB_URI app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False - app.config["MAX_CONTENT_LENGTH"] = int(os.environ.get("MAX_CONTENT_LENGTH", 1024 * 1024)) + app.config["MAX_CONTENT_LENGTH"] = MAX_CONTENT_LENGTH app.config["REDIS_QUEUE"] = Queue(connection=Redis(host="redis", port=6379)) db.init_app(app) @@ -433,10 +440,14 @@ def create_app() -> Flask: return send_file(output_file, as_attachment=True) + @app.route("/ads.txt") + def google_ads() -> str: + """Google Ads required file""" + return GOOGLE_ADS_TXT + return app if __name__ == "__main__": my_app = create_app() - debug_mode = os.environ.get("FLASK_DEBUG", "0") == "1" - my_app.run(host="0.0.0.0", port=5000, debug=debug_mode) + my_app.run(host="0.0.0.0", port=5000, debug=FLASK_DEBUG) diff --git a/aperisolve/config.py b/aperisolve/config.py index 8ecf6e6..a813a2a 100644 --- a/aperisolve/config.py +++ b/aperisolve/config.py @@ -6,12 +6,23 @@ from os import getenv from pathlib import Path -IMAGE_EXTENSIONS = [".png", ".jpg", ".jpeg", ".gif", ".bmp", ".webp", ".tiff"] -WORKER_FILES = ["binwalk", "foremost", "steghide", "zsteg", "openstego", "pcrt", "jpseek"] +PROJECT_VERSION = getenv("PROJECT_VERSION", "development") -RESULT_FOLDER = Path(__file__).parent.resolve() / "results" -REMOVED_IMAGES_FOLDER = Path(__file__).parent.resolve() / "removed_images" REMOVAL_MIN_AGE_SECONDS = int(getenv("REMOVAL_MIN_AGE_SECONDS", "300")) # 5 minutes MAX_PENDING_TIME = int(getenv("MAX_PENDING_TIME", "600")) # 10 minutes by default MAX_STORE_TIME = int(getenv("MAX_STORE_TIME", "259200")) # 3 days by default +MAX_CONTENT_LENGTH = int(getenv("MAX_CONTENT_LENGTH", "1048576")) # 1 MB by default CLEAR_AT_RESTART = int(getenv("CLEAR_AT_RESTART", "0")) + +IMAGE_EXTENSIONS = [".png", ".jpg", ".jpeg", ".gif", ".bmp", ".webp", ".tiff"] +WORKER_FILES = ["binwalk", "foremost", "steghide", "zsteg", "openstego", "pcrt", "jpseek"] + +GOOGLE_ADS_TXT = getenv("GOOGLE_ADS_TXT", "") +CUSTOM_EXTERNAL_SCRIPT = getenv("CUSTOM_EXTERNAL_SCRIPT", "") + + +RESULT_FOLDER = Path(__file__).parent.resolve() / "results" +REMOVED_IMAGES_FOLDER = Path(__file__).parent.resolve() / "removed_images" + +DB_URI = getenv("DB_URI", "") +FLASK_DEBUG = bool(getenv("FLASK_DEBUG", "0") == "1") diff --git a/aperisolve/templates/base.html b/aperisolve/templates/base.html index a2961d9..0fabf19 100644 --- a/aperisolve/templates/base.html +++ b/aperisolve/templates/base.html @@ -13,6 +13,7 @@ + From cbc2f5653b9a2b7eb84c0257d98829607d4e0443 Mon Sep 17 00:00:00 2001 From: Zeecka Date: Sun, 18 Jan 2026 14:33:37 +0100 Subject: [PATCH 2/4] Linting --- aperisolve/app.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/aperisolve/app.py b/aperisolve/app.py index 11158c8..b66a161 100644 --- a/aperisolve/app.py +++ b/aperisolve/app.py @@ -5,7 +5,6 @@ import hashlib import json -import os import shutil import time from datetime import datetime, timezone @@ -440,10 +439,10 @@ def create_app() -> Flask: return send_file(output_file, as_attachment=True) - @app.route("/ads.txt") - def google_ads() -> str: - """Google Ads required file""" - return GOOGLE_ADS_TXT + @app.route("/ads.txt") + def google_ads() -> str: + """Google Ads required file""" + return GOOGLE_ADS_TXT return app From 0f83855e85a38f174474033a553281c3ae977230 Mon Sep 17 00:00:00 2001 From: Zeecka Date: Sun, 18 Jan 2026 14:36:34 +0100 Subject: [PATCH 3/4] release.yml --- .github/workflows/release.yml | 62 +++-------------------------------- 1 file changed, 4 insertions(+), 58 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6812636..e39959d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -13,17 +13,6 @@ jobs: - name: Get release version run: echo "RELEASE_VERSION=${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV - - name: Determine tag type (prod vs main) - id: tag_type - run: | - if [[ "${{ env.RELEASE_VERSION }}" == *"-prod"* ]]; then - echo "is_prod_tag=true" >> $GITHUB_OUTPUT - echo "📦 Prod tag detected - will push :latest-prod" - else - echo "is_prod_tag=false" >> $GITHUB_OUTPUT - echo "📦 Main tag detected - will push :latest" - fi - - name: Checkout uses: actions/checkout@v4 @@ -40,20 +29,8 @@ jobs: username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - # Build and push for PROD tags (X.X.X-prod) - - name: Build and push Docker images (prod) - if: steps.tag_type.outputs.is_prod_tag == 'true' - uses: docker/build-push-action@v6.9.0 - with: - context: ./ - push: true - tags: | - ghcr.io/zeecka/aperisolve:${{ env.RELEASE_VERSION }} - ghcr.io/zeecka/aperisolve:prod - # Build and push for MAIN tags (X.X.X) - - name: Build and push Docker images (main) - if: steps.tag_type.outputs.is_prod_tag == 'false' + - name: Build and push Docker images uses: docker/build-push-action@v6.9.0 with: context: ./ @@ -73,39 +50,6 @@ jobs: with: fetch-depth: 0 - - name: Check if tag is from prod branch - id: check - run: | - TAG_REF="${GITHUB_REF#refs/tags/}" - echo "Tag: $TAG_REF" - echo "Commit SHA: $GITHUB_SHA" - - # Get branches containing this commit - BRANCHES=$(git branch -r --contains HEAD) - echo "Branches containing this commit: $BRANCHES" - - # Check if commit is on prod branch - if echo "$BRANCHES" | grep -q "origin/prod"; then - # Additional check: ensure this commit is at the HEAD of prod - # This prevents deployment if the same commit exists on multiple branches - PROD_HEAD=$(git rev-parse origin/prod) - TAG_COMMIT=$(git rev-parse HEAD) - - echo "Prod HEAD: $PROD_HEAD" - echo "Tag commit: $TAG_COMMIT" - - if [ "$PROD_HEAD" = "$TAG_COMMIT" ]; then - echo "is_prod=true" >> $GITHUB_OUTPUT - echo "✅ Tag is at prod branch HEAD - will deploy" - else - echo "is_prod=false" >> $GITHUB_OUTPUT - echo "⚠️ Commit is on prod but not at HEAD - skipping deployment" - fi - else - echo "is_prod=false" >> $GITHUB_OUTPUT - echo "❌ Tag is not from prod branch - skipping deployment" - fi - # wait for 120 seconds - name: Wait for image propagation if: steps.check.outputs.is_prod == 'true' @@ -114,7 +58,6 @@ jobs: sleep 120 - name: Deploy to production server - if: steps.check.outputs.is_prod == 'true' uses: appleboy/ssh-action@v1.0.3 with: host: ${{ secrets.PROD_SSH_HOST }} @@ -138,6 +81,9 @@ jobs: SKIP_IHDR_FILL=${{ vars.SKIP_IHDR_FILL }} REMOVAL_MIN_AGE_SECONDS=${{ vars.REMOVAL_MIN_AGE_SECONDS }} + GOOGLE_ADS_TXT=${{ vars.GOOGLE_ADS_TXT }} + CUSTOM_EXTERNAL_SCRIPT=${{ vars.CUSTOM_EXTERNAL_SCRIPT }} + FLASK_DEBUG=${{ vars.FLASK_DEBUG }} RQ_DASHBOARD_REDIS_URL=${{ vars.RQ_DASHBOARD_REDIS_URL }} From 6794744dbfc1eeb67d9fd4e77ee0e34a4fca3450 Mon Sep 17 00:00:00 2001 From: Zeecka Date: Sun, 18 Jan 2026 14:39:45 +0100 Subject: [PATCH 4/4] Bump version for release --- .env.example | 2 +- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.env.example b/.env.example index da7391a..3d231af 100644 --- a/.env.example +++ b/.env.example @@ -2,7 +2,7 @@ WEB_APP_PORT=5000 # Application configuration -PROJECT_VERSION=3.1.2 +PROJECT_VERSION=3.1.3 MAX_CONTENT_LENGTH=3145728 MAX_PENDING_TIME=600 MAX_STORE_TIME=259200 diff --git a/pyproject.toml b/pyproject.toml index 52d16ac..1be4be7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,7 +3,7 @@ [project] name = "aperisolve" -version = "3.1.2" +version = "3.1.3" description = "Open-source steganalysis web platform for automated image analysis and steganography detection" readme = "README.md" requires-python = ">=3.12"