Module: factory.service/package.core
Type: Abstract base class for external service integrations
ObjServiceIntegration provides a standard interface for syncing external service events to the Axion ticket system, RACI signoffs, and notifications. Each service subclass implements map_to_ticket_event() to translate service-specific payloads into a standard action dict that sync_to_ticket() dispatches.
The map_to_ticket_event() method must return a dict with an action key. Each action requires specific additional fields:
| Action | Required Fields | Description |
|---|---|---|
create |
subject, description, priority, ticket_type | Create a new ticket |
status_change |
ticket_guid, status, changed_by | Change ticket status |
comment |
ticket_guid, comment, commented_by | Add a comment |
assign |
ticket_guid, assigned_to, assigned_by | Assign ticket |
signoff |
ticket_guid, activity, role, email, signoff_status | Record RACI signoff |
link_pr |
ticket_guid, pr_id, repo | Link a pull request |
resolve |
ticket_guid, resolved_by | Resolve ticket |
escalate |
ticket_guid, escalated_by | Escalate ticket |
When ticket_guid is not provided, _resolve_ticket() attempts to find the ticket via:
external_id in def_integration_syncfeat/ticket-{guid} branch naming convention| Bitbucket Event | Event Type | Ticket Action | Fields Mapped |
|---|---|---|---|
| PR created | pr_created |
link_pr |
branch → ticket_guid (parsed), pr_id, repo |
| PR created (no ticket) | pr_created |
create |
PR title → subject, PR description → description, FEATURE type |
| PR reviewer assigned | pr_reviewer_added |
signoff (request) |
reviewer email → RACI Development Consulted |
| PR approved | pr_approved |
signoff |
reviewer → email, Development, C, APPROVED |
| All reviewers approved | pr_all_approved |
signoff |
Development, A, APPROVED (fully signed) |
| PR merged | pr_merged |
resolve |
merge author → resolved_by |
| PR declined | pr_declined |
comment |
decline reason → comment text |
| PR comment added | pr_comment |
comment |
comment body → comment text |
| Pipeline succeeded | pipeline_success |
comment |
build URL → comment |
| Pipeline failed | pipeline_failed |
escalate |
build failure → escalation reason |
| Commit pushed | commit_pushed |
comment |
commit message → comment |
| Asana Event | Event Type | Ticket Action | Fields Mapped |
|---|---|---|---|
| Task created | task_created |
create |
task name → subject, notes → description |
| Task completed | task_completed |
resolve |
assignee → resolved_by |
| Task moved to section | task_moved |
status_change |
section name → status (see Status Map) |
| Task assigned | task_assigned |
assign |
assignee email → assigned_to |
| Story/comment added | story_added |
comment |
story text → comment |
| Task deleted | task_deleted |
status_change |
→ CANCELLED |
| Subtask completed | subtask_completed |
comment |
subtask name → comment |
Asana Section → Ticket Status Map:
| Asana Section | Ticket Status |
|---|---|
| New | NEW |
| Triaged | TRIAGED |
| In Progress | IN_PROGRESS |
| On Hold | ON_HOLD |
| Escalated | ESCALATED |
| Resolved | RESOLVED |
| Done / Closed | CLOSED |
| Slack Event | Event Type | Ticket Action | Fields Mapped |
|---|---|---|---|
| Approval button clicked (approve) | approval_approve |
signoff |
user email → APPROVED signoff |
| Approval button clicked (reject) | approval_reject |
signoff |
user email → REJECTED signoff |
| Message reaction |
reaction_ticket |
create |
message text → subject, channel → description |
| Message reaction |
reaction_approve |
signoff |
reactor email → APPROVED |
| Thread reply | thread_reply |
comment |
reply text → comment |
| DM to bot with "create ticket" | dm_create |
create |
DM text → subject |
| Google Event | Event Type | Ticket Action | Fields Mapped |
|---|---|---|---|
| Gmail received (matching filter) | email_received |
create |
subject → subject, body → description, sender → requested_by |
| Calendar event due | calendar_due |
escalate |
event summary → escalation reason (SLA deadline) |
| Sheet row updated | sheet_updated |
comment |
row data → comment with changes |
| Drive file shared | drive_shared |
comment |
file link → comment |
| Form submission | form_submitted |
create |
form fields → ticket fields |
External service roles map to RACI roles:
| Integration Role | RACI Role | Activity |
|---|---|---|
| PR Author | Responsible (R) | Development |
| PR Reviewer | Consulted (C) | Development |
| PR Approver (all approved) | Accountable (A) | Development |
| Asana Task Assignee | Responsible (R) | mapped by section |
| Asana Project Owner | Accountable (A) | all activities |
| Slack Approval Responder | per button context | per request context |
| Gmail Sender (ticket creator) | Informed (I) | Outcome Monitoring |
PR Created (branch: feat/ticket-{guid})
│
├─ link_pr() → ticket task linked
├─ request_signoffs(Development) → PENDING for each reviewer
│
PR Reviewer Approves
│
├─ record_signoff(C, reviewer@email, APPROVED)
│
All Reviewers Approve
│
├─ record_signoff(A, APPROVED)
├─ is_fully_signed(Development) → True
│
PR Merged
│
├─ ticket.resolve()
├─ Slack notification
└─ Asana task → complete
from ObjServiceBitbucket import ObjServiceApi as BB
bb = BB()
result = bb.sync_to_ticket(
event_type="pr_approved",
event_data={
"pr_id": 403,
"reviewer": {
"display_name": "Michael van Laeren",
"email": "michael@technocore.co.za",
},
"branch": "feat/ticket-abc123",
},
)
# → {"action": "signoff", "ticket_guid": "abc123",
# "provider": "bitbucket"}
Each service reads credentials from config.yaml:
base:
bitbucket:
token: $environment_BB_TOKEN$
username: technocoregit
workspace: technocore_axion
repo: axion
asana:
token: $environment_ASANA_TOKEN$
workspace: ""
default_project: ""
slack:
bottoken: $environment_SLACK_BOT_TOKEN$
channel: "#axion-alerts"
signingsecret: $environment_SLACK_SECRET$
google:
service_account_file: resource.config/google-sa.json
delegated_user: admin@company.com