Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,18 @@ Run `./setup.sh`. It will clone all repos and set up the "upstream" and "downstr

If you want to also have your own forks as "origin", set it up manually in each created directory (e.g. `git remote add origin git@github.com:me/flowlogs-pipeline.git`)

## Non-admin users (PR mode)

If you don't have push access to the downstream `openshift/*` repositories, use the `-p` flag on any command. This pushes to your fork and creates a PR instead of pushing directly to downstream:

```bash
./set-z.sh -p 2.0.1
./sync.sh -p release-2.1
./new-branches.sh -p release-2.0 release-2.1
```

The scripts will automatically detect your GitHub fork (even if it has a different name than the downstream repo) and create PRs against the appropriate downstream branches.

## Create new release branch

After a y-stream release, we generally prepare the next y-stream branch. Run with the appropriate arguments (current / next):
Expand Down Expand Up @@ -42,6 +54,14 @@ WARNING: Merge failed in "operator", branch "release-2.0"; resolve conflicts, me

You need to resolve them manually, finish the pending merge with `git merge --continue`, then push with something like `git push downstream HEAD:release-2.1`.

## Project structure

- `common.sh` — shared definitions (repo arrays, helpers) sourced by all scripts
- `setup.sh` — initial clone and remote setup
- `set-z.sh` — bump z-stream version after a release
- `new-branches.sh` — create new release branches
- `sync.sh` — sync downstream from upstream

### Common conflicts

- GitHub workflows, in `.github/`, have been removed from downstream. If they changed upstream, you get a conflict. Just keep deleting those files.
138 changes: 138 additions & 0 deletions common.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
#!/bin/bash

# Shared definitions and helpers for sync scripts.
# Source this file from the other scripts:
# source "$(dirname "$0")/common.sh"

############################################################
# Repo arrays #
############################################################

repos=(operator ebpf-agent flowlogs-pipeline console-plugin cli)
upstream_repos=("network-observability-operator" "netobserv-ebpf-agent" "flowlogs-pipeline" "netobserv-web-console" "netobserv-cli")
downstream_repos=("network-observability-operator" "network-observability-ebpf-agent" "network-observability-flowlogs-pipeline" "network-observability-console-plugin" "network-observability-cli")
tekton_all_cpnt=("network-observability-operator" "netobserv-ebpf-agent" "flowlogs-pipeline" "network-observability-console-plugin" "network-observability-cli")
cp_variants=(pf4 pf5)

############################################################
# SED detection (macOS compatibility) #
############################################################

if command -v gsed &>/dev/null; then
SED=gsed
else
SED=sed
fi

############################################################
# Helpers #
############################################################

confirm() {
local prompt=${1:-"Continue?"}
if [[ $yes_mode != 1 ]]; then
read -p "${prompt} [yN] " yn
echo
if [[ ! $yn =~ ^[Yy]$ ]]; then
return 1
fi
fi
return 0
}

warnings=()

print_warnings() {
for warning in "${warnings[@]}"; do
echo "WARNING: $warning"
done
}

get_dockerfile_args_path() {
local repo=$1
if [[ "$repo" == "flowlogs-pipeline" ]]; then
echo "./contrib/docker/Dockerfile-args.downstream"
else
echo "./Dockerfile-args.downstream"
fi
}

############################################################
# Push or create PR #
############################################################

