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

MWPW-164253 #130

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
Open
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
19 changes: 19 additions & 0 deletions .github/workflows/ost-products.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
name: Trigger OST Products action

on:
schedule:
- cron: '0 8 * * *' # Daily at 8am UTC (9am CET), triggered on default branch = main
pull_request: # tmp, remove
branches:
- main
types: [opened, synchronize, reopened]
workflow_dispatch: # trigger

jobs:
update-products:
runs-on: ubuntu-latest
steps:
- name: Refresh cache
run: curl $OST_PRODUCTS_URL
env:
OST_PRODUCTS_URL: ${{ vars.OST_PRODUCTS_URL }}
1 change: 1 addition & 0 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ const config = {
'/libs/',
'**/libs/**',
'**/dist/**',
'studio/ost/index.js',
],
...eslintPluginPrettierRecommended,
};
Expand Down
11 changes: 7 additions & 4 deletions io-actions/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,29 @@
- install aio cli
- Request access to I/O Runtime in Adobe Corp org
- navigate to Developer Console https://developer.adobe.com/console
- in Mas HealthCheck project, create a workspace with your ldap
- in 'Merch at Scale' project, create a workspace with your ldap
- in your workspace click on 'Download all' and copy the auth .json in root of this project
- run `aio app use filename`
- this should populate the `.env` and the `.aio` file in the project root
- add ODIN_CDN_ENDPOINT,ODIN_ORIGIN_ENDPOINT,WCS_CDN_ENDPOINT,WCS_ORIGIN_ENDPOINT env vars to .env file
- ask a colleague for values:
- for health-check action,
add ODIN_CDN_ENDPOINT,ODIN_ORIGIN_ENDPOINT,WCS_CDN_ENDPOINT,WCS_ORIGIN_ENDPOINT env vars to .env file
- for ost-products, add AOS_URL and AOS_API_KEY env vars to .env file
- run `npm i`
- run `aio where` and verify output is:
```
aio where
You are currently in:
1. Org: Adobe Corp
2. Project: Mas HealthCheck
2. Project: MerchAtScale
3. Workspace: your ldap
```

## Local Dev

- `aio app dev` to start your local Dev server
- App will run on `localhost:9080` by default
- open https://localhost:9080/api/v1/web/MasHealthCheck/health-check
- open https://localhost:9080/api/v1/web/MerchAtScale/health-check


## Test & Coverage
Expand Down
12 changes: 11 additions & 1 deletion io-actions/app.config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ application:
web: web-src
runtimeManifest:
packages:
MasHealthCheck:
MerchAtScale:
license: Apache-2.0
actions:
health-check:
Expand All @@ -18,3 +18,13 @@ application:
annotations:
require-adobe-auth: false
final: true
ost-products:
function: src/ost-products/index.js
web: 'yes'
runtime: nodejs:18
inputs:
AOS_URL: $AOS_URL
AOS_API_KEY: $AOS_API_KEY
annotations:
require-adobe-auth: false
final: true
4 changes: 2 additions & 2 deletions io-actions/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion io-actions/package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "MasHealthCheck",
"name": "MerchAtScale",
"version": "0.0.1",
"private": true,
"dependencies": {
Expand Down
54 changes: 4 additions & 50 deletions io-actions/src/health-check/README.md
Original file line number Diff line number Diff line change
@@ -1,53 +1,7 @@
# MasHealthCheck
# health-check

## Setup / First Steps

- install aio cli
- Request access to I/O Runtime in Adobe Corp org
- navigate to Developer Console https://developer.adobe.com/console
- in Mas HealthCheck project, create a workspace with your ldap
- in your workspace click on 'Download all' and copy the auth .json in root of this project
- run `aio app use filename`
- this should populate the `.env` and the `.aio` file in the project root
- run `aio where` and verify output is:
```
aio where
You are currently in:
1. Org: Adobe Corp
2. Project: Mas HealthCheck
3. Workspace: your ldap
```

## Local Dev

- `aio app dev` to start your local Dev server
- App will run on `localhost:9080` by default
- open https://localhost:9080/api/v1/web/MasHealthCheck/health-check


## Test & Coverage

- Run `aio app test` to run unit tests for ui and actions

## Deploy & Cleanup
Checks ODIN and WCS endpoints, cached and origin ones.

- `aio app test && aio app deploy` to test, build and deploy all actions on Runtime and static files to CDN
- `aio app undeploy` to undeploy the app

## Config

### `.env`

You can generate this file using the command `aio app use`.

```bash
# This file must **not** be committed to source control

## please provide your Adobe I/O Runtime credentials
# AIO_RUNTIME_AUTH=
# AIO_RUNTIME_NAMESPACE=
```

### `app.config.yaml`
## Setup / First Steps

Main configuration file that defines an application's implementation.
Follow README in 'io-actions' folder
10 changes: 10 additions & 0 deletions io-actions/src/ost-products/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# ost-products

This script generate will:
* query AOS API
* generate a light-weight list of products
This list is used in the initial Product List screen of OST.

## Setup / First Steps

Follow README in 'io-actions' folder
153 changes: 153 additions & 0 deletions io-actions/src/ost-products/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
const KEY_PA = 'product_arrangement_code';
const ABM = 'ABM';
const PUF = 'PUF';
const M2M = 'M2M';
const PERPETUAL = 'PERPETUAL';
const P3Y = 'P3Y';
const COMMITMENT_YEAR = 'YEAR';
const COMMITMENT_MONTH = 'MONTH';
const COMMITMENT_TERM_LICENSE = 'TERM_LICENSE';
const TERM_ANNUAL = 'ANNUAL';
const TERM_MONTHLY = 'MONTHLY';
const getPlanType = ({ commitment, term }) => {
switch (commitment) {
case undefined:
return errorValueNotOffer;
case '':
return '';
case COMMITMENT_YEAR:
return term === TERM_MONTHLY
? ABM
: term === TERM_ANNUAL
? PUF
: '';
case COMMITMENT_MONTH:
return term === TERM_MONTHLY ? M2M : '';
case PERPETUAL:
return PERPETUAL;
case COMMITMENT_TERM_LICENSE:
return term === P3Y ? P3Y : '';
default:
return '';
}
};

const paginatedOffers = (allProducts, landscape, locale, params, page = 0) => {
const { AOS_URL, AOS_API_KEY } = params;
const [, country] = locale.split('_');
const offersEndpoint = `${AOS_URL}?country=${country}&merchant=ADOBE&service_providers=MERCHANDISING&locale=${locale}&api_key=${AOS_API_KEY}&landscape=${landscape}&page_size=100&page=${page}`;
return fetch(offersEndpoint)
.then((response) => response.json())
.then((offers) => {
console.log(`received ${landscape} - ${page}}`);
if (offers && offers.length > 0) {
const products = allProducts[landscape];
for (const offer of offers) {
if (offer.term || offer.commitment === 'PERPETUAL') {
const pa = offer[KEY_PA];
let p = products[pa];
if (!p) {
p = products[pa] = {
name: offer.merchandising?.copy?.name,
arrangement_code: pa,
icon: offer.merchandising?.assets?.icons?.svg,
planTypes: {},
customerSegments: {},
marketSegments: {},
};
}
p.planTypes[getPlanType(offer)] = true;
p.customerSegments[offer.customer_segment] = true;
offer.market_segments.forEach(
(s) => (p.marketSegments[s] = true),
);
}
}
return paginatedOffers(
allProducts,
landscape,
locale,
params,
++page,
);
} else {
console.log(
`collected ${
Object.entries(allProducts[landscape]).length
} products for ${landscape}`,
);
}
});
};

async function main(params) {
try {
const options = [
{ locale: 'en_US', landscape: 'DRAFT' },
{ locale: 'en_US', landscape: 'PUBLISHED' },
{ locale: 'en_CA', landscape: 'DRAFT' },
{ locale: 'en_CA', landscape: 'PUBLISHED' },
];
const allProducts = { DRAFT: {}, PUBLISHED: {} };
const promises = options.map((option) => {
console.log(
`fetching ${option.landscape} products for locale: ${option.locale}`,
);
return paginatedOffers(
allProducts,
option.landscape,
option.locale,
params,
);
});
await Promise.all(promises);
console.log('awaited');
console.log('fetched all AOS responses, assembling...');
const combinedProducts = allProducts.PUBLISHED;
Object.keys(allProducts.DRAFT).forEach((pa) => {
const draftOffer = allProducts.DRAFT[pa];
if (!combinedProducts[pa]) {
console.log(`found ${pa} to be draft`);
combinedProducts[pa] = {
...draftOffer,
draft: true,
};
} // merge planTypes, customerSegments and marketSegments for published and draft offers
else if (
JSON.stringify(combinedProducts[pa]) !==
JSON.stringify(draftOffer)
) {
console.log(
`found ${pa} to be draft, but there is already a published offer with the same PA.`,
);
combinedProducts[pa].planTypes = {
...combinedProducts[pa].planTypes,
...draftOffer.planTypes,
};
combinedProducts[pa].customerSegments = {
...combinedProducts[pa].customerSegments,
...draftOffer.customerSegments,
};
combinedProducts[pa].marketSegments = {
...combinedProducts[pa].marketSegments,
...draftOffer.marketSegments,
};
}
});
return {
headers: {
'Content-Type': 'application/json',
'Cache-Control': 'max-age=86400', // cached in Adobe IO gateway 24 hours
},
statusCode: 200,
body: JSON.stringify(combinedProducts),
};
} catch (error) {
return {
statusCode: 500,
body: `ERROR in I/O action: ${error.toString()}.`,
};
}
}

exports.main = main;
Loading
Loading