Last active
September 19, 2023 18:18
-
-
Save klutchell/86e90621695b688bdb4c0ed971d6bc18 to your computer and use it in GitHub Desktop.
balena-os bulk edit gitmodules
This file contains hidden or 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
#!/bin/bash | |
set -euo pipefail | |
GH_TOKEN="$(<"${HOME}/.github_pat")" | |
github_org="balena-os" | |
repo_yaml_match="yocto-based OS image" | |
clone_root_path="src" # Set the root repository clone path here | |
# known_branches=("pyro" "rocko" "sumo" "thud" "warrior" "zeus" "dunfell" "honister" "kirkstone" "master" "main") # Add your list of known branches here | |
pr_branch="kyle/update-gitmodules" # Set the branch name for the PR | |
# Function to check if repo.yml contains the required property | |
check_repo_yml() { | |
local repo_url="$1" | |
local base64_repo_yml_content | |
local repo_yml_content | |
base64_repo_yml_content=$(gh api "$repo_url" --header "Authorization: token $GH_TOKEN" 2>/dev/null | jq -r '.content') | |
repo_yml_content=$(echo "$base64_repo_yml_content" | base64 --decode) | |
if [[ $repo_yml_content == *"$repo_yaml_match"* ]]; then | |
return 0 | |
else | |
return 1 | |
fi | |
} | |
# Function to get the submodule branch containing the commit | |
get_submodule_branch() { | |
local _repo_name="$1" | |
local _submodule_path="$2" | |
submodule_commit=$(git submodule status "$submodule_path" | awk '{print $1}') | |
( | |
cd "$_submodule_path" || exit | |
echo "$_repo_name: $_submodule_path: Fetching submodule..." | |
git fetch --all >/dev/null 2>&1 | |
submodule_branch="" | |
if [ -z "$submodule_branch" ]; then | |
echo "$_repo_name: $_submodule_path: Getting branches containing commit $submodule_commit..." | |
submodule_branch="$(git branch -r --contains "$submodule_commit" | grep -v "origin/HEAD" | grep -v '-' | awk -F'/' '{print $2}' || true)" | |
fi | |
if [ "$(echo "$submodule_branch" | wc -l)" -gt 1 ]; then | |
echo "$_repo_name: $_submodule_path: Multiple matching branches found!" | |
git branch -r --contains "$submodule_commit" | grep -v "origin/HEAD" | grep -v '-' | |
submodule_branch= | |
fi | |
if [ -z "$submodule_branch" ] && [ "$_submodule_path" = "layers/meta-balena" ]; then | |
submodule_branch="master" | |
fi | |
if [ -z "$submodule_branch" ] && [ "$_submodule_path" = "balena-yocto-scripts" ]; then | |
submodule_branch="master" | |
fi | |
if [ -z "$submodule_branch" ] && [ "$_submodule_path" = "contracts" ]; then | |
submodule_branch="master" | |
fi | |
if [ -z "$submodule_branch" ] && [ "$_submodule_path" = "tests/autohat" ]; then | |
submodule_branch="master" | |
fi | |
# for branch in "${known_branches[@]}"; do | |
# if git branch -r --contains "$submodule_commit" | grep -v "origin/HEAD" | grep -v "-" | grep -q "origin/$branch"; then | |
# submodule_branch="$branch" | |
# break | |
# fi | |
# done | |
if [ -z "$submodule_branch" ]; then | |
echo "$_repo_name: $_submodule_path: Unable to determine branch!" | |
# git branch -r --contains "$submodule_commit" | cat | |
return | |
fi | |
echo "$_repo_name: $_submodule_path: Applying branch $submodule_branch..." | |
( | |
cd "${PWD/$_submodule_path//}" || exit | |
git config --file .gitmodules "submodule.$_submodule_path.branch" "$submodule_branch" | |
) | |
) | |
} | |
update_gitmodules() { | |
( | |
local _repo_name="$1" | |
local _repo_workdir="$2" | |
cd "$repo_workdir" || exit | |
# Update .gitmodules with branch information | |
if [ -f ".gitmodules" ]; then | |
while read -r submodule; do | |
submodule_path=$(echo "$submodule" | awk -F'[= ]' '{print $2}') | |
if [ "$(git config --file .gitmodules "submodule.$submodule_path.branch")" != "" ]; then | |
echo "$_repo_name: $submodule_path: Skipping submodule with branch information..." | |
continue | |
fi | |
if ! git submodule update --init --recursive "$submodule_path"; then | |
echo "$_repo_name: Unable to update submodule $submodule_path!" | |
continue | |
fi | |
get_submodule_branch "$_repo_name" "$submodule_path" | |
done < <(git config --file .gitmodules --get-regexp '^submodule\..*\.path$') | |
fi | |
) | |
} | |
# Function to create a PR with the changed files | |
create_pr() { | |
local _repo_name="$1" | |
local _repo_workdir="$2" | |
( | |
cd "$_repo_workdir" || exit | |
git checkout -B "$pr_branch" origin/master | |
git add .gitmodules | |
# bail out here if nothing has changed | |
if [ -z "$(git status --porcelain .gitmodules)" ]; then | |
echo "$_repo_name: No changes to commit!" | |
return | |
fi | |
git commit -s -m "Update .gitmodules with submodule branch information" -m "Changelog-entry: Update .gitmodules with submodule branch information" | |
# bail out here if nothing has changed | |
if [ -z "$(git diff $pr_branch remotes/origin/$pr_branch)" ]; then | |
echo "$_repo_name: No changes to push!" | |
return | |
fi | |
git push -f origin "$pr_branch" | |
gh label create no-review --description "Auto-approve via policy-bot" --color c2e0c6 --force | |
gh pr create --fill --label no-review || gh pr edit "$pr_branch" --add-label no-review | |
) | |
} | |
# Get the list of repositories | |
repos=$(gh api "orgs/$github_org/repos" --paginate --header "Authorization: token $GH_TOKEN") | |
# Create the clone root path directory if it doesn't exist | |
mkdir -p "$clone_root_path" | |
# Iterate through the repositories | |
while IFS= read -r repo_data; do | |
repo="$(echo "$repo_data" | jq -r '.clone_url')" | |
archived="$(echo "$repo_data" | jq -r '.archived')" | |
repo_name=$(basename "$repo" .git) | |
repo_workdir="$clone_root_path/$repo_name" | |
repo_yml_url="repos/$github_org/$repo_name/contents/repo.yml" | |
if [[ "$repo_name" != "balena-"* ]]; then | |
# echo "$repo_name: Skipping non-balena repository..." | |
rm -rf "${repo_workdir:?}/" | |
continue | |
fi | |
if [ "$archived" = "true" ]; then | |
# echo "$repo_name: Skipping archived repository..." | |
rm -rf "${repo_workdir:?}/" | |
continue | |
fi | |
# if ! check_repo_yml "$repo_yml_url"; then | |
# # echo "$repo_name: Skipping non-yocto repository..." | |
# rm -rf "${repo_workdir:?}/" | |
# continue | |
# fi | |
if [ -d "$repo_workdir" ]; then | |
echo "$repo_name: Resetting $repo_workdir..." | |
( | |
cd "$repo_workdir" || exit | |
git fetch --all | |
git reset --hard origin/master | |
git clean -fdx | |
) || continue | |
else | |
echo "$repo_name: Cloning to $repo_workdir..." | |
git clone "$repo" "$repo_workdir" | |
fi | |
if [ ! -f "$repo_workdir/repo.yml" ] || [[ "$(<"$repo_workdir/repo.yml")" != *"$repo_yaml_match"* ]]; then | |
continue | |
fi | |
if [ ! -f "$repo_workdir/.gitmodules" ]; then | |
continue | |
fi | |
update_gitmodules "$repo_name" "$repo_workdir" | |
create_pr "$repo_name" "$repo_workdir" | |
done < <(echo "$repos" | jq -c '.[]') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment