Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ServiceNow CMR integration #3392

Merged
merged 44 commits into from
Jan 3, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
da33e6d
added servicenow CMR template
amauch-adobe Sep 23, 2024
38e9ff9
updated template to remove skms
amauch-adobe Sep 23, 2024
f66875c
started adding servicenow api calls
amauch-adobe Oct 18, 2024
d51f694
added the servicenow cmr calls.
amauch-adobe Nov 8, 2024
a1f21fd
test branch added
amauch-adobe Nov 8, 2024
3c712cc
removed skms.yml where we are using servicenow
amauch-adobe Nov 8, 2024
7fe436a
updated function calls and parameters
amauch-adobe Nov 12, 2024
a8f94f5
test update
amauch-adobe Nov 14, 2024
9309372
Updated calls to output to file and check output
amauch-adobe Nov 22, 2024
62f1d94
testing output
amauch-adobe Nov 22, 2024
b1b3686
fixed github env variable declarations
amauch-adobe Nov 22, 2024
f297fdd
added output to console for response from curl
amauch-adobe Nov 22, 2024
ef3d17f
fixed file existence and size check
amauch-adobe Nov 23, 2024
e995310
small update
amauch-adobe Nov 23, 2024
332c5de
fixed curl statements and timestamps
amauch-adobe Nov 23, 2024
25a32c7
another small update
amauch-adobe Nov 23, 2024
2a3dc42
testing
amauch-adobe Nov 23, 2024
df65f10
testing theory
amauch-adobe Nov 23, 2024
b9eadae
testing arguments
amauch-adobe Nov 23, 2024
6ccfac2
second attempt
amauch-adobe Nov 23, 2024
aec0316
updated branch to remove caching
amauch-adobe Nov 25, 2024
9b78e3c
reverted changes of new branch
amauch-adobe Nov 25, 2024
cffec0e
another small fix
amauch-adobe Nov 25, 2024
7af8e82
testing a thought
amauch-adobe Nov 25, 2024
869aabe
moved release summary to last param
amauch-adobe Nov 25, 2024
1851649
testing out semantics for env variables
amauch-adobe Nov 25, 2024
da0a480
updated shell commands to fix errors
amauch-adobe Nov 25, 2024
2f02923
small github env fixes
amauch-adobe Nov 25, 2024
28c6741
updated curl statement
amauch-adobe Nov 25, 2024
6756dea
updated calls and timespans
amauch-adobe Nov 26, 2024
1e71146
added printouts for debugging
amauch-adobe Nov 27, 2024
8c23f60
small fixes
amauch-adobe Nov 28, 2024
20fbd83
updated calls per guidance from winter solstice
amauch-adobe Dec 2, 2024
260ae83
added new python script and removed shell script
amauch-adobe Dec 15, 2024
8654a29
added sanitization method
amauch-adobe Dec 16, 2024
585755d
updated servicenow integration to use python
amauch-adobe Dec 17, 2024
43440e1
updated variables and added headers
amauch-adobe Dec 17, 2024
f9b121e
fixed cmr_id parsing and cmr closing
amauch-adobe Dec 17, 2024
a1e53e3
added small test change for PR
amauch-adobe Dec 18, 2024
01e6c07
updated execution path
amauch-adobe Dec 18, 2024
a24bccb
fixing environment variable access
amauch-adobe Dec 18, 2024
382edde
fixed branches in yaml
amauch-adobe Dec 18, 2024
760e337
updated approvers, removed executor
amauch-adobe Dec 18, 2024
4c01c2a
changed stage variables, urls to prod
amauch-adobe Dec 18, 2024
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
178 changes: 178 additions & 0 deletions .github/workflows/servicenow.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
import requests
import time
import datetime
import timedelta
import json
import os
import sys

def find_string_in_json(json_data, target_string):
"""
Finds a target string in a JSON object.

Args:
json_data (dict or list): The JSON data to search.
target_string (str): The string to find.

Returns:
bool: True if the string is found, False otherwise.
"""

