Skip to content

Commit

Permalink
Merge branch 'stage' of github.com:adobecom/milo into MWPW-163603
Browse files Browse the repository at this point in the history
  • Loading branch information
npeltier committed Jan 7, 2025
2 parents 86a938c + 82694a3 commit cc45338
Show file tree
Hide file tree
Showing 135 changed files with 13,100 additions and 2,570 deletions.
62 changes: 41 additions & 21 deletions .github/workflows/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,43 +3,62 @@
const owner = process.env.REPO_OWNER || ''; // example owner: adobecom
const repo = process.env.REPO_NAME || ''; // example repo name: milo
const auth = process.env.GH_TOKEN || ''; // https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens
const CURRENT_YEAR = 2024;
const RCPDates = [
{
start: new Date('2024-05-26T00:00:00-07:00'),
end: new Date('2024-06-01T00:00:00-07:00'),
start: new Date('2024-12-12T11:00:00-08:00'),
end: new Date('2024-12-12T14:00:00-08:00'),
},
{
start: new Date('2024-06-13T11:00:00-07:00'),
end: new Date('2024-06-13T14:00:00-07:00'),
start: new Date('2024-12-15T00:00:00-08:00'),
end: new Date('2025-01-02T00:00:00-08:00'),
},
{
start: new Date('2024-06-30T00:00:00-07:00'),
end: new Date('2024-07-06T00:00:00-07:00'),
start: new Date('2025-02-23T00:00:00-08:00'),
end: new Date('2025-03-01T00:00:00-08:00'),
},
{
start: new Date('2024-08-25T00:00:00-07:00'),
end: new Date('2024-08-31T00:00:00-07:00'),
start: new Date('2025-03-12T11:00:00-07:00'),
end: new Date('2025-03-12T14:00:00-07:00'),
},
{
start: new Date('2024-09-12T11:00:00-07:00'),
end: new Date('2024-09-12T14:00:00-07:00'),
start: new Date('2025-03-17T00:00:00-07:00'),
end: new Date('2025-03-20T17:00:00-07:00'),
},
{
start: new Date('2024-10-07T00:00:00-07:00'),
end: new Date('2024-10-18T17:00:00-07:00'),
start: new Date('2025-05-25T00:00:00-07:00'),
end: new Date('2025-05-31T00:00:00-07:00'),
},
{
start: new Date('2024-11-17T00:00:00-08:00'),
end: new Date('2024-11-30T00:00:00-08:00'),
start: new Date('2025-06-12T11:00:00-07:00'),
end: new Date('2025-06-12T14:00:00-07:00'),
},
{
start: new Date('2024-12-12T11:00:00-08:00'),
end: new Date('2024-12-12T14:00:00-08:00'),
start: new Date('2025-06-29T00:00:00-07:00'),
end: new Date('2025-07-05T00:00:00-07:00'),
},
{
start: new Date('2024-12-15T00:00:00-08:00'),
end: new Date('2025-01-02T00:00:00-08:00'),
start: new Date('2025-08-24T00:00:00-07:00'),
end: new Date('2025-08-30T00:00:00-07:00'),
},
{
start: new Date('2025-09-11T11:00:00-07:00'),
end: new Date('2025-09-11T14:00:00-07:00'),
},
{
start: new Date('2025-10-06T00:00:00-07:00'),
end: new Date('2025-10-16T17:00:00-07:00'),
},
{
start: new Date('2025-11-16T00:00:00-08:00'),
end: new Date('2025-11-29T00:00:00-08:00'),
},
{
start: new Date('2025-12-10T11:00:00-08:00'),
end: new Date('2025-12-10T14:00:00-08:00'),
},
{
start: new Date('2025-12-14T00:00:00-08:00'),
end: new Date('2026-01-04T00:00:00-08:00'),
},
];

Expand All @@ -49,8 +68,9 @@ const isShortRCP = (start, end) => {

const isWithinRCP = ({ offset = 0, excludeShortRCP = false } = {}) => {
const now = new Date();
if (now.getFullYear() !== CURRENT_YEAR) {
console.log(`ADD NEW RCPs for ${CURRENT_YEAR + 1}`);
const lastRcpDate = RCPDates.reverse()[0];
if (now > lastRcpDate.end) {
console.log('ADD NEW RCPs for the current year');
return true;
}

Expand Down
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
Loading

0 comments on commit cc45338

Please sign in to comment.