Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
67 changes: 67 additions & 0 deletions .github/workflows/build-and-publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
name: Build and Publish Docker Image

on:
push:
branches:
- master
pull_request:
types: [closed]
branches:
- master
workflow_dispatch:

permissions:
contents: read

env:
PROGET_REGISTRY: proget.accruentsystems.com
IMAGE_NAME: proget.accruentsystems.com/qe_docker/library/rfhistoric

jobs:
build-and-publish:
if: >
github.event_name == 'push' ||
github.event_name == 'workflow_dispatch' ||
(github.event_name == 'pull_request' && github.event.pull_request.merged == true)
runs-on: ubuntu-latest
name: Build and Publish to ProGet

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Get version
id: version
run: |
VERSION=$(python -c "import sys; sys.path.insert(0, '.'); from version import VERSION; print(VERSION)")
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "[INFO] Building version: $VERSION"

- name: Log in to ProGet Docker registry
uses: docker/login-action@v3
with:
registry: ${{ env.PROGET_REGISTRY }}
username: ${{ secrets.PROGET_USERNAME }}
password: ${{ secrets.PROGET_PASSWORD }}

- name: Build Docker image
run: |
docker build \
-t ${{ env.IMAGE_NAME }}:latest \
-t ${{ env.IMAGE_NAME }}:${{ steps.version.outputs.version }} \
.
echo "[INFO] Built image: ${{ env.IMAGE_NAME }}:${{ steps.version.outputs.version }}"

- name: Push Docker image
run: |
docker push ${{ env.IMAGE_NAME }}:latest
docker push ${{ env.IMAGE_NAME }}:${{ steps.version.outputs.version }}
echo "[SUCCESS] Pushed ${{ env.IMAGE_NAME }}:latest and :${{ steps.version.outputs.version }}"

