Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
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
88 changes: 88 additions & 0 deletions .github/workflows/demo-release-closed-poll.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
name: Testops - TestRail Milestone CLOSED - polling
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

introducing a new workflow environment: demo for PRs
Once the PR has passed review, demo can change to either staging or production


on:
pull_request:
push:
branches: [ rpapa-release-close]
workflow_dispatch:
inputs:
branchName:
description: "rpapa branch"
required: true
default: "rpapa-release-close"

env:
CLOUD_SQL_DATABASE_NAME: preflight
CLOUD_SQL_DATABASE_USERNAME: ${{ secrets.CLOUD_SQL_DATABASE_USERNAME }}
CLOUD_SQL_DATABASE_PASSWORD: ${{ secrets.CLOUD_SQL_DATABASE_PASSWORD }}
CLOUD_SQL_DATABASE_PORT: ${{ secrets.CLOUD_SQL_DATABASE_PORT }}
TESTRAIL_HOST: ${{ secrets.TESTRAIL_HOST }}
TESTRAIL_USERNAME: ${{ secrets.TESTRAIL_USERNAME }}
TESTRAIL_PASSWORD: ${{ secrets.TESTRAIL_PASSWORD }}
ATLASSIAN_API_TOKEN: ${{ secrets.ATLASSIAN_API_TOKEN }}
ATLASSIAN_HOST: ${{ secrets.ATLASSIAN_HOST }}
ATLASSIAN_USERNAME: ${{ secrets.ATLASSIAN_USERNAME }}
JIRA_HOST: ${{ secrets.JIRA_HOST }}
JIRA_USER: ${{ secrets.JIRA_USER }}
JIRA_PASSWORD: ${{ secrets.JIRA_PASSWORD }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
BUGZILLA_API_KEY: ${{ secrets.BUGZILLA_API_KEY }}
BITRISE_HOST: ${{ secrets.BITRISE_HOST }}
BITRISE_APP_SLUG: ${{ secrets.BITRISE_APP_SLUG }}
BITRISE_TOKEN: ${{ secrets.BITRISE_TOKEN }}
SENTRY_HOST: ${{ secrets.SENTRY_HOST }}
SENTRY_API_TOKEN: ${{ secrets.SENTRY_API_TOKEN_CSO }}
SENTRY_ORGANIZATION_SLUG: ${{ secrets.SENTRY_ORGANIZATION_SLUG }}
SENTRY_IOS_PROJECT_ID: ${{ secrets.SENTRY_IOS_PROJECT_ID }}
SENTRY_FENIX_PROJECT_ID: ${{ secrets.SENTRY_FENIX_PROJECT_ID }}
SENTRY_FENIX_BETA_PROJECT_ID: ${{ secrets.SENTRY_FENIX_BETA_PROJECT_ID }}

jobs:
reports:
name: Run reports (${{ matrix.name }})
runs-on: ubuntu-latest

strategy:
fail-fast: false
max-parallel: 6
matrix:
include:
- name: Mobile Testrail Milestones CLOSED
args: --platform mobile --project ALL --report-type testrail-milestones-closed

steps:
- uses: actions/checkout@v5
- uses: actions/setup-python@v5
with:
python-version: "3.11"
cache: "pip"
cache-dependency-path: requirements.txt
- uses: mattes/gce-cloudsql-proxy-action@v1
with:
creds: ${{ secrets.GCLOUD_AUTH }}
instance: ${{ secrets.CLOUD_SQL_CONNECTION_NAME }}
port: ${{ secrets.CLOUD_SQL_DATABASE_PORT }}
- run: pip install -r requirements.txt
- run: python ./__main__.py ${{ matrix.args }}

notify:
name: Slack notify
runs-on: ubuntu-latest
needs: [reports, sentry]
if: always()
steps:
- uses: actions/checkout@v5
- run: echo "JOB_LOG_URL=https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" >> $GITHUB_ENV
- uses: slackapi/[email protected]
env:
WORKFLOW_NAME: ${{ github.workflow }}
BRANCH: ${{ github.head_ref || github.ref_name }}
JOB_STATUS: ${{ (needs.reports.result == 'success' && needs.sentry.result == 'success') && ':white_check_mark:' || ':x:' }}
JOB_STATUS_COLOR: ${{ (needs.reports.result == 'success' && needs.sentry.result == 'success') && '#36a64f' || '#FF0000' }}
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL_MOBILE_ALERTS_TOOLING }}
SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK
with:
webhook: ${{ secrets.SLACK_WEBHOOK_URL_MOBILE_ALERTS_TOOLING }}
webhook-type: webhook-trigger
payload-file-path: "./config/payload-slack-content.json"
payload-templated: true
17 changes: 11 additions & 6 deletions __main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,15 @@
handle_bitrise_builds,
)

"""
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

commenting this out for now only because its throwing an error locally

from handlers.bugzilla import (
handle_bugzilla_desktop_bugs,
handle_bugzilla_desktop_release_flags_for_bugs,
handle_bugzilla_meta_bugs,
handle_bugzilla_qe_verify,
handle_bugzilla_query_by_keyword,
)
"""