push_or_pr() {
local downstream_repo=$1
local target_branch=$2
local commit_title=$3

if [[ $pr_mode == 1 ]]; then
local pr_branch="${commit_title}-${target_branch}"
pr_branch=$(echo "$pr_branch" | tr ' ' '-' | tr '[:upper:]' '[:lower:]')
local gh_user=$(gh api user --jq '.login')
# Add fork remote if not present
if ! git remote | grep -q "^fork$"; then
local fork_name=""
if gh api "repos/${gh_user}/${downstream_repo}" &>/dev/null; then
fork_name="${downstream_repo}"
fi
if [[ -z "$fork_name" ]]; then
local source_repo=$(gh api "repos/openshift/${downstream_repo}" --jq '.source.full_name // empty' 2>/dev/null)
if [[ -n "$source_repo" ]]; then
local source_name=$(basename "$source_repo")
if gh api "repos/${gh_user}/${source_name}" &>/dev/null; then
fork_name="${source_name}"
fi
fi
fi
if [[ -z "$fork_name" ]]; then
echo " No fork found. Forking openshift/${downstream_repo}..."
gh repo fork "openshift/${downstream_repo}" --clone=false
fork_name="${downstream_repo}"
fi
local fork_url="git@github.com:${gh_user}/${fork_name}.git"
echo " Using fork: ${gh_user}/${fork_name}"
git remote add fork "${fork_url}"
fi
echo " Pushing to fork branch ${pr_branch}..."
git push fork HEAD:${pr_branch} -f
echo " Creating PR against openshift/${downstream_repo}:${target_branch}..."
gh pr create --repo "openshift/${downstream_repo}" --base "${target_branch}" --head "${gh_user}:${pr_branch}" --title "${commit_title}" --body "${commit_title}"
else
git push downstream HEAD:${target_branch}
fi
}

############################################################
# Sanity checks #
############################################################

sanity_check_repos() {
local branch=$1
for repo in "${repos[@]}"; do
echo -e "\n\033[1mSanity check on $repo\033[0m"
pushd $repo
git fetch downstream
git ls-remote --exit-code --heads downstream refs/heads/$branch
if [[ "$?" != "0" ]]; then
echo "Branch downstream/$branch not found. Stopping here."
exit 1
fi
git diff HEAD --exit-code
if [[ "$?" != "0" ]]; then
echo "There are uncommited changes in $repo, commit or reset manually before running this script. Stopping here."
exit 1
fi
if [[ "$repo" == "console-plugin" ]]; then
for variant in "${cp_variants[@]}"; do
echo -e "\n\033[1mVariant: $variant\033[0m"
git ls-remote --exit-code --heads downstream refs/heads/$branch-$variant
if [[ "$?" != "0" ]]; then
echo "Branch downstream/$branch-$variant not found. Stopping here."
exit 1
fi
done
fi
popd
done
}
90 changes: 30 additions & 60 deletions new-branches.sh
Original file line number Diff line number Diff line change
@@ -1,33 +1,36 @@
#!/bin/bash

source "$(dirname "$0")/common.sh"

############################################################
# Help #
############################################################
show_help()
{
echo "Create new branches on downstream repositories, and bump version accordingly."
echo
echo "Syntax: new-branches.sh [-h|-y] SOURCE TARGET"
echo "Syntax: new-branches.sh [-h|-y|-p] SOURCE TARGET"
echo "Options:"
echo " -h Print this help."
echo " -y Yes-mode (non-interactive: proceed without asking)."
echo " -p PR-mode (push to fork and create PRs instead of pushing directly to downstream)."
echo
echo "Arguments:"
echo " SOURCE Source downstream branch"
echo " TARGET Target downstream branch"
echo
echo "Example:"
echo " ./new-branches.sh release-1.12 release-1.13"
echo " ./new-branches.sh -p release-1.12 release-1.13 # for non-admin users"
echo
}

# Reset in case getopts has been used previously in the shell.
OPTIND=1
yes_mode=0
repos=(operator ebpf-agent flowlogs-pipeline console-plugin cli)
cp_variants=(pf4 pf5)
pr_mode=0

while getopts "h?y" opt; do
while getopts "h?yp" opt; do
case "$opt" in
h|\?)
show_help
Expand All @@ -36,6 +39,9 @@ while getopts "h?y" opt; do
y)
yes_mode=1
;;
p)
pr_mode=1
;;
esac
done

Expand All @@ -54,102 +60,66 @@ if [ "$#" != "2" ]; then
exit 1
fi

source="$1"
source_branch="$1"
target="$2"

# Sanity checks
for repo in "${repos[@]}"; do
echo -e "\n\033[1mSanity check on $repo\033[0m"
pushd $repo
git fetch downstream
git ls-remote --exit-code --heads downstream refs/heads/$source
if [[ "$?" != "0" ]]; then
echo "Branch downstream/$source not found. Stopping here."
exit 1
fi
git diff HEAD --exit-code
if [[ "$?" != "0" ]]; then
echo "There are uncommited changes in $repo, commit or reset manually before running this script. Stopping here."
exit 1
fi
if [[ "$repo" == "console-plugin" ]]; then
for variant in "${cp_variants[@]}"; do
echo -e "\n\033[1mVariant: $variant\033[0m"
git ls-remote --exit-code --heads downstream refs/heads/$source-$variant
if [[ "$?" != "0" ]]; then
echo "Branch downstream/$source-$variant not found. Stopping here."
exit 1
fi
done
fi
popd
done
sanity_check_repos "$source_branch"