if isinstance(json_data, dict):
for key, value in json_data.items():
if isinstance(value, str) and target_string in value:
return True
elif isinstance(value, (dict, list)):
if find_string_in_json(value, target_string):
return True
elif isinstance(json_data, list):
for item in json_data:
if isinstance(item, str) and target_string in item:
return True
elif isinstance(item, (dict, list)):
if find_string_in_json(item, target_string):
return True

return False

# Execute Script logic:
# python3 servicenow.py
if __name__ == "__main__":

print("Starting CMR Action...")

print("Setting Planned Maintenance Time Windows for CMR...")
start_time = (datetime.datetime.now() + datetime.timedelta(seconds = 10)).timestamp()
end_time = (datetime.datetime.now() + datetime.timedelta(minutes = 10)).timestamp()

print("Set Release Summary for CMR...")
release_title = os.environ['PR_TITLE']
release_details = os.environ['PR_BODY']
pr_num = os.environ['PR_NUMBER']
pr_created = os.environ['PR_CREATED_AT']
pr_merged = os.environ['PR_MERGED_AT']
release_summary = f"Release_Details: {release_details} \n\nPull Request Number: {pr_num} \nPull Request Created At: {pr_created} \nPull Request Merged At: {pr_merged}"

print("Getting IMS Token")
ims_url = 'https://ims-na1.adobelogin.com/ims/token'
headers = {"Content-Type":"multipart/form-data"}
data = {
'client_id': os.environ['IMSACCESS_CLIENT_ID'],
'client_secret': os.environ['IMSACCESS_CLIENT_SECRET'],
'grant_type': "authorization_code",
'code': os.environ['IMSACCESS_AUTH_CODE']
}
response = requests.post(ims_url, data=data)
jsonParse = json.loads(response.text)

if response.status_code != 200:
print("POST failed with response code: ", response.status_code)
print(response.text)
sys.exit(1)
elif find_string_in_json(jsonParse, "error"):
print("IMS token request failed with response code: ", response.status_code)
print(response.text)
sys.exit(1)
else:
print("IMS token request was successful")
token = jsonParse["access_token"]

print("Create CMR in ServiceNow...")

servicenow_cmr_url = 'https://ipaasapi.adobe-services.com/change_management/changes'
headers = {
"Accept":"application/json",
"Authorization":token,
"Content-Type":"application/json",
"api_key":os.environ['IPAAS_KEY']
}
data = {
"title":release_title,
"description":release_summary,
"instanceIds": [ 537445 ],
"plannedStartDate": start_time,
"plannedEndDate": end_time,
"coordinator": "narcis@adobe.com",
"customerImpact": "No Impact",
"changeReason": [ "New Features", "Bug Fixes", "Enhancement", "Maintenance", "Security" ],
"preProductionTestingType": [ "End-to-End", "Functional", "Integrations", "QA", "Regression", "UAT", "Unit Test" ],
"backoutPlanType": "Roll back",
"approvedBy": [ "casalino@adobe.com", "jmichnow@adobe.com", "mauchley@adobe.com", "bbalakrishna@adobe.com", "tuscany@adobe.com", "brahmbha@adobe.com" ],
"testPlan": "Test plan is documented in the PR link in the Milo repository above. See the PR's merge checks to see Unit and Nala testing.",
"implementationPlan": "The change will be released as part of the continuous deployment of Milo's production branch, i.e., \"main\"",
"backoutPlan": "Revert merge to the Milo production branch by creating a revert commit.", "testResults": "Changes are tested and validated successfully in staging environment. Please see the link of the PR in the description for the test results and/or the \"#nala-test-results\" slack channel."
}
response = requests.post(servicenow_cmr_url, headers=headers, json=data)
jsonParse = json.loads(response.text)