from handlers.confluence import (
handle_confluence_build_validation,
Expand All @@ -53,6 +55,7 @@
handle_testrail_test_plans_and_runs,
handle_testrail_test_results,
handle_testrail_milestones,
handle_testrail_milestones_closed,
handle_testrail_users,
handle_testrail_test_case_coverage,
# handle_testrail_test_run_counts_update,
Expand Down Expand Up @@ -111,7 +114,7 @@ def parse_args(cmdln_args):
def validate_project(platform, project, report_type):
# Conditionally require --platform and --project
# if --report-type is 'test-case-coverage'
if report_type in ('test-case-coverage', 'testrail-milestones'):
if report_type in ('test-case-coverage', 'testrail-milestones', 'testrail-milestones-closed'):
if not project:
print("--project is required for the report selected")
if not platform:
Expand Down Expand Up @@ -171,11 +174,11 @@ def expand_project_args(platform, projects):
# === DISPATCH MAP ===
COMMAND_MAP = {
'bitrise-builds': handle_bitrise_builds,
'bugzilla-desktop-bugs': handle_bugzilla_desktop_bugs,
'bugzilla-desktop-release-flags-for-bugs': handle_bugzilla_desktop_release_flags_for_bugs, # noqa
'bugzilla-meta-bugs': handle_bugzilla_meta_bugs,
'bugzilla-qe-verify': handle_bugzilla_qe_verify,
'bugzilla-query-by-keyword': handle_bugzilla_query_by_keyword,
#'bugzilla-desktop-bugs': handle_bugzilla_desktop_bugs,
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as above

#'bugzilla-desktop-release-flags-for-bugs': handle_bugzilla_desktop_release_flags_for_bugs, # noqa
#'bugzilla-meta-bugs': handle_bugzilla_meta_bugs,
#'bugzilla-qe-verify': handle_bugzilla_qe_verify,
#'bugzilla-query-by-keyword': handle_bugzilla_query_by_keyword,
'confluence-updates': handle_confluence_updates,
'confluence-build-validation': handle_confluence_build_validation,
'github-issue-regression': handle_github_issue_regression,
Expand All @@ -185,6 +188,7 @@ def expand_project_args(platform, projects):
'sentry-issues': handle_sentry_issues,
'sentry-rates': handle_sentry_rates,
'testrail-milestones': handle_testrail_milestones,
'testrail-milestones-closed': handle_testrail_milestones_closed,
'testrail-users': handle_testrail_users,
'testrail-test-case-coverage': handle_testrail_test_case_coverage,
# 'testrail-test-run-counts': handle_testrail_test_run_counts_update,
Expand All @@ -203,6 +207,7 @@ def main():
print(f"args.report_type: {args.report_type}")
print(f"args.arg_list: {args.arg_list}")


if report_type not in COMMAND_MAP:
sys.exit(f"Unknown or unsupported report type: {report_type}")

Expand Down
15 changes: 12 additions & 3 deletions api/testrail/report_milestones.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,11 @@ def _tr() -> TestRail():
# ORCHESTRATOR (BATCH)
# ===================================================================

def testrail_milestones(project):
def run(project, milestone_validate_closed: bool = False):
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is only 1 entry point to this module (and all report modules). Standard practice in this case is to use an entry function called: run.

Other new standards here are using: _fetch for fetching external API data
and _upsert for remote update / upload / insert operations

_fetch(project, milestone_validate_closed)


def _fetch(project, milestone_validate_closed):

tr = _tr()

Expand Down Expand Up @@ -141,9 +145,14 @@ def testrail_milestones(project):
pl.extract_build_version
)

import sys
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DIAGNOSTIC only

print(f"milestone_validate_closed: {milestone_validate_closed}")
sys.exit()


# Insert into database only if there is data
if not df_selected.empty:
report_milestones_insert(projects_id, df_selected)
_db_upsert(projects_id, df_selected)
else:
print(
f"No milestones data to insert into database for project "
Expand All @@ -155,7 +164,7 @@ def testrail_milestones(project):
# DB INSERT
# ===================================================================

def report_milestones_insert(projects_id, payload):
def _db_upsert(projects_id, payload):
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

upsert is a stand name for an insert / update / upload operation.


# DIAGNOSTIC
print("--------------------------------------")
Expand Down
1 change: 1 addition & 0 deletions constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
'jira-qa-requests-new-issue-types',
'jira-softvision-worklogs',
'testrail-milestones',
'testrail-milestones-closed',
'testrail-users',
'testrail-test-case-coverage',
'testrail-test-run-counts',
Expand Down
5 changes: 5 additions & 0 deletions handlers/testrail.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ def handle_testrail_milestones(args):
milestones.testrail_milestones(args.arg_list)


def handle_testrail_milestones_closed(args):
milestone_validate_closed = True
Copy link
Collaborator Author

@rpappalax rpappalax Oct 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

doing it this way, we don't have to make the COMMAND_MAP more complex with additional input params. We simply use a different function name and pass in an optional variable which will trigger an alternate path for the report module we already have in place for milestones

milestones.run(args.arg_list, milestone_validate_closed)


def handle_testrail_users(args):
users.testrail_users()

Expand Down
Loading