- name: Summary
run: |
echo "## Docker Image Published" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Registry:** ${{ env.PROGET_REGISTRY }}" >> $GITHUB_STEP_SUMMARY
echo "**Image:** ${{ env.IMAGE_NAME }}" >> $GITHUB_STEP_SUMMARY
echo "**Tags:** \`latest\`, \`${{ steps.version.outputs.version }}\`" >> $GITHUB_STEP_SUMMARY
6 changes: 5 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@ FROM python:3.9
# Install any needed packages
RUN apt-get update \
&& rm -rf /var/lib/apt/lists/*
RUN pip install git+https://github.com/accruent/robotframework-historic

# Copy source and install locally so the build reflects local changes
COPY . /app
WORKDIR /app
RUN pip install .

# Make port 5000 available to the world outside this container
EXPOSE 5000
Expand Down
36 changes: 18 additions & 18 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ services:
# Database
db:
image: mysql:5.7
command: --sql-mode="STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"
volumes:
- db_data:/var/lib/mysql
- ./docker/init.sql:/docker-entrypoint-initdb.d/init.sql
restart: always
environment:
MYSQL_ROOT_PASSWORD: password
Expand All @@ -27,24 +29,22 @@ services:
MYSQL_ROOT_PASSWORD: password
networks:
- rf
# rfhistoric
# rfhistoric:
# depends_on:
# - db
# image: proget.accruentsystems.com/qe_docker/library/rfhistoric:latest
# restart: always
# ports:
# - '5000:5000'
# environment:
# SQLHOST: db
# PORT: 3306
# USERNAME: username
# PASSWORD: password
# FLASKHOST: 0.0.0.0
# links:
# - db
# networks:
# - rf
# rfhistoric - build locally with: docker compose build rfhistoric
rfhistoric:
depends_on:
- db
build: .
restart: always
ports:
- '5001:5000'
environment:
SQLHOST: db
PORT: 3306
USERNAME: root
PASSWORD: password
FLASKHOST: 0.0.0.0
networks:
- rf
networks:
rf:
volumes:
Expand Down
230 changes: 230 additions & 0 deletions docker/init.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,230 @@
-- ============================================================
-- RF Historic local dev seed data
-- Three scenarios to validate the dashboard redirect logic:
-- 1. rf_full_data - full RF results (dashboard should render normally)
-- 2. roomba_sync_data - executions only, no suite/test rows (should redirect to ehistoric)
-- 3. empty_project - no executions at all (should show no-data redirect page)
-- ============================================================

-- ------------------------------------------------------------
-- Bootstrap: core registry database and user accounts database
-- ------------------------------------------------------------
CREATE DATABASE IF NOT EXISTS robothistoric;
CREATE DATABASE IF NOT EXISTS accounts;

USE accounts;

CREATE TABLE IF NOT EXISTS TB_USERS (
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255),
email VARCHAR(255),
password VARCHAR(255)
);

-- Test login: admin@local / admin
INSERT INTO TB_USERS (name, email, password)
VALUES ('Admin', 'admin@local', '$2b$12$/3e9h/RIPYK2xIKOoIVXd.mpHrBT4AsWkv8wJYXTrQWJEu4Ah3v8u');

USE robothistoric;

CREATE TABLE IF NOT EXISTS TB_PROJECT (
Project_Id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
Project_Name VARCHAR(255),
Project_Desc TEXT,
Project_Image TEXT,
Created_Date DATETIME,
Last_Updated DATETIME,
Total_Executions INT,
Recent_Pass_Perc FLOAT,
Overall_Pass_Perc FLOAT
);

INSERT INTO TB_PROJECT (Project_Id, Project_Name, Project_Desc, Project_Image, Created_Date, Last_Updated, Total_Executions, Recent_Pass_Perc, Overall_Pass_Perc)
VALUES
(0, 'rf_full_data', 'Full RF results - dashboard should render normally', '', NOW(), NOW(), 3, 75.0, 70.0),
(0, 'roomba_sync_data', 'Roomba synced executions only - should redirect to ehistoric', '', NOW(), NOW(), 2, 0.0, 0.0),
(0, 'empty_project', 'No executions at all - should show no-data redirect page', '', NOW(), NOW(), 0, 0.0, 0.0);

-- ------------------------------------------------------------
-- Scenario 1: rf_full_data - executions + suites + tests
-- ------------------------------------------------------------
CREATE DATABASE IF NOT EXISTS rf_full_data;
USE rf_full_data;

CREATE TABLE IF NOT EXISTS TB_EXECUTION (
Execution_Id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
Execution_Date DATETIME,
Execution_Desc TEXT,
Execution_Total INT,
Execution_Pass INT,
Execution_Fail INT,
Execution_Time FLOAT,
Execution_STotal INT,
Execution_SPass INT,
Execution_SFail INT,
Execution_Skip INT,
Execution_SSkip INT
);

CREATE TABLE IF NOT EXISTS TB_SUITE (
Suite_Id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
Execution_Id INT,
Suite_Name TEXT,
Suite_Status CHAR(4),
Suite_Total INT,
Suite_Pass INT,
Suite_Fail INT,
Suite_Time FLOAT,
Suite_Skip INT
);

CREATE TABLE IF NOT EXISTS TB_TEST (
Test_Id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
Execution_Id INT,
Test_Name TEXT,
Test_Status CHAR(4),
Test_Time FLOAT,
Test_Error TEXT,
Test_Comment TEXT,
Test_Assigned_To TEXT,
Test_ETA TEXT,
Test_Review_By TEXT,
Test_Issue_Type TEXT,
Test_Tag TEXT,
Test_Updated TEXT
);

INSERT INTO TB_EXECUTION (Execution_Date, Execution_Desc, Execution_Total, Execution_Pass, Execution_Fail, Execution_Time, Execution_STotal, Execution_SPass, Execution_SFail, Execution_Skip, Execution_SSkip)
VALUES
(NOW() - INTERVAL 2 DAY, 'Run 1', 4, 3, 1, 12.5, 2, 1, 1, 0, 0),
(NOW() - INTERVAL 1 DAY, 'Run 2', 4, 4, 0, 10.2, 2, 2, 0, 0, 0),
(NOW(), 'Run 3', 4, 3, 1, 11.8, 2, 1, 1, 0, 0);

INSERT INTO TB_SUITE (Execution_Id, Suite_Name, Suite_Status, Suite_Total, Suite_Pass, Suite_Fail, Suite_Time, Suite_Skip)
VALUES
(1, 'Login Suite', 'FAIL', 2, 1, 1, 6.0, 0),
(1, 'Search Suite', 'PASS', 2, 2, 0, 6.5, 0),
(2, 'Login Suite', 'PASS', 2, 2, 0, 5.1, 0),
(2, 'Search Suite', 'PASS', 2, 2, 0, 5.1, 0),
(3, 'Login Suite', 'PASS', 2, 2, 0, 5.9, 0),
(3, 'Search Suite', 'FAIL', 2, 1, 1, 5.9, 0);

INSERT INTO TB_TEST (Execution_Id, Test_Name, Test_Status, Test_Time, Test_Error)
VALUES
(1, 'Valid login', 'PASS', 3.1, ''),
(1, 'Invalid login', 'FAIL', 2.9, 'Element not found'),
(1, 'Search by name', 'PASS', 3.2, ''),
(1, 'Search by tag', 'PASS', 3.3, ''),
(2, 'Valid login', 'PASS', 2.5, ''),
(2, 'Invalid login', 'PASS', 2.6, ''),
(2, 'Search by name', 'PASS', 2.5, ''),
(2, 'Search by tag', 'PASS', 2.5, ''),
(3, 'Valid login', 'PASS', 2.9, ''),
(3, 'Invalid login', 'PASS', 3.0, ''),
(3, 'Search by name', 'FAIL', 2.9, 'Timeout waiting for results'),
(3, 'Search by tag', 'PASS', 3.0, '');

-- ------------------------------------------------------------
-- Scenario 2: roomba_sync_data - executions only, no suite/test rows
-- ------------------------------------------------------------
CREATE DATABASE IF NOT EXISTS roomba_sync_data;
USE roomba_sync_data;

CREATE TABLE IF NOT EXISTS TB_EXECUTION (
Execution_Id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
Execution_Date DATETIME,
Execution_Desc TEXT,
Execution_Total INT,
Execution_Pass INT,
Execution_Fail INT,
Execution_Time FLOAT,
Execution_STotal INT,
Execution_SPass INT,
Execution_SFail INT,
Execution_Skip INT,
Execution_SSkip INT
);

CREATE TABLE IF NOT EXISTS TB_SUITE (
Suite_Id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
Execution_Id INT,
Suite_Name TEXT,
Suite_Status CHAR(4),
Suite_Total INT,
Suite_Pass INT,
Suite_Fail INT,
Suite_Time FLOAT,
Suite_Skip INT
);

CREATE TABLE IF NOT EXISTS TB_TEST (
Test_Id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
Execution_Id INT,
Test_Name TEXT,
Test_Status CHAR(4),
Test_Time FLOAT,
Test_Error TEXT,
Test_Comment TEXT,
Test_Assigned_To TEXT,
Test_ETA TEXT,
Test_Review_By TEXT,
Test_Issue_Type TEXT,
Test_Tag TEXT,
Test_Updated TEXT
);

-- Only executions - no suite or test rows (simulates roomba sync)
INSERT INTO TB_EXECUTION (Execution_Date, Execution_Desc, Execution_Total, Execution_Pass, Execution_Fail, Execution_Time, Execution_STotal, Execution_SPass, Execution_SFail, Execution_Skip, Execution_SSkip)
VALUES
(NOW() - INTERVAL 1 DAY, 'Roomba sync run 1', 0, 0, 0, 0.0, 0, 0, 0, 0, 0),
(NOW(), 'Roomba sync run 2', 0, 0, 0, 0.0, 0, 0, 0, 0, 0);

-- ------------------------------------------------------------
-- Scenario 3: empty_project - no data at all (tables exist but are empty)
-- ------------------------------------------------------------
CREATE DATABASE IF NOT EXISTS empty_project;
USE empty_project;

CREATE TABLE IF NOT EXISTS TB_EXECUTION (
Execution_Id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
Execution_Date DATETIME,
Execution_Desc TEXT,
Execution_Total INT,
Execution_Pass INT,
Execution_Fail INT,
Execution_Time FLOAT,
Execution_STotal INT,
Execution_SPass INT,
Execution_SFail INT,
Execution_Skip INT,
Execution_SSkip INT
);

CREATE TABLE IF NOT EXISTS TB_SUITE (
Suite_Id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
Execution_Id INT,
Suite_Name TEXT,
Suite_Status CHAR(4),
Suite_Total INT,
Suite_Pass INT,
Suite_Fail INT,
Suite_Time FLOAT,
Suite_Skip INT
);

CREATE TABLE IF NOT EXISTS TB_TEST (
Test_Id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
Execution_Id INT,
Test_Name TEXT,
Test_Status CHAR(4),
Test_Time FLOAT,
Test_Error TEXT,
Test_Comment TEXT,
Test_Assigned_To TEXT,
Test_ETA TEXT,
Test_Review_By TEXT,
Test_Issue_Type TEXT,
Test_Tag TEXT,
Test_Updated TEXT
);
-- No rows inserted - empty tables
4 changes: 4 additions & 0 deletions robotframework_historic/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,10 @@ def dashboard(db):
execution_fail_data=execution_fail_data,
execution_time_data=execution_time_data,db_name=db)

elif results_data[0][0] > 0:
# Execution data exists but no suite/test rows (e.g. roomba-synced project)
return redirect(url_for('ehistoric', db=db))

else:
return redirect(url_for('redirect_url'))

Expand Down
2 changes: 1 addition & 1 deletion version.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
"""Pypi version goes here. Update with releases."""
VERSION = "0.1.8"
VERSION = "0.1.9"
Loading