if response.status_code != 200:
print("POST failed with response code: ", response.status_code)
print(response.text)
sys.exit(1)
elif find_string_in_json(jsonParse, "error"):
print("CMR creation failed with response code: ", response.status_code)
print(response.text)
sys.exit(1)
else:
print("CMR creation was successful")
transaction_id = jsonParse["id"]

print("Waiting for Transaction from Queue to ServiceNow then Retrieve CMR ID...")

servicenow_get_cmr_url = f'https://ipaasapi.adobe-services.com/change_management/transactions/{transaction_id}'
headers = {
"Accept":"application/json",
"Authorization":token,
"api_key":os.environ['IPAAS_KEY']
}

# Wait 10 seconds to provide time for the transaction to exit the queue and be saved into ServiceNow as a CMR record.
time.sleep(10)
response = requests.get(servicenow_get_cmr_url, headers=headers)
jsonParse = json.loads(response.text)

if response.status_code != 200:
print("GET failed with response code: ", response.status_code)
print(response.text)
sys.exit(1)
elif find_string_in_json(jsonParse, "error"):
print("CMR ID retrieval failed with response code: ", response.status_code)
print(response.text)
sys.exit(1)
else:
print("CMR ID retrieval was successful")
cmr_id = jsonParse["result"]["changeId"]

print("Setting Actual Maintenance Time Windows for CMR...")
actual_start_time = (datetime.datetime.now() - datetime.timedelta(seconds = 10)).timestamp()
actual_end_time = datetime.datetime.now().timestamp()

print("Closing CMR in ServiceNow...")

headers = {
"Accept":"application/json",
"Authorization":token,
"Content-Type":"application/json",
"api_key":os.environ['IPAAS_KEY']
}
data = {
"id": transaction_id,
"actualStartDate": actual_start_time,
"actualEndDate": actual_end_time,
"state": "Closed",
"closeCode": "Successful",
"notes": "The change request is closed as the change was released successfully"
}
response = requests.post(servicenow_cmr_url, headers=headers, json=data)
jsonParse = json.loads(response.text)

if response.status_code != 200:
print("POST failed with response code: ", response.status_code)
print(response.text)
sys.exit(1)
elif find_string_in_json(jsonParse, "error"):
print("CMR closure failed with response code: ", response.status_code)
print(response.text)
sys.exit(1)
else:
print("CMR closure was successful")
44 changes: 44 additions & 0 deletions .github/workflows/servicenow.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# This workflow will install Python dependencies, run CMR creation in ServiceNow
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python

name: Create CMR in ServiceNow

on:
pull_request:
types:
- closed
branches:
- main

permissions:
contents: read

env:
IMSACCESS_CLIENT_ID: ${{ secrets.IMSACCESS_CLIENT_ID }}
IMSACCESS_CLIENT_SECRET: ${{ secrets.IMSACCESS_CLIENT_SECRET_PROD }}
IMSACCESS_AUTH_CODE: ${{ secrets.IMSACCESS_AUTH_CODE_PROD }}
IPAAS_KEY: ${{ secrets.IPAAS_KEY_PROD }}
PR_TITLE: ${{ github.event.pull_request.title }}
PR_BODY: ${{ github.event.pull_request.body }}
PR_NUMBER: ${{ github.event.pull_request.number }}
PR_CREATED_AT: ${{ github.event.pull_request.created_at }}
PR_MERGED_AT: ${{ github.event.pull_request.merged_at }}

jobs:
build:
# Only run this workflow on pull requests that have merged and not manually closed by user
if: github.event.pull_request.merged == true
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
- name: Set up Python 3.x, latest minor release
uses: actions/setup-python@v5
with:
python-version: "3.x"
- name: Install dependencies
run: |
python -m pip install --upgrade pip requests timedelta
- name: Execute script for creating and closing CMR
run: |
python ./.github/workflows/servicenow.py
130 changes: 0 additions & 130 deletions .github/workflows/skms.yaml

This file was deleted.

Loading