Skip to content

Commit

Permalink
#160 Keep Track of Build Statuses
Browse files Browse the repository at this point in the history
  • Loading branch information
rogerluan committed Dec 3, 2021
2 parents fd11ac7 + 491ba71 commit 5fc83ea
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 8 deletions.
5 changes: 4 additions & 1 deletion README.md
Expand Up @@ -26,7 +26,7 @@

# Intro

App Store Connect Notifier is a node.js app fetches your app info directly from App Store Connect and posts changes in Slack as a bot. Since App Store Connect doesn't provide event webhooks (yet), these scripts use polling with the help of _fastlane_'s [Spaceship](https://github.com/fastlane/fastlane/tree/master/spaceship).
App Store Connect Notifier is a node.js app fetches your app and build info directly from App Store Connect and posts changes in Slack as a bot. Since App Store Connect doesn't provide event webhooks (yet), these scripts use polling with the help of _fastlane_'s [Spaceship](https://github.com/fastlane/fastlane/tree/master/spaceship).

# Preview

Expand Down Expand Up @@ -92,6 +92,9 @@ export BOT_STATUS_SLACK_WEBHOOK_URL="https://hooks.slack.com/services/XXXXXXXX/X

# How often the script should check for updates (in seconds). Required.
export POLL_TIME_IN_SECONDS=120

# The number of builds to keep track often (default 5)
export NUMBER_OF_BUILDS=5
```

### Method 3: Docker
Expand Down
22 changes: 21 additions & 1 deletion src/fetch_app_status.rb
Expand Up @@ -45,6 +45,10 @@ def itc_team_id_array
ENV["ITC_TEAM_IDS"].to_s.split(",")
end

def number_of_builds
(ENV["NUMBER_OF_BUILDS"] || 5).to_i
end

unless uses_app_store_connect_auth_token || uses_app_store_connect_auth_credentials
puts "Couldn't find valid authentication token or credentials."
exit
Expand All @@ -68,6 +72,18 @@ def get_version_info(app)
}
end

def get_build_info(app)
builds = app.get_builds.sort_by(&:uploaded_date).reverse[0, number_of_builds]

builds.map do |build|
{
version: build.version,
uploaded_data: build.uploaded_date,
status: build.processing_state,
}
end
end

def get_app_version_from(bundle_ids)
apps = []
if bundle_ids
Expand All @@ -77,7 +93,11 @@ def get_app_version_from(bundle_ids)
else
apps = Spaceship::ConnectAPI::App.all
end
apps.map { |app| get_version_info(app) }
apps.map do |app|
info = get_version_info(app)
info["builds"] = get_build_info(app)
info
end
end

if uses_app_store_connect_auth_token
Expand Down
27 changes: 26 additions & 1 deletion src/poll-itc.js
Expand Up @@ -36,13 +36,16 @@ function checkAppStatus() {
function _checkAppStatus(currentAppInfo) {
// Use the live version if edit version is unavailable
const appInfoKey = "appInfo-" + currentAppInfo.appId
const buildInfoKey = "builds-appInfo-" + currentAppInfo.appId
const submissionStartkey = "submissionStart" + currentAppInfo.appId
const lastAppInfo = db.get(appInfoKey)
const lastBuildInfo = db.get(buildInfoKey) || {}

if (!lastAppInfo || lastAppInfo.status != currentAppInfo.status || debug) {
if (!lastAppInfo) {
poster.slackMessage("App Store Connect Notifier Bot has just restarted.")
} else {
poster.slack(currentAppInfo, db.get(submissionStartkey))
poster.slackApp(currentAppInfo, db.get(submissionStartkey))
}
// Store submission start time
if (currentAppInfo.status == "WAITING_FOR_REVIEW") {
Expand All @@ -56,6 +59,28 @@ function _checkAppStatus(currentAppInfo) {

// Store latest app info in database
db.set(appInfoKey, currentAppInfo)

const buildChange = lastAppInfo && JSON.stringify(lastAppInfo.builds) != JSON.stringify(currentAppInfo.builds)
if (lastAppInfo && buildChange) {
const builds = currentAppInfo.builds
const newBuildInfo = {}

builds.forEach((buildInfo) => {
const oldBuildInfo = lastBuildInfo[buildInfo.version]
if (!oldBuildInfo) {
poster.slackBuild(currentAppInfo, buildInfo)
newBuildInfo[buildInfo.version] = buildInfo
} else if (oldBuildInfo.status != buildInfo.status) {
poster.slackBuild(currentAppInfo, buildInfo)
newBuildInfo[buildInfo.version] = buildInfo
} else {
console.log("No build change detected.")
}
})

// Store latest build info in database
db.set(buildInfoKey, newBuildInfo)
}
}

if (!pollIntervalSeconds) {
Expand Down
66 changes: 61 additions & 5 deletions src/post-update.js
@@ -1,9 +1,7 @@
const moment = require("moment")
require("./string-utilities.js")

function postToSlack(appInfo, submissionStartDate) {
const message = `The status of your app *${appInfo.name}* has been changed to *${appInfo.status.formatted()}*`
const attachment = slackAttachment(appInfo, submissionStartDate)
function postToSlack(message, attachment) {
const webhook_url = process.env.BOT_SLACK_WEBHOOK_URL
if (webhook_url) {
postUsingWebhook(message, webhook_url, [attachment])
Expand All @@ -13,6 +11,18 @@ function postToSlack(appInfo, submissionStartDate) {
}
}

function postToSlackApp(appInfo, submissionStartDate) {
const message = `The status of your app *${appInfo.name}* has been changed to *${appInfo.status.formatted()}*`
const attachment = slackAttachment(appInfo, submissionStartDate)
postToSlack(message, attachment)
}

function postToSlackBuild(appInfo, buildInfo) {
const message = `The status of build version *${buildInfo.version}* for your app *${appInfo.name}* has been changed to *${buildInfo.status}*`
const attachment = slackAttachmentBuild(message, appInfo, buildInfo)
postToSlack(message, attachment)
}

function postMessageToSlack(message) {
const webhook_url = process.env.BOT_STATUS_SLACK_WEBHOOK_URL
if (webhook_url) {
Expand Down Expand Up @@ -146,13 +156,52 @@ function slackAttachment(appInfo, submissionStartDate) {
return attachment
}

function slackAttachmentBuild(fallback, appInfo, buildInfo) {
const attachment = {
fallback,
"color": colorForStatus(buildInfo.status),
"title": "App Store Connect",
"author_name": appInfo.name,
"author_icon": appInfo.iconUrl,
"title_link": `https://appstoreconnect.apple.com/apps/${appInfo.appId}/appstore`,
"fields": [
{
"title": "Build Version",
"value": buildInfo.version,
"short": true
},
{
"title": "Build Status",
"value": buildInfo.status,
"short": true
},
{
"title": "Version",
"value": appInfo.version,
"short": true
},
{
"title": "App Status",
"value": appInfo.status.formatted(),
"short": true
}
],
"footer": "App Store Connect",
"footer_icon": "https://devimages.apple.com.edgekey.net/app-store/marketing/guidelines/images/app-store-icon.png",
"ts": new Date().getTime() / 1000
}

return attachment
}

function colorForStatus(status) {
const infoColor = "#8e8e8e"
const warningColor = "#f4f124"
const successColor1 = "#1eb6fc"
const successColor2 = "#14ba40"
const failureColor = "#e0143d"
const colorMapping = {
// App
"PREPARE_FOR_SUBMISSION" : infoColor,
"WAITING_FOR_REVIEW" : successColor1,
"IN_REVIEW" : successColor1,
Expand All @@ -167,12 +216,19 @@ function colorForStatus(status) {
"REMOVED_FROM_SALE" : failureColor,
"DEVELOPER_REJECTED" : failureColor,
"DEVELOPER_REMOVED_FROM_SALE" : failureColor,
"INVALID_BINARY" : failureColor
"INVALID_BINARY" : failureColor,

// Build
"PROCESSING" : infoColor,
"FAILED" : failureColor,
"INVALID" : failureColor,
"VALID" : successColor2,
}
return colorMapping[status]
}

module.exports = {
slack: postToSlack,
slackApp: postToSlackApp,
slackBuild: postToSlackBuild,
slackMessage: postMessageToSlack
}

0 comments on commit 5fc83ea

Please sign in to comment.