48 Commits

Author SHA1 Message Date
Marcin-Ramotowski b56efa4fa3 Automatyczna zmiana: 1753630035 2025-07-27 17:29:21 +02:00
Marcin-Ramotowski bb0a6e5dd9 Automatyczna zmiana: 1753629562 2025-07-27 17:29:13 +02:00
Marcin-Ramotowski 072cf7e9aa Automatyczna zmiana: 1753628608 2025-07-27 17:03:34 +02:00
Marcin-Ramotowski 17add103eb Automatyczna zmiana: 1753627976 2025-07-27 16:53:00 +02:00
Marcin-Ramotowski b887fd46b0 Automatyczna zmiana: 1753626456 2025-07-27 16:32:56 +02:00
Marcin-Ramotowski abf126f31e Automatyczna zmiana: 1753625912 2025-07-27 16:31:17 +02:00
Marcin-Ramotowski 0d6a52d2f9 Automatyczna zmiana: 1753625345 2025-07-27 16:09:10 +02:00
Marcin-Ramotowski e080594dcb Automatyczna zmiana: 1753624962 2025-07-27 16:03:26 +02:00
Marcin-Ramotowski 6a11df64b0 Automatyczna zmiana: 1753624408 2025-07-27 15:53:34 +02:00
Marcin-Ramotowski fe9a68023a Automatyczna zmiana: 1753624006 2025-07-27 15:46:56 +02:00
Marcin-Ramotowski 80210e67ea Automatyczna zmiana: 1753623624 2025-07-27 15:40:34 +02:00
Marcin-Ramotowski 300adef0f9 Updated path in repo 2025-07-27 14:56:59 +02:00
Marcin-Ramotowski 492df7e45c Changed deploy repo branch 2025-07-27 14:48:25 +02:00
Marcin-Ramotowski af829bc5bb Added overwrite output lines during waiting
ci/woodpecker/push/build Pipeline was successful
2025-07-26 16:47:54 +02:00
Marcin-Ramotowski 66e2a0e3b9 Merge branch 'dev' into woodpecker
ci/woodpecker/push/build Pipeline was successful
2025-07-26 16:35:10 +02:00
Marcin-Ramotowski 6bfcbb1c96 Automatyczna zmiana: 1753539316
ci/woodpecker/push/build Pipeline was successful
2025-07-26 16:15:16 +02:00
Marcin-Ramotowski 7072671564 Added dockerd command
ci/woodpecker/push/build Pipeline was successful
2025-07-22 19:36:56 +02:00
Marcin-Ramotowski a2c2e39a1b Corrected commands variables expansion
ci/woodpecker/push/build Pipeline failed
2025-07-22 19:30:03 +02:00
Marcin-Ramotowski 55eeec730d Added userns-mode annotation
ci/woodpecker/push/build Pipeline failed
2025-07-21 15:39:06 +02:00
Marcin-Ramotowski e6c9675abc Added sysbox as runtimeClass
ci/woodpecker/push/build Pipeline failed
2025-07-20 11:15:32 +02:00
Marcin-Ramotowski ebf713f75f Removed Goss from pipeline; added GitOps commit 2025-07-20 11:01:12 +02:00
Marcin-Ramotowski 13f098fc7c Removed Goss 2025-07-20 10:02:27 +02:00
Marcin-Ramotowski 8cf8a92f8d Removed Jenkinsfile 2025-07-20 10:01:57 +02:00
Marcin-Ramotowski 571a45d3de Added script to trigger and measure deployment time 2025-07-20 10:00:29 +02:00
Marcin-Ramotowski 560090319a Added build args to Dockerfile 2025-07-20 09:59:53 +02:00
Marcin-Ramotowski e6c68f839a Added script to trigger and measure deployment time 2025-07-20 09:54:38 +02:00
Marcin-Ramotowski fcb93a5cf8 Added build args to Dockerfile 2025-07-20 09:54:31 +02:00
Marcin-Ramotowski c9b1dac864 Added endpoint to fetch app version 2025-07-03 22:47:21 +02:00
Marcin-Ramotowski cd4ab3fd27 Handled more errors during db initialization 2025-06-12 18:42:07 +00:00
Marcin-Ramotowski 301cf5922e Changed docker image base to Alpine and added curl 2025-06-11 22:15:37 +00:00
Marcin-Ramotowski 479ec4f917 Added healthcheck 2025-06-11 22:04:35 +00:00
Marcin-Ramotowski 3f40a6126c Added more descriptions of functions 2025-06-11 20:04:04 +00:00
Marcin-Ramotowski dd9e9ce110 Improved function body 2025-06-11 19:57:15 +00:00
Marcin-Ramotowski cefb8eba4d Added missing dgoss installation
ci/woodpecker/push/build Pipeline was successful
2025-05-25 20:09:14 +00:00
Marcin-Ramotowski 1e54ba614a Corrected output path for dgoss command
ci/woodpecker/push/build Pipeline failed
2025-05-25 20:05:49 +00:00
Marcin-Ramotowski 7469609600 Removed redundant quote around dgoss command
ci/woodpecker/push/build Pipeline failed
2025-05-25 20:01:31 +00:00
Marcin-Ramotowski b7a1fcfe49 Added double quotes around dgoss run command 2025-05-25 20:00:13 +00:00
Marcin-Ramotowski a9743ecfbe Restored old procedure for Goss tests 2025-05-25 19:59:21 +00:00
Marcin-Ramotowski 76f33f50f5 Extended time to dockerd start
ci/woodpecker/push/build Pipeline failed
2025-05-25 19:54:30 +00:00
Marcin-Ramotowski 203a81573d Added dockerd start in the background
ci/woodpecker/push/build Pipeline failed
2025-05-25 19:43:19 +00:00
Marcin-Ramotowski 383e906102 Corrected image name
ci/woodpecker/push/build Pipeline failed
2025-05-25 19:36:16 +00:00
Marcin-Ramotowski e7330f07ee Returned to privileged mode
ci/woodpecker/push/build Pipeline failed
2025-05-25 19:34:22 +00:00
Marcin-Ramotowski c996be5953 Modified building step 2025-05-25 17:44:17 +00:00
Marcin-Ramotowski bf60011948 Added double quotes around command to run Dgoss 2025-05-25 17:17:11 +00:00
Marcin-Ramotowski 82d5962020 Added steps to build, test and push docker image 2025-05-25 17:14:18 +00:00
Marcin-Ramotowski 1254b036f5 Added cd to api directory
ci/woodpecker/push/build Pipeline was successful
2025-05-25 16:54:15 +00:00
Marcin-Ramotowski 6d84bf694e Added python tests to Woodpecker Workflow
ci/woodpecker/push/build Pipeline failed
2025-05-25 16:43:44 +00:00
Marcin-Ramotowski c2df9d136e Test first Woodpecker workflow
ci/woodpecker/push/my-first-workflow Pipeline failed
2025-05-25 16:19:25 +00:00
9 changed files with 208 additions and 13 deletions
+71
View File
@@ -0,0 +1,71 @@
when:
- event: [push, manual]
branch: woodpecker
steps:
- name: code-tests
image: python:3.11.7-alpine
commands:
- cd api
- python3 -m venv env
- source env/bin/activate
- pip install -r requirements.txt pytest
- python3 -m pytest --junit-xml=pytest_junit.xml
- name: build-and-push
image: marcin00.azurecr.io/azure-cli-docker:slim-bookworm
environment:
ACR_NAME: marcin00
CLIENT_ID: c302726f-fafb-4143-94c1-67a70975574a
commands:
- dockerd &
- export DOCKER_IMAGE=marcin00.azurecr.io/user-microservice:${CI_COMMIT_SHA}
- docker build -t $DOCKER_IMAGE --build-arg APP_VERSION=${CI_COMMIT_SHA} --build-arg BUILD_DATE=$(date -u +"%Y-%m-%dT%H:%M:%SZ") .
- az login --identity --client-id $CLIENT_ID
- az acr login --name $ACR_NAME
- docker push $DOCKER_IMAGE
backend_options:
kubernetes:
annotations:
io.kubernetes.cri-o.userns-mode: "auto:size=65536"
runtimeClassName: sysbox-runc
- name: gitops-commit
image: alpine/git
environment:
DEPLOY_REPO_URL: ssh://git@srv22.mikr.us:20343/pikram/user-microservice-deploy.git
DEPLOY_REPO_BRANCH: woodpecker-fluxcd-deploy
GITEA_DEPLOY_KEY:
from_secret: gitea-deploy-key
GITEA_KNOWN_HOST:
from_secret: gitea-known-host
commands:
- mkdir -p ~/.ssh
- echo "$GITEA_KNOWN_HOST" >> ~/.ssh/known_hosts
- chmod 644 ~/.ssh/known_hosts
- echo "$GITEA_DEPLOY_KEY" > ~/.ssh/id_rsa
- chmod 600 ~/.ssh/id_rsa
- git config --global user.name "woodpecker[bot]"
- git config --global user.email "woodpecker@marcin00.pl"
- git clone $DEPLOY_REPO_URL --branch $DEPLOY_REPO_BRANCH
- cd user-microservice-deploy/apps/user-microservice
- |
awk -v commit="$CI_COMMIT_SHA" '
$0 ~ /name:[[:space:]]*api/ { in_api_container = 1; print; next }
in_api_container && $0 ~ /^[[:space:]]*image:[[:space:]]*/ {
sub(/:[^:[:space:]]+$/, ":" commit)
in_api_container = 0
print
next
}
{ print }
' deploy.yaml > deploy.tmp && mv deploy.tmp deploy.yaml
- git add deploy.yaml
- 'git diff-index --quiet HEAD || git commit -m "WOODPECKER: Changed deployed version to $CI_COMMIT_SHA"'
- git push origin $DEPLOY_REPO_BRANCH
+14 -1
View File
@@ -1,5 +1,18 @@
FROM python:3.11.7-slim-bookworm
FROM python:3.11.7-alpine
# Wersja i data builda jako build-arg
ARG APP_VERSION=unknown
ARG BUILD_DATE=unknown
# Ustawiamy zmienne w ENV, by były dostępne w kontenerze
ENV APP_VERSION=$APP_VERSION
ENV BUILD_DATE=$BUILD_DATE
WORKDIR /app
COPY api .
RUN apk add --no-cache curl
RUN pip install -r requirements.txt
CMD python3 app.py
+3 -1
View File
@@ -4,6 +4,7 @@ from flask_jwt_extended import JWTManager
from jwt import ExpiredSignatureError
from models import db, RevokedToken
import os
from tech_views import tech_bp
from utils import init_db, wait_for_db
from views import user_bp
from werkzeug.exceptions import HTTPException
@@ -26,6 +27,7 @@ def create_app(config_name="default"):
# Blueprints registration
app.register_blueprint(user_bp)
app.register_blueprint(tech_bp)
# Database and JWT initialization
db.init_app(app)
@@ -53,7 +55,7 @@ def create_app(config_name="default"):
# Fill database by initial values (only if we are not testing)
with app.app_context():
wait_for_db()
wait_for_db(max_retries=100)
db.create_all()
if config_name != "testing":
init_db()
+20
View File
@@ -0,0 +1,20 @@
from flask import Blueprint, jsonify
from models import db
from sqlalchemy import text
from utils import db_ready
# Blueprint with technical endpoints
tech_bp = Blueprint('tech_bp', __name__)
@tech_bp.route('/health', methods=['GET'])
def health_check():
"Check if service works and database is functional"
try:
with db.engine.connect() as connection:
connection.execute(text("SELECT 1"))
return jsonify(status="healthy"), 200
except Exception:
if db_ready:
return jsonify(status="unhealthy"), 500
else:
return jsonify(status="starting"), 503
+11 -11
View File
@@ -3,19 +3,21 @@ from flask_jwt_extended import get_jwt_identity
from models import User, db
import os
from sqlalchemy import text
from sqlalchemy.exc import DatabaseError
from sqlalchemy.exc import DatabaseError, InterfaceError
import time
from werkzeug.security import generate_password_hash
db_ready = False
def admin_required(user_id, message='Access denied.'):
"Check if common user try to make administrative action."
user = db.session.get(User, user_id)
if user is None or user.role != "Administrator":
abort(403, message)
def validate_access(owner_id, message='Access denied.'):
# Check if user try to access or edit resource that does not belong to them
"Check if user try to access or edit resource that does not belong to them."
logged_user_id = int(get_jwt_identity())
logged_user_role = db.session.get(User, logged_user_id).role
if logged_user_role != "Administrator" and logged_user_id != owner_id:
@@ -30,20 +32,18 @@ def get_user_or_404(user_id):
return user
MAX_RETRIES = 100
def wait_for_db():
for retries in range(MAX_RETRIES):
def wait_for_db(max_retries):
"Try to connect with database <max_retries> times."
global db_ready
for _ in range(max_retries):
try:
with db.engine.connect() as connection:
connection.execute(text("SELECT 1"))
print("Successfully connected with database.")
db_ready = True
return
except DatabaseError:
print(f"Waiting for database... (retry {retries + 1})")
except DatabaseError | InterfaceError:
time.sleep(3)
print("Failed to connect to database.")
raise Exception("Database not ready after multiple retries.")
raise Exception("Failed to connect to database.")
def init_db():
+8
View File
@@ -2,6 +2,7 @@ from flask import Blueprint, jsonify, request, abort
from flask_jwt_extended import create_access_token, set_access_cookies, jwt_required, \
verify_jwt_in_request, get_jwt_identity, unset_jwt_cookies, get_jwt
from models import db, RevokedToken, User
import os
from utils import admin_required, validate_access, get_user_or_404
from werkzeug.security import check_password_hash, generate_password_hash
@@ -110,3 +111,10 @@ def user_logout():
response = jsonify({"msg": "User logged out successfully."})
unset_jwt_cookies(response)
return response
@user_bp.route('/version', methods=['GET'])
def version():
return jsonify({
"version": os.getenv("APP_VERSION", "unknown"),
"build_time": os.getenv("BUILD_DATE", "unknown")
})
+65
View File
@@ -0,0 +1,65 @@
#!/bin/bash
# === KONFIGURACJA ===
APP_URL="https://user-microservice.marcin00.pl/version"
MARKER_FILE="version_marker.txt"
OUTPUT_FILE="deployment_times.csv"
CHECK_INTERVAL=1 # sekundy
# === POBRANIE AKTUALNEJ WERSJI APLIKACJI ===
echo "[INFO] Pobieranie aktualnej wersji z /version..."
OLD_VERSION=$(curl -s "$APP_URL" | jq -r '.version')
if [[ -z "$OLD_VERSION" ]]; then
echo "[ERROR] Nie udało się pobrać aktualnej wersji aplikacji."
exit 1
fi
echo "[INFO] Aktualna wersja: $OLD_VERSION"
# === Modyfikacja pliku, commit i push ===
TIMESTAMP=$(date +%s)
echo "$TIMESTAMP" > "$MARKER_FILE"
git add "$MARKER_FILE"
git commit -m "Automatyczna zmiana: $TIMESTAMP"
START_TIME=$(date +%s)
echo "[INFO] Wykonuję git push..."
git push
if [[ $? -ne 0 ]]; then
echo "[ERROR] Push nie powiódł się."
exit 1
fi
echo "[INFO] Oczekiwanie na wdrożenie nowej wersji..."
# === Odpytywanie endpointa /version ===
WAITED=0
echo "[WAIT] Oczekiwanie na nową wersję..."
while true; do
sleep $CHECK_INTERVAL
WAITED=$((WAITED + CHECK_INTERVAL))
NEW_VERSION=$(curl -s "$APP_URL" | jq -r '.version')
if [[ "$NEW_VERSION" != "$OLD_VERSION" ]]; then
END_TIME=$(date +%s)
DURATION=$((END_TIME - START_TIME))
# Nadpisujemy linię z licznikiem
printf "\r[INFO] Nowa wersja wdrożona po %ds: %s\n" "$WAITED" "$NEW_VERSION"
echo "[INFO] Czas wdrożenia: $DURATION sekund"
echo "$START_TIME,$END_TIME,$DURATION,$OLD_VERSION,$NEW_VERSION" >> "$OUTPUT_FILE"
break
else
# Nadpisujemy TYLKO linię z licznikiem
printf "\r[WAIT] Czekam... %ds" "$WAITED"
fi
done
# Żeby kursor przeszedł do nowej linii po zakończeniu
echo ""
+15
View File
@@ -7,9 +7,24 @@ services:
build: .
env_file:
- api/.env
ports:
- 80:80
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost/health"]
interval: 10s
timeout: 5s
retries: 5
start_period: 15s
db:
container_name: db
hostname: db
image: mysql:latest
env_file:
- db/.env
ports:
- 3306:3306
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 10s
timeout: 5s
retries: 5
+1
View File
@@ -0,0 +1 @@
1753630035