Skip to content

Instantly share code, notes, and snippets.

@padupe
Created October 13, 2022 20:55
Show Gist options
  • Save padupe/fb68b39d11fe893b5d5315e4b613a4ee to your computer and use it in GitHub Desktop.
Save padupe/fb68b39d11fe893b5d5315e4b613a4ee to your computer and use it in GitHub Desktop.
[Backstage] Catalog Software Integration
#!/bin/bash
## Running this script will do following for all passed repos:
## - Create a branch `backstage-integration`
## - Add catalog-info.yaml
## - Creates a PullRequest
##
## Inspired at: https://gist.github.com/axdotl/8231abd46793ea23160662c3d81f4ba9
## - User: @axdotl
##
## Requirements:
## - GitHub Personal Access Token with owner privilege;
## - Organization Indication on GitHub;
## - Default branch indicated;
## - Repository must have at least one team with Admin privileges;
## - List of repositories in .txt format;
## - File catalog-info.yaml with variables that will be used.
##
## This script expects following files
## - repos.txt: a file with repository names (one per li (deixar última linha em branco)ne)
## - catalog-info.yaml: A minimal manifest template with content like
##
## #catalog-info.yaml
## apiVersion: backstage.io/v1alpha1
## kind: <KIND>
## metadata:
## name: <NAME>
## annotations:
## github.com/project-slug: <ORG>/<NAME>
## tags:
## - <LANGUAGE>
## spec:
## type: <SPEC_TYPE>
## lifecycle: production
## owner: <TEAM_OWNER>
## <DEFINITION>
GH_TOKEN=ghp_****
ORG=your-org
branchDefault=production
while read -r repo; do
echo ""
if [[ $repo == \#* ]]
then
echo "Ignore $repo"
continue
fi
echo "Repo: $repo"
api="api"
front="front"
iac="iac"
kind=
specType=
# Exclusive for kind: API
definition=
# Validate Kind and spec.type at catalog-info.yaml
if [[ $repo == $iac* ]]
then
kind=Resource
specType=iac
echo 'Kind is "Resource" ✅'
elif [[ $repo == *"$front"* ]]
then
kind=Component
specType=website
echo 'Kind is "Component", spec.type is "website" ✅'
elif [[ $repo == *"$api"* ]]
then
kind=API
specType=openapi
definition='definition: "openapi: 3.0.0"'
echo 'Kind is "API" ✅'
else
kind=Component
specType=service
echo 'Kind is "Component", spec.type is "service" ✅'
fi
# Validate if catalog-info.yaml exists
rc=$(curl -s -o /dev/null -w "%{http_code}" -H "Authorization: token $GH_TOKEN" -H "Accept: application/vnd.github.v3+json" https://api.github.com/repos/$ORG/$repo/contents/catalog-info.yaml)
if [[ $rc == '200' ]]
then
echo "catalog-info.yaml found, no more actions required."
continue
elif [[ $rc == '404' ]]
then
echo "No catalog-info.yaml found"
else
echo "Failed to check for catalog-info.yaml, status $rc"
echo "Will continue with next item..."
continue
fi
# Validate branch default at GitHub
hasMain=$(curl -s -o /dev/null -w "%{http_code}" -H "Authorization: token $GH_TOKEN" -H "Accept: application/vnd.github.v3+json" https://api.github.com/repos/$ORG/$repo/git/refs/heads/$branchDefault)
mainName=$branchDefault
if [[ $hasMain == '200' ]]
then
echo "has main branch"
elif [[ $hasMain == '404' ]]
then
echo "has master branch"
mainName=$branchDefault
else
echo "Failed to check for main"
fi
headsRef=$(curl -s -H "Authorization: token $GH_TOKEN" -H "Accept: application/vnd.github.v3+json" https://api.github.com/repos/$ORG/$repo/git/refs/heads/$mainName)
headsSha=$(echo "$headsRef" | jq '.object.sha' -r)
headsUrl=$(echo "$headsRef" | jq '.object.url' -r)
# Get Admin Team
verifyTeams=$(curl -H "Authorization: token $GH_TOKEN" -H "Accept: application/vnd.github.v3+json" https://api.github.com/repos/$ORG/$repo/teams)
## Get first position at array
getTeamAdmin=$(echo "$verifyTeams" | jq -r '.[0] | select(.permissions.admin==true)')
if ! [[ $getTeamAdmin ]]
then
echo 'Without Admin Team'
printf "${repo}\n" >> repos-without-admin.team.txt
continue
fi
## Format adim team value
echo "Admin Team: $getTeamAdmin"
teamAdmin=$(echo "$getTeamAdmin" | jq -r '.name')
echo "Team Slug: $teamAdmin" #Squad-core-api-admin
slugString=${teamAdmin,,} #squad-core-api-admin
adminInfo="admin"
teamAdminSlug=
if [[ $slugString == *"$adminInfo"* ]]
then
teamAdminSlug="${slugString}"
echo 'Slug already has the suffix "admin" ✅'
else
teamAdminSlug="${slugString}-admin"
echo 'Slug was given the suffix "-admin" ✅'
fi
echo "Team Slug After Validation: $teamAdminSlug"
# Get top language at Repository
language=$(curl -s -H "Authorization: token $GH_TOKEN" -H "Accept: application/vnd.github.v3+json" https://api.github.com/repos/$ORG/$repo/languages | jq 'to_entries|map("\(.key)=\(.value|tostring)")|.[]' -r | awk '{split($0,a,"="); print tolower(a[1])}' | head -1)
echo "Language: $language"
if [[ $language == '' ]]
then
language=poc
echo "Could not find a highlighted language"
fi
# Create Branch "backstage-integration"
createBranch=$(curl -s -o /dev/null -w "%{http_code}" -H "Authorization: token $GH_TOKEN" -H "Accept: application/vnd.github.v3+json" -X POST https://api.github.com/repos/$ORG/$repo/git/refs -d "{\"ref\":\"refs/heads/backstage-integration\", \"sha\":\"$headsSha\"}")
if [[ $createBranch == '201' ]]
then
echo "Branch backstage-integration ✅"
else
echo "Branch backstage-integration ❌"
printf "${repo}\n" >> repos-with-error.txt
continue
fi
# Create "catalog-info.yaml" file
catalogInfo=$(sed "s/<NAME>/$repo/" < catalog-info.yaml | sed "s/<KIND>/$kind/" | sed "s/<ORG>/$ORG/" | sed "s/<SPEC_TYPE>/$specType/" | sed "s/<LANGUAGE>/$language/" | sed "s/<TEAM_OWNER>/$teamAdminSlug/" | sed "s/<DEFINITION>/$definition/" | base64 -w 0)
commitRc=$(curl -s -o /dev/null -w "%{http_code}" -H "Authorization: token $GH_TOKEN" -H "Accept: application/vnd.github.v3+json" -X PUT https://api.github.com/repos/$ORG/$repo/contents/catalog-info.yaml -d "{\"message\":\"Add catalog-info.yaml for Backstage integration.\",\"content\": \"$catalogInfo\",\"branch\": \"refs/heads/backstage-integration\"}")
if [[ $commitRc == '201' ]]
then
echo "catalog-info.yaml added ✅"
else
echo "catalog-info.yaml added ❌"
continue
fi
# Create Pull Request
createPrRc=$(curl -s -o /dev/null -w "%{http_code}" -H "Authorization: token $GH_TOKEN" -H "Accept: application/vnd.github.v3+json" -X POST https://api.github.com/repos/$ORG/$repo/pulls -d "{\"head\":\"backstage-integration\",\"base\":\"$mainName\",\"title\": \"Add catalog-info.yaml for Backstage integration.\",\"body\":\"This pull request adds a **Backstage entity metadata file** to this repository so that the component can be added to the $ORG software catalog.\n\nAfter this pull request is merged, the component will become available.\n\nFeel free to make changes to the file. For more information, read about the [descriptor format of catalog entities](https://backstage.io/docs/features/software-catalog/descriptor-format).\"}")
if [[ $createPrRc == '201' ]]
then
echo "PullRequest ✅"
else
echo "PullRequest ❌"
continue
fi
done <repos.txt
@padupe
Copy link
Author

padupe commented Oct 13, 2022

More than deserved credits to @axdotl, I just tweaked the script to make it even more "nice".

@axdotl
Copy link

axdotl commented Oct 14, 2022

I'm glad that the script was helpful. 🚀

@iamxicao
Copy link

🚀🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment