How to know if there are changes to promote on Heroku pipeline platform? - heroku

My objective is to write a script that promotes a "stage" application in our Heroku pipeline to production, but only if there are any changes to promote.
I can promote without issues by using:
// POST /pipeline-promotions
{
"pipeline": {
"id": "<pipeline-id>"
},
"source": {
"app": {
"id": "<stage-app-id>"
}
},
"targets": [
{
"app": {
"id": "<production-id>"
}
}
]
}
My issues is that if I execute this, without any changes are present, the release actions are still started on the production application.
In other words, how can I determine if any changes are available for promotion - just like heroku does in their GUI?

Thanks to Heroku support, I managed to figure this out.
It can be done by comparing the slug id's when looking at pipelines/<pipeline-id>/latest-releases.
If the slug-ids are the same, there are no changes to promote.

Related

SAP Fiori Launchpad on Cloud Foundry - Role Configuration Issues

We have a range of apps deployed to our Fiori Launchpad (via an mta) file on Cloud Foundry.
I came across this blog that describes setting up role access on an app by app basis.
Configuring Roles – SAP Fiori Launchpad Cloudfoundry | SAP Blogs.
Firstly, I setup approuter/xs-app.json as follows. Note this has as single config_admin scope as opposed to the 2 (approver and user) in the blog. The reason for this is we only need a single configurable role at the moment, so I'm making the assumption we only need a single scope.
Does the below snippet look correct? I've used "srv_api" as the destination from the blog, but not sure If it needs to be something else.
{
"authenticationMethod": "route",
"welcomeFile": "/cp.portal",
"routes": [
{
"source": "^/catalog(.*)$",
"target": "/catalog$1",
"destination": "srv_api",
"authenticationType": "xsuaa",
"scope": {
"GET": ["$XSAPPNAME.config_admin"],
"PATCH": ["$XSAPPNAME.config_admin"],
"POST": ["$XSAPPNAME.config_admin"],
"PUT": ["$XSAPPNAME.config_admin"],
"DELETE": ["$XSAPPNAME.config_admin"],
"default": ["$XSAPPNAME.config_admin"]
}
}
],
"logout": {
"logoutEndpoint": "/do/logout"
}
}
Next up, xs-security.json in the project root.
{
"xsappname": "demo",
"tenant-mode": "dedicated",
"description": "Security profile of called application",
"scopes": [
{
"name": "uaa.user",
"description": "UAA"
},
{
"name": "$XSAPPNAME.config_admin",
"description": "UAA configuration admin"
}
],
"role-templates": [
{
"name": "Token_Exchange",
"description": "UAA",
"scope-references": ["uaa.user"]
},
{
"name": "ADMIN_USER",
"description": "UAA ADMIN_USER",
"scope-references": ["uaa.config_admin"]
}
]
}
... and finally the manifest.json of the app I would like to apply the role to:
"sap.platform.cf": { "oAuthScopes": ["$XSAPPNAME.config_admin"] }
The app exists in a Group containing only that app.
When deployed to SAP Cloud Foundry, the Group and app are hidden. Fine I thought, just needs the role configured on the BTP side?
In BTP, I setup the role collection with my user, and the the two roles, ADMIN_USER and Token_Exchange, which were deployed correctly to BTP in the previous step.
However, the app and it's Catalog are still hidden from view on the Fiori Launchpad. The only apps that do appear are the one's without the "sap.platform.cf" manifest entry.
Am I approaching this the correct way? Have I missed something?
Or do I need to setup two separate scope, as in the guide, and include the relevant scope in each and every app?
*Note - I've tried setting up the user without the Token_Exhange role, with the same result.
The answer is a typo in xs-security.json
Should be: "scope-references": ["$XSAPPNAME.config_admin"]

Use Artifactory JFrog CLI to delete all *-SNAPSHOT builds but always ensure to leave one behind

I have been using Artifactory JFrog cli & AQL lanaguage to cleanup maven SNAPSHOT builds. So far I have been deleting everything by pattern matching *-SNAPSHOT. However I wish to have 1 build (the youngest) remain, as these are required for other builds. Would anyone be able to point me in the right direction, as I cant find anything obvious in Artifactorys docs.
My current query looks like the following
{
"files": [
{
"aql": {
"items.find": {
"repo": "test-repo",
"path": {"$match":"root-folder/*"},
"name": {"$match":"*-SNAPSHOT"},
"type": "folder",
"$or": [
{
"$and": [
{
"created": { "$before":"7d" }
}
]
}
]
}
}
}
]
}
Directory structure looks like the following
test-repo/root-folder/maven-project1/1.7.0-SNAPSHOT/
test-repo/root-folder/maven-project1/1.8.0-SNAPSHOT/
test-repo/root-folder/maven-project2/1.7.0-SNAPSHOT/
test-repo/root-folder/maven-project2/1.8.0-SNAPSHOT/
In this example I would want to keep the latest builds i.e. v1.8.0

Is there a list of events for when Heroku runs scripts?

I find the documentation at - https://devcenter.heroku.com/articles/app-json-schema#scripts - is poor. It doesn't list all of the different events which can be hooked into to run scripts. I want to run a script for when the app is first created and another with each release. The first is objective is already achieved with a script with runs on the "postdeploy" event. I can't see anything though to help with the second. If using a procfile I know I just specify the "release" process type but I'm trying to do this with an app.json file so I believe the procfile is not relevant.
Does anybody know how I can do what I want? Even better the whereabouts of this explained on Heroku.
At the moment I have this for my app.json -
{
"name": "accounts",
"success_url": "/users/signup",
"addons": [
{
"plan": "heroku-postgresql:hobby-dev"
}
],
"env": {
"NEW_USERS_ARE_SUPERUSERS": "0"
},
"formation": {
"web": {
"quantity": 1,
"size": "free",
"command": "gunicorn proj.wsgi"
}
},
"buildpacks": [
{
"url": "heroku/python"
}
],
"scripts": {
"postdeploy": "psql -c \"create extension pg_trgm\" $DATABASE_URL && ./bin/setup.sh"
}
}
Can I just add a "release" key to the "scripts" dictionary? I saw somewhere somebody had "heroky-postbuild" but that didn't seem to work when I tried it.

Why I can't save my connector on Microsoft Teams?

