Compare commits
9
Commits
99be50ebc6
...
355c6e1bc0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
355c6e1bc0 | ||
|
|
907616511b | ||
|
|
939fa4270a | ||
|
|
1f4bf3219b | ||
|
|
df03c52a05 | ||
|
|
d63a623763 | ||
|
|
7ed264db5a | ||
|
|
6fec838344 | ||
|
|
4c160924f7 |
@@ -24,11 +24,11 @@ jobs:
|
|||||||
apt-get install -y python3 python3-pip python3-venv curl
|
apt-get install -y python3 python3-pip python3-venv curl
|
||||||
fi
|
fi
|
||||||
python3 -m pip install --upgrade pip --break-system-packages || python3 -m pip install --upgrade pip || true
|
python3 -m pip install --upgrade pip --break-system-packages || python3 -m pip install --upgrade pip || true
|
||||||
pip3 install -r requirements.txt --break-system-packages || pip3 install -r requirements.txt
|
pip3 install -r compilation/requirements.txt --break-system-packages || pip3 install -r compilation/requirements.txt
|
||||||
|
|
||||||
- name: Verify Python Syntax
|
- name: Verify Python Syntax
|
||||||
run: |
|
run: |
|
||||||
python3 -m py_compile src/Server.py src/Win_Client.py src/Linux_Client.py package_dist.py upload_release.py test_pipeline.py tests/*.py
|
python3 -m py_compile src/Server.py src/Win_Client.py src/Linux_Client.py compilation/package_dist.py compilation/upload_release.py tests/test_pipeline.py tests/*.py
|
||||||
|
|
||||||
- name: Run Component Unit Tests
|
- name: Run Component Unit Tests
|
||||||
run: |
|
run: |
|
||||||
@@ -65,7 +65,7 @@ jobs:
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# 4. Execute end-to-end integration test
|
# 4. Execute end-to-end integration test
|
||||||
python3 test_pipeline.py
|
python3 tests/test_pipeline.py
|
||||||
|
|
||||||
# 5. Cleanly terminate background server
|
# 5. Cleanly terminate background server
|
||||||
kill $SERVER_PID || true
|
kill $SERVER_PID || true
|
||||||
|
|||||||
@@ -26,11 +26,11 @@ jobs:
|
|||||||
apt-get install -y python3 python3-pip python3-venv binutils zip
|
apt-get install -y python3 python3-pip python3-venv binutils zip
|
||||||
fi
|
fi
|
||||||
python3 -m pip install --upgrade pip --break-system-packages || python3 -m pip install --upgrade pip || true
|
python3 -m pip install --upgrade pip --break-system-packages || python3 -m pip install --upgrade pip || true
|
||||||
pip3 install pyinstaller -r requirements.txt --break-system-packages || pip3 install pyinstaller -r requirements.txt
|
pip3 install pyinstaller -r compilation/requirements.txt --break-system-packages || pip3 install pyinstaller -r compilation/requirements.txt
|
||||||
|
|
||||||
- name: Compile Standalone Linux Binaries
|
- name: Compile Standalone Linux Binaries
|
||||||
run: |
|
run: |
|
||||||
python3 package_dist.py --target linux
|
python3 compilation/package_dist.py --target linux
|
||||||
|
|
||||||
- name: Publish Linux Release Assets
|
- name: Publish Linux Release Assets
|
||||||
env:
|
env:
|
||||||
@@ -39,4 +39,4 @@ jobs:
|
|||||||
GITEA_REPOSITORY: ${{ github.repository }}
|
GITEA_REPOSITORY: ${{ github.repository }}
|
||||||
GITEA_REF_NAME: ${{ inputs.tag || github.ref_name }}
|
GITEA_REF_NAME: ${{ inputs.tag || github.ref_name }}
|
||||||
run: |
|
run: |
|
||||||
python3 upload_release.py --skip-build
|
python3 compilation/upload_release.py --skip-build
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ jobs:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
& $py -m pip install --upgrade pip
|
& $py -m pip install --upgrade pip
|
||||||
& $py -m pip install pyinstaller -r requirements.txt
|
& $py -m pip install pyinstaller -r compilation/requirements.txt
|
||||||
|
|
||||||
- name: Compile Standalone Windows Binaries
|
- name: Compile Standalone Windows Binaries
|
||||||
shell: powershell
|
shell: powershell
|
||||||
@@ -46,7 +46,7 @@ jobs:
|
|||||||
$py = "py -3.12"
|
$py = "py -3.12"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
& $py package_dist.py --target windows
|
& $py compilation/package_dist.py --target windows
|
||||||
|
|
||||||
- name: Publish Windows Release Assets
|
- name: Publish Windows Release Assets
|
||||||
shell: powershell
|
shell: powershell
|
||||||
@@ -62,4 +62,4 @@ jobs:
|
|||||||
$py = "py -3.12"
|
$py = "py -3.12"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
& $py upload_release.py --skip-build
|
& $py compilation/upload_release.py --skip-build
|
||||||
|
|||||||
@@ -177,22 +177,24 @@ LOGAR/
|
|||||||
│ ├── ci.yml # Continuous Integration automated test suite (runs on every push)
|
│ ├── ci.yml # Continuous Integration automated test suite (runs on every push)
|
||||||
│ ├── release-linux.yml # Linux release workflow (compiles Server.bin, Linux_Client.bin, checksums)
|
│ ├── release-linux.yml # Linux release workflow (compiles Server.bin, Linux_Client.bin, checksums)
|
||||||
│ └── release-windows.yml # Windows release workflow (compiles Server.exe, Win_Client.exe, checksums)
|
│ └── release-windows.yml # Windows release workflow (compiles Server.exe, Win_Client.exe, checksums)
|
||||||
├── .gitignore # Ignore venv, caches, DBs, and private keys
|
├── compilation/ # Build, packaging, and release automation tools
|
||||||
├── requirements.txt # Unified dependencies
|
│ ├── package_dist.py # Multi-platform standalone binary packaging script
|
||||||
├── README.md # Comprehensive documentation
|
│ ├── requirements.txt # Unified project dependencies
|
||||||
|
│ └── upload_release.py # Direct Gitea REST API release asset publisher
|
||||||
├── src/ # Core application source modules
|
├── src/ # Core application source modules
|
||||||
│ ├── __init__.py
|
│ ├── __init__.py
|
||||||
│ ├── Server.py # Central TCP server and Hermes API
|
│ ├── Server.py # Central TCP server and Hermes API
|
||||||
│ ├── Win_Client.py # Windows edge forwarder
|
│ ├── Win_Client.py # Windows edge forwarder
|
||||||
│ └── Linux_Client.py # Linux edge forwarder
|
│ └── Linux_Client.py # Linux edge forwarder
|
||||||
├── server_config.sample.json # Central server sample configuration
|
├── tests/ # Automated test suites
|
||||||
├── package_dist.py # Multi-platform standalone binary packaging script
|
│ ├── test_linux_client.py # Linux client unit tests
|
||||||
├── upload_release.py # Direct Gitea REST API release asset publisher
|
│ ├── test_pipeline.py # End-to-end integration test
|
||||||
├── test_pipeline.py # End-to-end integration test
|
|
||||||
├── tests/ # Unified unit test suites
|
|
||||||
│ ├── test_server.py # Server unit tests
|
│ ├── test_server.py # Server unit tests
|
||||||
│ ├── test_win_client.py # Windows client unit tests
|
│ └── test_win_client.py # Windows client unit tests
|
||||||
│ └── test_linux_client.py # Linux client unit tests
|
├── .gitignore # Ignore venv, caches, DBs, and private keys
|
||||||
|
├── README.md # Comprehensive documentation
|
||||||
|
├── RELEASE_NOTES.md # Release history and changelog
|
||||||
|
├── server_config.sample.json # Central server sample configuration
|
||||||
└── out/ # Edge forwarder deployment packages
|
└── out/ # Edge forwarder deployment packages
|
||||||
├── win_client/
|
├── win_client/
|
||||||
│ ├── client_config.sample.json # Reference client configuration
|
│ ├── client_config.sample.json # Reference client configuration
|
||||||
@@ -210,7 +212,7 @@ LOGAR/
|
|||||||
|
|
||||||
1. **Install dependencies**:
|
1. **Install dependencies**:
|
||||||
```bash
|
```bash
|
||||||
pip install -r requirements.txt
|
pip install -r compilation/requirements.txt
|
||||||
```
|
```
|
||||||
2. **Start the server** (generates `server_config.json` and keypair on first run):
|
2. **Start the server** (generates `server_config.json` and keypair on first run):
|
||||||
```bash
|
```bash
|
||||||
@@ -297,15 +299,15 @@ The pipeline test exercises invalid token rejection, encrypted socket streaming,
|
|||||||
```
|
```
|
||||||
3. **Execute the integration test** in Shell 2:
|
3. **Execute the integration test** in Shell 2:
|
||||||
```bash
|
```bash
|
||||||
python test_pipeline.py
|
python tests/test_pipeline.py
|
||||||
```
|
```
|
||||||
|
|
||||||
## Continuous Integration via Gitea Actions
|
## Continuous Integration via Gitea Actions
|
||||||
|
|
||||||
Continuous integration is automated via [`.gitea/workflows/ci.yml`](.gitea/workflows/ci.yml) and triggers automatically on **every push** and pull request:
|
Continuous integration is automated via [`.gitea/workflows/ci.yml`](.gitea/workflows/ci.yml) and triggers automatically on **every push** and pull request:
|
||||||
1. **Syntax Compilation**: Validates all Python scripts (`src/Server.py`, `src/Win_Client.py`, `src/Linux_Client.py`, `package_dist.py`, `upload_release.py`, `test_pipeline.py`, and test suites).
|
1. **Syntax Compilation**: Validates all Python scripts (`src/Server.py`, `src/Win_Client.py`, `src/Linux_Client.py`, `compilation/package_dist.py`, `compilation/upload_release.py`, `tests/test_pipeline.py`, and test suites).
|
||||||
2. **Component Unit Tests**: Discovers and runs all unit tests in `tests/` (`test_server.py`, `test_win_client.py`, `test_linux_client.py`).
|
2. **Component Unit Tests**: Discovers and runs all unit tests in `tests/` (`test_server.py`, `test_win_client.py`, `test_linux_client.py`).
|
||||||
3. **End-to-End Pipeline Verification**: Automatically spins up the LOGAR server hub, generates test configs, runs `test_pipeline.py` (testing socket authentication, 4-run rule persistence, Hermes API report, and client integrations), and shuts down the test instance.
|
3. **End-to-End Pipeline Verification**: Automatically spins up the LOGAR server hub, generates test configs, runs `tests/test_pipeline.py` (testing socket authentication, 4-run rule persistence, Hermes API report, and client integrations), and shuts down the test instance.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -362,13 +364,13 @@ git push origin v1.0.1
|
|||||||
You can also compile and package binaries locally anytime:
|
You can also compile and package binaries locally anytime:
|
||||||
```bash
|
```bash
|
||||||
# Windows
|
# Windows
|
||||||
py -3.12 package_dist.py --target windows
|
py -3.12 compilation/package_dist.py --target windows
|
||||||
|
|
||||||
# Linux
|
# Linux
|
||||||
python3 package_dist.py --target linux
|
python3 compilation/package_dist.py --target linux
|
||||||
```
|
```
|
||||||
To upload local builds directly to Gitea:
|
To upload local builds directly to Gitea:
|
||||||
```powershell
|
```powershell
|
||||||
python upload_release.py --tag v1.0.1 --token <YOUR_GITEA_TOKEN>
|
python compilation/upload_release.py --tag v1.0.1 --token <YOUR_GITEA_TOKEN>
|
||||||
```
|
```
|
||||||
*(Environment variables `GITEA_TOKEN`, `GITEA_SERVER_URL`, `GITEA_REPOSITORY`, and `GITEA_REF_NAME` are also supported automatically).*
|
*(Environment variables `GITEA_TOKEN`, `GITEA_SERVER_URL`, `GITEA_REPOSITORY`, and `GITEA_REF_NAME` are also supported automatically).*
|
||||||
|
|||||||
@@ -7,10 +7,10 @@ import platform
|
|||||||
import subprocess
|
import subprocess
|
||||||
import argparse
|
import argparse
|
||||||
|
|
||||||
ROOT_DIR = os.path.abspath(os.path.dirname(__file__))
|
ROOT_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
|
||||||
SRC_DIR = os.path.join(ROOT_DIR, "src")
|
SRC_DIR = os.path.join(ROOT_DIR, "src")
|
||||||
DIST_DIR = os.path.abspath("dist")
|
DIST_DIR = os.path.join(ROOT_DIR, "dist")
|
||||||
BUILD_TEMP = os.path.abspath("build_temp")
|
BUILD_TEMP = os.path.join(ROOT_DIR, "build_temp")
|
||||||
|
|
||||||
def clean_and_prep():
|
def clean_and_prep():
|
||||||
if os.path.exists(DIST_DIR):
|
if os.path.exists(DIST_DIR):
|
||||||
@@ -4,7 +4,8 @@ import json
|
|||||||
import argparse
|
import argparse
|
||||||
import urllib.request
|
import urllib.request
|
||||||
import urllib.parse
|
import urllib.parse
|
||||||
import mimetypes
|
ROOT_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
|
||||||
|
sys.path.insert(0, os.path.dirname(__file__))
|
||||||
import package_dist
|
import package_dist
|
||||||
|
|
||||||
import time
|
import time
|
||||||
@@ -162,8 +163,8 @@ def main():
|
|||||||
if not notes and args.notes_file and os.path.exists(args.notes_file):
|
if not notes and args.notes_file and os.path.exists(args.notes_file):
|
||||||
with open(args.notes_file, "r", encoding="utf-8") as nf:
|
with open(args.notes_file, "r", encoding="utf-8") as nf:
|
||||||
notes = nf.read()
|
notes = nf.read()
|
||||||
elif not notes and os.path.exists("RELEASE_NOTES.md"):
|
elif not notes and os.path.exists(os.path.join(ROOT_DIR, "RELEASE_NOTES.md")):
|
||||||
with open("RELEASE_NOTES.md", "r", encoding="utf-8") as nf:
|
with open(os.path.join(ROOT_DIR, "RELEASE_NOTES.md"), "r", encoding="utf-8") as nf:
|
||||||
notes = nf.read()
|
notes = nf.read()
|
||||||
elif not notes:
|
elif not notes:
|
||||||
notes = (
|
notes = (
|
||||||
@@ -184,9 +185,9 @@ def main():
|
|||||||
print("[*] Assembling compiled binaries...")
|
print("[*] Assembling compiled binaries...")
|
||||||
package_dist.main()
|
package_dist.main()
|
||||||
|
|
||||||
dist_dir = os.path.abspath("dist")
|
dist_dir = os.path.join(ROOT_DIR, "dist")
|
||||||
if not os.path.exists(dist_dir) or not os.listdir(dist_dir):
|
if not os.path.exists(dist_dir) or not os.listdir(dist_dir):
|
||||||
print("[!] No binaries found in dist/. Run package_dist.py first.")
|
print(f"[!] No binaries found in {dist_dir}. Run package_dist.py first.")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
print(f"[*] Connecting to Gitea: {args.url} (repo: {args.repo})...")
|
print(f"[*] Connecting to Gitea: {args.url} (repo: {args.repo})...")
|
||||||
@@ -9,8 +9,11 @@ import urllib.request
|
|||||||
import warnings
|
import warnings
|
||||||
from datetime import datetime, timezone, timedelta
|
from datetime import datetime, timezone, timedelta
|
||||||
|
|
||||||
# Ensure src/ directory is in sys.path
|
# Ensure repository root and src/ directory are in sys.path
|
||||||
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "src")))
|
ROOT_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
|
||||||
|
SRC_DIR = os.path.join(ROOT_DIR, "src")
|
||||||
|
sys.path.insert(0, ROOT_DIR)
|
||||||
|
sys.path.insert(0, SRC_DIR)
|
||||||
|
|
||||||
warnings.filterwarnings("ignore")
|
warnings.filterwarnings("ignore")
|
||||||
import pgpy
|
import pgpy
|
||||||
@@ -23,13 +26,16 @@ HERMES_PORT = 8443
|
|||||||
|
|
||||||
def run_tests():
|
def run_tests():
|
||||||
print("=== [1] Verifying server_config.json & client_config.json ===")
|
print("=== [1] Verifying server_config.json & client_config.json ===")
|
||||||
assert os.path.exists("server_config.json"), "server_config.json must exist"
|
server_cfg_path = "server_config.json" if os.path.exists("server_config.json") else os.path.join(ROOT_DIR, "server_config.json")
|
||||||
assert os.path.exists("client_config.json"), "client_config.json must exist"
|
client_cfg_path = "client_config.json" if os.path.exists("client_config.json") else os.path.join(ROOT_DIR, "client_config.json")
|
||||||
|
|
||||||
|
assert os.path.exists(server_cfg_path), f"{server_cfg_path} must exist"
|
||||||
|
assert os.path.exists(client_cfg_path), f"{client_cfg_path} must exist"
|
||||||
|
|
||||||
with open("client_config.json", "r", encoding="utf-8") as f:
|
with open(client_cfg_path, "r", encoding="utf-8") as f:
|
||||||
client_conf = json.load(f)
|
client_conf = json.load(f)
|
||||||
|
|
||||||
with open("server_config.json", "r", encoding="utf-8") as f:
|
with open(server_cfg_path, "r", encoding="utf-8") as f:
|
||||||
server_conf = json.load(f)
|
server_conf = json.load(f)
|
||||||
|
|
||||||
assert "server_name" not in client_conf, "client_config.json must NOT contain server_name"
|
assert "server_name" not in client_conf, "client_config.json must NOT contain server_name"
|
||||||
Reference in New Issue
Block a user