forked from AdobeDocs/aep-mobile-sdkdocs
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
12 changed files
with
882 additions
and
184 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,194 @@ | ||
/* | ||
Copyright 2023 Adobe. All rights reserved. | ||
This file is licensed to you under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. You may obtain a copy | ||
of the License at http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software distributed under | ||
the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS | ||
OF ANY KIND, either express or implied. See the License for the specific language | ||
governing permissions and limitations under the License. | ||
*/ | ||
|
||
const https = require('https'); | ||
const { fetchReleaseInfoWithTagName } = require('./github-release'); | ||
const { capitalizeFirstLetter } = require('./utils'); | ||
|
||
// Maven Search REST API | ||
// https://central.sonatype.org/search/rest-api-guide/ | ||
|
||
// Fetch the latest Android artifacts from Maven Central | ||
async function fetchMavenArtifactInfo(groupId, capacity, timestampInMilliseconds) { | ||
let options = { | ||
host: 'search.maven.org', | ||
port: 443, | ||
timeout: 5000, | ||
path: `/solrsearch/select?q=g:${groupId}&core=gav&rows=${capacity}&wt=json`, | ||
method: 'GET', | ||
headers: { | ||
'Content-Type': 'application/json', | ||
'User-Agent': 'server-side', | ||
} | ||
}; | ||
|
||
console.log(`request options: ${JSON.stringify(options)}`) | ||
|
||
// TODO: condiser refactoring the code blow with libraries like axios. | ||
return new Promise((resolve) => { | ||
let reqGet = https.request(options, function (res) { | ||
if (res.statusCode != 200) { | ||
throw new Error(`response statusCode: ${res.statusCode}`) | ||
} | ||
console.log(`response statusCode: ${res.statusCode}`) | ||
|
||
let data = []; | ||
res.on('data', function (chunk) { | ||
data.push(chunk); | ||
}).on('end', function () { | ||
let buffer = Buffer.concat(data); | ||
let str = new TextDecoder("utf-8").decode(buffer) | ||
let responseJson = JSON.parse(str) | ||
|
||
let array = [] | ||
responseJson.response.docs.forEach(element => { | ||
if (timestampInMilliseconds < element.timestamp) { | ||
array.push(artifactInfo(element.timestamp, element.a, element.v)) | ||
} | ||
}); | ||
resolve(array) | ||
}); | ||
}); | ||
reqGet.on('error', function (e) { | ||
console.error(e) | ||
throw new Error("Got error response.") | ||
}); | ||
reqGet.on('timeout', function () { | ||
reqGet.destroy() | ||
throw new Error("Request timeout.") | ||
}); | ||
reqGet.end(); | ||
}) | ||
|
||
} | ||
|
||
function artifactInfo(timestamp, artifactId, version) { | ||
return { | ||
"timestamp": timestamp, | ||
"artifactId": artifactId, | ||
"version": version | ||
} | ||
} | ||
|
||
// Fetch the latest Android release info from GitHub | ||
async function fetchAndroidReleaseInfo(token, groupId, timestampInMilliseconds, capacity = 10) { | ||
let array = await fetchMavenArtifactInfo(groupId, capacity, timestampInMilliseconds); | ||
console.log("fetchMavenArtifactInfo():") | ||
console.log(array) | ||
let releaseInfoArray = await Promise.all(array.map(async (item) => { | ||
let artifactId = item.artifactId; | ||
let version = item.version; | ||
let extensionName = artifactIdToExtensionName(artifactId); | ||
if (extensionName == null) { | ||
return null; | ||
} | ||
let info = buildGitHubInfo(artifactId, version); | ||
if (info == null) { | ||
return null; | ||
} | ||
let releaseInfo = await fetchReleaseInfoWithTagName(token, "adobe", info.repoName, info.tagName); | ||
// update release info with extension, version, and platform | ||
releaseInfo.version = version; | ||
releaseInfo.extension = extensionName; | ||
releaseInfo.platform = 'Android'; | ||
return releaseInfo; | ||
})); | ||
return releaseInfoArray | ||
} | ||
|
||
// Convert artifactId to extension name. The extension name is used to generate the release title. | ||
function artifactIdToExtensionName(artifactId) { | ||
switch (artifactId) { | ||
case "sdk-bom": | ||
return "BOM" | ||
case "campaignclassic": | ||
return "Campaign Classic" | ||
case "campaign": | ||
return "Campaign Standard" | ||
case "core": | ||
case "lifecycle": | ||
case "identity": | ||
case "signal": | ||
case "edge": | ||
case "optimize": | ||
case "places": | ||
case "media": | ||
case "target": | ||
case "analytics": | ||
case "assurance": | ||
case "audience": | ||
case "campaign": | ||
return capitalizeFirstLetter(artifactId) | ||
case "userprofile": | ||
return "UserProfile" | ||
case "edgeconsent": | ||
return "EdgeConsent" | ||
case "edgeidentity": | ||
return "EdgeIdentity" | ||
case "edgebridge": | ||
return "EdgeBridge" | ||
case "edgemedia": | ||
return "EdgeMedia" | ||
default: | ||
console.log("artifactId not supported: " + artifactId) | ||
return null | ||
} | ||
} | ||
|
||
function buildGitHubInfo(artifactId, artifactVersion) { | ||
switch (artifactId) { | ||
case "sdk-bom": | ||
return { | ||
repoName: "aepsdk-commons", | ||
tagName: "bom-" + artifactVersion | ||
} | ||
|
||
case "core": | ||
case "lifecycle": | ||
case "identity": | ||
case "signal": | ||
return { | ||
repoName: `aepsdk-${artifactId}-android`, | ||
tagName: `v${artifactVersion}-${artifactId}` | ||
} | ||
|
||
case "edge": | ||
case "optimize": | ||
case "places": | ||
case "media": | ||
case "target": | ||
case "edgeidentity": | ||
case "analytics": | ||
case "assurance": | ||
case "edgebridge": | ||
case "edgeconsent": | ||
case "edgemedia": | ||
case "audience": | ||
case "userprofile": | ||
case "messaging": | ||
case "campaignclassic": | ||
case "campaign": | ||
return { | ||
repoName: `aepsdk-${artifactId}-android`, | ||
tagName: `v${artifactVersion}` | ||
} | ||
|
||
default: | ||
console.log("artifactId not supported: " + artifactId) | ||
return null | ||
} | ||
} | ||
|
||
module.exports = { | ||
fetchMavenArtifactInfo, | ||
fetchAndroidReleaseInfo | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
/* | ||
Copyright 2023 Adobe. All rights reserved. | ||
This file is licensed to you under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. You may obtain a copy | ||
of the License at http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software distributed under | ||
the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS | ||
OF ANY KIND, either express or implied. See the License for the specific language | ||
governing permissions and limitations under the License. | ||
*/ | ||
|
||
const https = require('https'); | ||
|
||
// REST API to retrieve release info | ||
// https://docs.github.com/en/free-pro-team@latest/rest/releases/releases?apiVersion=2022-11-28#list-releases | ||
// Example | ||
// https://api.github.com/repos/adobe/aepsdk-react-native/releases?per_page=5 | ||
// Example | ||
// https://api.github.com/repos/adobe/aepsdk-react-native/releases/tags/@adobe/[email protected] | ||
|
||
// Alternative JS client: https://github.com/octokit/rest.js | ||
// https://octokit.github.io/rest.js/v20#repos-get-release | ||
// octokit.rest.repos.listReleases({ | ||
// owner, | ||
// repo, | ||
// }); | ||
|
||
async function fetchReleaseInfo(token, owner, repo, capacity = 5) { | ||
let options = { | ||
host: 'api.github.com', | ||
port: 443, | ||
timeout: 5000, | ||
path: `/repos/${owner}/${repo}/releases?per_page=${capacity}`, | ||
method: 'GET', | ||
headers: { | ||
'Accept': 'application/vnd.github+json', | ||
'User-Agent': 'server-side', | ||
'X-GitHub-Api-Version': '2022-11-28', | ||
'Authorization': `Bearer ${token}`, | ||
} | ||
}; | ||
|
||
console.log(`request options: ${JSON.stringify(options)}`) | ||
|
||
return new Promise((resolve) => { | ||
let reqGet = https.request(options, function (res) { | ||
if (res.statusCode != 200) { | ||
throw new Error(`response statusCode: ${res.statusCode}`) | ||
} | ||
console.log(`response statusCode: ${res.statusCode}`) | ||
|
||
let data = []; | ||
res.on('data', function (chunk) { | ||
data.push(chunk); | ||
}).on('end', function () { | ||
let buffer = Buffer.concat(data); | ||
let str = new TextDecoder("utf-8").decode(buffer) | ||
let responseJson = JSON.parse(str) | ||
if (Array.isArray(responseJson) == false) { | ||
throw new Error("response JSON is not an array") | ||
} | ||
let array = [] | ||
responseJson.forEach(element => { | ||
array.push(releaseInfo(element.published_at, element.body, repo, element.tag_name)) | ||
}); | ||
resolve(array) | ||
}); | ||
}); | ||
reqGet.on('error', function (e) { | ||
console.error(e); | ||
throw new Error("Got error response.") | ||
}); | ||
reqGet.on('timeout', function () { | ||
reqGet.destroy() | ||
throw new Error("Request timeout.") | ||
}); | ||
reqGet.end(); | ||
}) | ||
} | ||
|
||
async function fetchReleaseInfoWithTagName(token, owner, repo, tag) { | ||
let options = { | ||
host: 'api.github.com', | ||
port: 443, | ||
timeout: 5000, | ||
path: `/repos/${owner}/${repo}/releases/tags/${tag}`, | ||
method: 'GET', | ||
headers: { | ||
'Accept': 'application/vnd.github+json', | ||
'User-Agent': 'server-side', | ||
'X-GitHub-Api-Version': '2022-11-28', | ||
'Authorization': `Bearer ${token}`, | ||
} | ||
}; | ||
|
||
console.log(`request options: ${JSON.stringify(options)}`) | ||
|
||
return new Promise((resolve) => { | ||
let reqGet = https.request(options, function (res) { | ||
if (res.statusCode != 200) { | ||
console.error(`Error: response statusCode: ${res.statusCode}, please check if the tag (${tag}) exists in Github repo.`) | ||
} | ||
console.log(`response statusCode: ${res.statusCode}`) | ||
|
||
let data = []; | ||
res.on('data', function (chunk) { | ||
data.push(chunk); | ||
}).on('end', function () { | ||
let buffer = Buffer.concat(data); | ||
let str = new TextDecoder("utf-8").decode(buffer) | ||
let responseJson = JSON.parse(str) | ||
resolve(releaseInfo(responseJson.published_at, responseJson.body, repo, responseJson.tag_name)) | ||
}); | ||
}); | ||
reqGet.on('error', function (e) { | ||
console.error(e); | ||
throw new Error("Got error response.") | ||
}); | ||
reqGet.on('timeout', function () { | ||
reqGet.destroy() | ||
throw new Error("Request timeout.") | ||
}); | ||
reqGet.end(); | ||
}) | ||
|
||
} | ||
|
||
function releaseInfo(published_at, body, repo_name, tag_name) { | ||
return { | ||
"published_at": published_at, | ||
"body": body, | ||
"repo_name": repo_name, | ||
"tag_name": tag_name | ||
} | ||
} | ||
|
||
module.exports = { | ||
fetchReleaseInfo, | ||
fetchReleaseInfoWithTagName | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
/* | ||
Copyright 2023 Adobe. All rights reserved. | ||
This file is licensed to you under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. You may obtain a copy | ||
of the License at http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software distributed under | ||
the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS | ||
OF ANY KIND, either express or implied. See the License for the specific language | ||
governing permissions and limitations under the License. | ||
*/ | ||
|
||
const timestampObj = require('./timestamp.json') | ||
const releaseNoteMap = require('./releaseNoteMap.json') | ||
const { saveJsonObjToFile } = require('./utils') | ||
const { updateReleaseNotesPage, fetchAllReleaseInfo, sortReleaseInfoByDateASC } = require('./update-release-notes'); | ||
|
||
const token = process.argv[2]; | ||
|
||
if (token == undefined) { | ||
throw new Error("token is undefined") | ||
} | ||
|
||
run() | ||
|
||
async function run() { | ||
const list = await fetchAllReleaseInfo(token, timestampObj.ts) | ||
const sortedList = sortReleaseInfoByDateASC(list) | ||
// 1. Update the main release page | ||
updateReleaseNotesPage("./src/pages/home/release-notes/index.md", sortedList) | ||
const ignoreList = ['AEP React Native', 'Roku', 'AEP Flutter'] | ||
for (const releaseInfo of sortedList) { | ||
// We don't have separate release note pages for AEP React Native, Roku, and AEP Flutter | ||
if (ignoreList.includes(releaseInfo.platform) || releaseInfo.extension == "BOM") { | ||
continue | ||
} | ||
let filePath = releaseNoteMap[releaseInfo.extension] | ||
if (filePath != undefined) { | ||
// 2. Update the extension's release note page | ||
updateReleaseNotesPage(filePath, [releaseInfo]) | ||
} else { | ||
console.error(`Error: no release note page found for ${releaseInfo.extension}`) | ||
} | ||
} | ||
let jsonObj = { | ||
"ts": Date.now() | ||
} | ||
saveJsonObjToFile(jsonObj, `${__dirname}/timestamp.json`) | ||
} |
Oops, something went wrong.