I made a custom connector for teams that display notifications on channels and add Tab on teams.
For the tab parts -> Everything is working well
But I have a problem for the connector parts, I get an error when I try to save my settings in the developer console:
Received error from connectors {"seq":1585127802210,"timestamp":1585127814174,"flightSettings":{"Name":"ConnectorFrontEndSettings","AriaSDKT....
-> registerOnSaveHandler is called
-> setSettings is correctly set with entityId, contentUrl (same configurationUrl as the connector configuration) and the configName.
getSettings -> is called to save to my app the webhook url -> it works
-> notifySuccess is then called and
I checked on the connector dashboard everything seems fine, on the App Studio everything is green also!
I don't know what is happening..
My manifest
{
"$schema": "https://developer.microsoft.com/en-us/json-schemas/teams/v1.5/MicrosoftTeams.schema.json",
"manifestVersion": "1.5",
"version": "1.0.0",
"id": "ca153ede-92f2-46e7-8695-3726b5343bf4",
"packageName": "com.kagilum.icescrum",
"developer": {
"name": "Kagilum SAS",
"websiteUrl": "https://www.icescrum.com",
"privacyUrl": "https://www.icescrum.com/privacy",
"termsOfUseUrl": "https://www.icescrum.com/termsofuser"
},
"icons": {
"color": "color.png",
"outline": "outline.png"
},
"name": {
"short": "iceScrum",
"full": "Connect with iceScrum"
},
"description": {
"short": "A true Agile project management tool",
"full": "iceScrum is a web application for using Scrum while keeping the spirit of a collaborative workspace. It also offers virtual boards with post-its for sprint backlog, product backlog and others."
},
"accentColor": "#FFFFFF",
"configurableTabs": [
{
"configurationUrl": "https://preview.icescrum.com/msTeams/setupTab/",
"canUpdateConfiguration": true,
"scopes": [
"team",
"groupchat"
],
"supportedSharePointHosts": [
"sharePointFullPage",
"sharePointWebPart"
]
}
],
"connectors": [
{
"connectorId": "f00d8890-daa8-4c87-89f5-83cbab0bccd4",
"configurationUrl": "https://preview.icescrum.com/msTeams/setup/",
"scopes": [
"team"
]
}
],
"permissions": [
"identity",
"messageTeamMembers"
],
"validDomains": [
"preview.icescrum.com"
]
}
Piece of code related to
microsoftTeams.settings.registerOnSaveHandler(function(saveEvent) {
microsoftTeams.settings.setSettings({
entityId: 'icescrum-pkey-' + $scope.settings.project.pkey,
contentUrl: isSettings.serverUrl + '/msTeams/setup/',
configName: $scope.settings.project.name
});
microsoftTeams.settings.getSettings(function(settings) {
$scope.settings.webhookUrl = settings.webhookUrl;
return FormService.httpPost('msTeams/save', $scope.settings, true).then(function() {
saveEvent.notifySuccess(); //wait that the settings are really saved on iceScrum side
});
});
});
microsoftTeams.settings.getSettings(function(settings) {
$scope.setup = !settings.configName;
var tokenData = JSON.parse(localStorage.getItem("msTeams-oauth"));
var userData = JSON.parse(localStorage.getItem("msTeams-user"));
if (tokenData) {
FormService.httpGet('ws/project/user/' + userData.id + '?light=true', {headers: {'Authorization': 'Bearer ' + tokenData['accessToken']}}, true).then(function(projects) {
$scope.projects = projects;
if (settings.entityId) {
$scope.settings.project = _.find($scope.projects, {pkey: settings.entityId.split('icescrum-pkey-')[1]});
}
$scope.ready = true;
});
}
});
Full error:
angular.min.js:113 2020-03-25T20:35:25.953Z Received error from connectors {"seq":1585168484680,"timestamp":1585168525943,"flightSettings":{"Name":"ConnectorFrontEndSettings","AriaSDKToken":"d127f72a3abd41c9b9dd94faca947689-d58285e6-3a68-4cab-a458-37b9d9761d35-7033","SPAEnabled":true,"ClassificationFilterEnabled":true,"ClientRoutingEnabled":true,"EnableYammerGroupOption":true,"EnableFadeMessage":false,"EnableDomainBasedOwaConnectorList":false,"EnableDomainBasedTeamsConnectorList":false,"DevPortalSPAEnabled":true,"ShowHomeNavigationButtonOnConfigurationPage":false,"DisableConnectToO365InlineDeleteFeedbackPage":true},"status":500,"clientType":"SkypeSpaces","connectorType":"f00d8890-daa8-4c87-89f5-83cbab0bccd4","name":"handleMessageError"}
In case this helps anyone else, I spent ages today trying to get to the bottom of this and couldn't find a solution. Until...as a last gasp show of desperation I decide to use App Studio to recreate the entire connector manifest from scratch, including creating a new connector in the portal.
For some reason, this then worked fine - even though I can see that the two manifest files are identical with the exception of the ID (and I already tried regenerating the ID for the original one).
Bit late to the story, but having followed multiple github issues like this and stack overflow posts, I'm pretty convinced that its the problem with Connectors dashboard. If you made any change to settings, they are not really propageted/saved correctly.
So for example, if you changed validDomains or configurationPage URL, they won't actually do anything. You can verify that with your devtools. For me, after changing the configurationPage the Teams is still making request to old URL as well as the new one, but the old request produces error that's listed in question.
The only workaround I was able to find is to recreate connector in dashboard. Reported problem to MS Teams dev team, waiting to hear back.
Also late here, but I ran into this problem and the below was the solution after 3 days of frustration.
Despite everything mentioned in the documentation, the following is required otherwise you'll get this error. This fixed things for me.
microsoftTeams.settings.registerOnSaveHandler(saveEvent => {
microsoftTeams.settings.setSettings({
contentUrl: "https://xxxxxx.ngrok.io/teams/connector"
});
saveEvent.notifySuccess();
});
The documentation states that registering a save handler is optional and Teams will handle notify success if it's not declared. WRONG. You must register a save handler.
The documentation does not state that setSettings is required. WRONG. You must set settings or else you will receive this error.
The documentation does not state that you must save a contentURL. WRONG. You must set content URL in the setSettings. You can apparently omit other things when setting your settings, but not content URL.
The documentation does not specifically mention it, but the contentURL must comply with your validURLs in your manifest. If it does not, you'll also see this error.
So in your case, you must ensure that isSettings.serverUrl (setSettings() contentURL) does match preview.icescrum.com (manifest validURLs). If they do not, you'll see this error.

Use GitHub GraphQL to retrieve all open milestones and all issues (open and closed) for the milestone

I understand that GitHub's GraphQL-based v4 API is much more efficient than the v3 API.
I would like to use the GraphQL API to retrieve, for a given repo:
All of the open milestones.
For each milestone, its title, description, all of its issues (open and closed)
For each issue, its title, description, status, and all messages.
Is there a straightforward way to do this?
Yes. It is straightforward to do so . The query looks like :
{
repository(owner: "gatsbyjs", name: "gatsby") {
description
url
milestones(states: [OPEN],first:2) {
nodes{
title
description
url
issues(states:[OPEN,CLOSED], first:2){
nodes{
title
state
url
comments(first:2){
nodes{
url
body
createdAt
}
pageInfo{
hasNextPage
endCursor
}
}
}
pageInfo{
endCursor
hasNextPage
}
}
}
pageInfo{
endCursor
hasNextPage
}
}
}
}
Note:
For the repository which the url is https://github.com/gatsbyjs/gatsby , its owner is gatsbyjs and its name is gatsby
Go to its API Explorer to try and fine tune the query.Click Ctrl+Space will auto-suggest the available fields that can be retrieved.
Do the paginating by yourself to loop through all records by adjusting the starting cursor and the number of records to be returned in first , after.
It gives you the following :
{
"data": {
"repository": {
"description": "Build blazing fast, modern apps and websites with React",
"url": "https://github.com/gatsbyjs/gatsby",
"milestones": {
"nodes": [
{
"title": "Next Major",
"description": "Issues that will require a breaking change, and which would constitute being done in the next major version of Gatsby.",
"url": "https://github.com/gatsbyjs/gatsby/milestone/5",
"issues": {
"nodes": [
{
"title": "Make accessibility warnings errors",
"state": "OPEN",
"url": "https://github.com/gatsbyjs/gatsby/issues/19945",
"comments": {
"nodes": [
{
"url": "https://github.com/gatsbyjs/gatsby/issues/19945#issuecomment-568891716",
"body": "Hiya!\n\nThis issue has gone quiet. Spooky quiet. 👻\n\nWe get a lot of issues, so we currently close issues after 30 days of inactivity. It’s been at least 20 days since the last update here.\nIf we missed this issue or if you want to keep it open, please reply here. You can also add the label \"not stale\" to keep this issue open!\nAs a friendly reminder: the best way to see this issue, or any other, fixed is to open a Pull Request. Check out [gatsby.dev/contribute](https://www.gatsbyjs.org/contributing/how-to-contribute/) for more information about opening PRs, triaging issues, and contributing!\n\nThanks for being a part of the Gatsby community! 💪💜",
"createdAt": "2019-12-25T12:02:26Z"
},
{
"url": "https://github.com/gatsbyjs/gatsby/issues/19945#issuecomment-570779866",
"body": "Hey again!\n\nIt’s been 30 days since anything happened on this issue, so our friendly neighborhood robot (that’s me!) is going to close it.\nPlease keep in mind that I’m only a robot, so if I’ve closed this issue in error, I’m `HUMAN_EMOTION_SORRY`. Please feel free to reopen this issue or create a new one if you need anything else.\nAs a friendly reminder: the best way to see this issue, or any other, fixed is to open a Pull Request. Check out [gatsby.dev/contribute](https://www.gatsbyjs.org/contributing/how-to-contribute/) for more information about opening PRs, triaging issues, and contributing!\n\nThanks again for being part of the Gatsby community! 💪💜",
"createdAt": "2020-01-04T12:02:28Z"
}
],
"pageInfo": {
"hasNextPage": false,
"endCursor": "Y3Vyc29yOnYyOpHOIgVo2g=="
}
}
},
{
"title": "Configurable output folder",
"state": "OPEN",
"url": "https://github.com/gatsbyjs/gatsby/issues/1878",
"comments": {
"nodes": [
{
"url": "https://github.com/gatsbyjs/gatsby/issues/1878#issuecomment-324062470",
"body": "Do you have a specific use case in mind? This has been discussed before but no one has come up with a concrete use case that justified adding a new option.\r\n\r\nEvery option we add to Gatsby makes the project more complex which has all sorts of long-term costs so unless something is really valuable, I'd rather people handle this sort of thing themselves e.g. just copy the files to the output directory you want or create a symlink. This could easily be turned into a plugin that people could install, etc.",
"createdAt": "2017-08-22T15:27:41Z"
},
{
"url": "https://github.com/gatsbyjs/gatsby/issues/1878#issuecomment-324074853",
"body": "Yes, I have a use-case. I am going to use Gatsby for a documentation part as a part of complex project. All static files (Gatsby output, plus some others) should be placed into one folder `build`, that will be deployed somehow later. In other words, the Gatsby output is only one subfolder in my setup.\r\n\r\nSo far I have worked this around in `postbuild` step, but it looks hacky:\r\n\r\n```\r\n\"build\": \"gatsby build\",\r\n\"postbuild\": \"mv public build/gatsby-subsite\"\r\n```\r\nAdding configurable output folder will reduce this complexity and will help me not to move files around one more time.",
"createdAt": "2017-08-22T16:08:21Z"
}
],
"pageInfo": {
"hasNextPage": true,
"endCursor": "Y3Vyc29yOnYyOpHOE1D9ZQ=="
}
}
}
],
"pageInfo": {
"endCursor": "Y3Vyc29yOnYyOpLPgAAAAAAAArvODwULXA==",
"hasNextPage": true
}
}
}
],
"pageInfo": {
"endCursor": "Y3Vyc29yOnYyOpHOAEEbsw==",
"hasNextPage": false
}
}
}
}
}

Resources