x=`echo ${target} | cut -d - -f2 | cut -d . -f1`
y=`echo ${target} | cut -d - -f2 | cut -d . -f2`

echo ""
echo "Creating branches \"downstream/$target\" as copies of \"downstream/$source\", then bumping to $x.$y.0"
echo "Creating branches \"downstream/$target\" as copies of \"downstream/$source_branch\", then bumping to $x.$y.0"

if [[ $yes_mode != 1 ]]; then
read -p "Continue? [yN] " yn
echo
if [[ ! $yn =~ ^[Yy]$ ]] ; then
exit 1
fi
fi
confirm || exit 1

bump_and_push() {
local repo=$1
local source_branch=$2
local src_branch=$2
local target_branch=$3
local downstream_repo=$4
local tmp_branch="tmp-$target_branch"

git checkout -B $tmp_branch downstream/$source_branch
git checkout -B $tmp_branch downstream/$src_branch
if [[ "$?" != "0" ]]; then
echo "Could not check out, please make sure all repos are in a clean state without uncommited changes. Stopping here."
exit 1
fi
git reset --hard downstream/$source_branch
git reset --hard downstream/$src_branch

local dockerfile_args_path="./Dockerfile-args.downstream"
if [[ "$repo" == "flowlogs-pipeline" ]]; then
dockerfile_args_path="./contrib/docker/Dockerfile-args.downstream"
fi
local dockerfile_args_path
dockerfile_args_path=$(get_dockerfile_args_path "$repo")

echo " Updating ${dockerfile_args_path}..."
sed -i -r "s/^BUILDVERSION=.+/BUILDVERSION=${x}.${y}.0/" ${dockerfile_args_path}
sed -i -r "s/^BUILDVERSION_Y=.+/BUILDVERSION_Y=${x}.${y}/" ${dockerfile_args_path}
$SED -i -r "s/^BUILDVERSION=.+/BUILDVERSION=${x}.${y}.0/" ${dockerfile_args_path}
$SED -i -r "s/^BUILDVERSION_Y=.+/BUILDVERSION_Y=${x}.${y}/" ${dockerfile_args_path}

echo " Setting branch '${target_branch}' in ./tekton..."
find .tekton -type f -exec sed -i -e "s/${source_branch}/${target_branch}/g" {} \;
find .tekton -type f -exec $SED -i -e "s/${src_branch}/${target_branch}/g" {} \;

echo " Displaying diff..."
git add -A
git diff HEAD

if [[ $yes_mode != 1 ]]; then
read -p "Looks good to you, and proceed to commit and push ${target_branch}? (you can bring manual changes before answering) [yN] " yn
echo
if [[ ! $yn =~ ^[Yy]$ ]] ; then
exit 1
fi
fi
confirm "Looks good to you, and proceed to commit and push ${target_branch}? (you can bring manual changes before answering)" || exit 1

echo " Commiting and pushing to ${target_branch}..."
git commit --allow-empty -m "Prepare ${target_branch}"
git push downstream HEAD:${target_branch}
push_or_pr "${downstream_repo}" "${target_branch}" "Prepare ${target_branch}"
}

i_cpnt=0
for repo in "${repos[@]}"; do
echo -e "\n\033[1mProcessing $repo\033[0m"
pushd $repo
bump_and_push $repo $source $target
ds_repo=${downstream_repos[$i_cpnt]}
bump_and_push $repo $source_branch $target $ds_repo
if [[ "$repo" == "console-plugin" ]]; then
for variant in "${cp_variants[@]}"; do
echo -e "\n\033[1mVariant: $variant\033[0m"
bump_and_push $repo $source-$variant $target-$variant
bump_and_push $repo $source_branch-$variant $target-$variant $ds_repo
done
fi
popd
i_cpnt="$((i_cpnt+1))"
done
Loading