Skip to content

rebase CI #18

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
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
25 changes: 25 additions & 0 deletions .github/actions/download/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
name: 'Download artifact'
description: 'Donwload artifacts with normalized names'
inputs:
name:
required: true
type: string
path:
required: true
type: string

runs:
using: "composite"
steps:
- name: Normalise name
run: |
name=${{ inputs.name }}
echo "NAME=${name//\//_}" >> "$GITHUB_ENV"
shell: bash

- name: Download artifact
uses: actions/download-artifact@v4
with:
name: ${{ env.NAME }}
path: ${{ inputs.path }}

33 changes: 33 additions & 0 deletions .github/actions/upload/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: 'Upload artifact'
description: 'Upload artifacts with normalized names'
inputs:
if-no-files-found:
default: 'error'
type: string
name:
required: true
type: string
path:
required: true
type: string
retention-days:
default: 0
type: number

runs:
using: "composite"
steps:
- name: Normalise name
run: |
name=${{ inputs.name }}
echo "NAME=${name//\//_}" >> "$GITHUB_ENV"
shell: bash

- name: Upload artifact
uses: actions/upload-artifact@v4
with:
if-no-files-found: ${{ inputs.if-no-files-found }}
retention-days: ${{ inputs.retention-days }}
name: ${{ env.NAME }}
path: ${{ inputs.path }}

63 changes: 63 additions & 0 deletions .github/scripts/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#!/bin/bash

set -eux

uname -a
uname -p
uname
pwd
env

if [ "${RUNNER_OS}" = Windows ] ; then
ext=".exe"
else
ext=""
fi

ghcup --no-verbose install ghc --set --install-targets "${GHC_TARGETS}" "${GHC_VERSION}"

sed -i.bak -e '/DELETE MARKER FOR CI/,/END DELETE/d' cabal.project # see comment in cabal.project
cabal update
cabal user-config diff
cabal user-config init -f
"ghc-${GHC_VERSION}" --info
"ghc" --info

# https://github.com/haskell/cabal/issues/7313#issuecomment-811851884
if [ "$(getconf LONG_BIT)" == "32" ] || [ "${DISTRO}" == "CentOS" ] ; then
echo 'constraints: lukko -ofd-locking' >> cabal.release.project.local
fi

# shellcheck disable=SC2206
args=(
-w "ghc-$GHC_VERSION"
--disable-profiling
--enable-executable-stripping
--project-file=cabal.release.project
${ADD_CABAL_ARGS}
)

cabal v2-build "${args[@]}" cabal-install

mkdir -p "out"
# shellcheck disable=SC2154
cp "$(cabal list-bin "${args[@]}" cabal-install:exe:cabal)" "out/cabal$ext"
cp dist-newstyle/cache/plan.json "out/plan.json"
cd "out/"

# create tarball/zip
TARBALL_PREFIX="cabal-install-$("./cabal" --numeric-version)"
case "${TARBALL_EXT}" in
zip)
zip "${TARBALL_PREFIX}-${ARTIFACT}.${TARBALL_EXT}" "cabal${ext}" plan.json
;;
tar.xz)
tar caf "${TARBALL_PREFIX}-${ARTIFACT}.${TARBALL_EXT}" "cabal${ext}" plan.json
;;
*)
fail "Unknown TARBALL_EXT: ${TARBALL_EXT}"
;;
esac

rm "cabal${ext}" plan.json

46 changes: 46 additions & 0 deletions .github/scripts/rebase_local.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#!/bin/bash

set -eux

upstream_repo=$1
# of the form [<branch>:<rebase-target>], e.g.:
# BA:master B1:master B2:B1 B3:B2
spec=$2

{

git remote add upstream "${upstream_repo}" || true
git fetch upstream

output_branches=()

# sync master with upstream
git checkout master
git reset --hard upstream/master
output_branches+=( "master" )

# rebase each branch
mkdir -p rebase
for branch_spec in ${spec} ; do
branch=$(echo "${branch_spec}" | awk -F ':' '{ print $1 }')
(
rebase_target=$(echo "${branch_spec}" | awk -F ':' '{ print $2 }')
git checkout "${branch}"
common_ancestor=$(git merge-base "${branch}" "origin/${rebase_target}")
[ -e rebase/"${branch}" ] && exit 1
mkdir -p rebase/"${branch}"
cd rebase/"${branch}"
echo "${common_ancestor}" > BASE_COMMIT
git format-patch "${common_ancestor}".."${branch}"
if compgen -G "*.patch" > /dev/null; then
git reset --hard "${rebase_target}"
git am --3way *.patch
fi
)
output_branches+=( "${branch}" )
done

} >&2

echo "${output_branches[*]}"

142 changes: 142 additions & 0 deletions .github/scripts/rebase_spec.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
#!/bin/bash

# Branch regex we consider for rebase targets.
# For our purposes this is usually 'stable-haskell/feature/*'.
# 'master' is always considered.
branch_regex=$1
shift 1
declare -a input_branches
input_branches=( "$@" )
set -eux

[ ${#input_branches[@]} -eq 0 ] &&
input_branches=( $(gh pr list --label rebase --state open --json headRefName --jq ".[] | select( .headRefName | match(\"${branch_regex}\")) | .headRefName" --template '{{range .}}{{tablerow .headRefName}}{{end}}') )

branch_list=( )
declare -A branch_map

# @FUNCTION: die
# @USAGE: [msg]
# @DESCRIPTION:
# Exits the shell script with status code 2
# and prints the given message in red to STDERR, if any.
die() {
(>&2 red_message "$1")
exit 2
}

# @FUNCTION: red_message
# @USAGE: <msg>
# @DESCRIPTION:
# Print a red message.
red_message() {
printf "\\033[0;31m%s\\033[0m\\n" "$1"
}

# @FUNCTION: array_contains
# @USAGE: <arr_ref> <val>
# @DESCRIPTION:
# Checks whether the array reference contains the given value.
# @RETURN: 0 if value exists, 1 otherwise
array_contains() {
local -n arr=$1
local val=$2
shift 2
if [[ " ${arr[*]} " =~ [[:space:]]${val}[[:space:]] ]]; then
return 0
else
return 1
fi
}

max_backtrack=10

# @FUNCTION: backtrack
# @USAGE: <map_ref> <start_key> <abort_value>
# @DESCRIPTION:
# Backtrack dependencies through an array list.
# E.g. given an associated array with key value pairs of:
# B1 -> M
# B2 -> B1
# B3 -> B2
#
# ...if we pass B3 as start_key and M as abort_value, then
# we receive the flattened ordered list "B1 B2 B3"
# @STDOUT: space separated list of backtracked values
backtrack() {
backtrack_ 0 "$1" "$2" "$3"
}

# internal to track backtrack depth
backtrack_() {
local depth=$1
if [[ $depth -gt $max_backtrack ]] ; then
die "Dependency backtracking too deep... aborting!"
fi
shift 1

if [[ $1 != map ]] ; then
local -n map=$1
fi

local base=$2
local abort_value=$3
local value

if [ "${base}" = "${abort_value}" ] ; then
return
fi

value=${map[$base]}

if [ "${value}" = "${abort_value}" ] ; then
if ! array_contains branch_list "${base}" ; then
echo "${base}"
fi
else
if array_contains branch_list "${base}" ; then
backtrack_ $((depth++)) map "${map[$value]}" "${abort_value}"
else
echo "$(backtrack_ $((depth++)) map "${map[$base]}" "${abort_value}")" "${base}"
fi
fi
}

{

# create branch rebase tree
# we're doing that on the state of the local tree/master
while IFS= read -r branch || [[ -n $branch ]]; do
rebase_target=$(git branch --merged "${branch}" --sort="ahead-behind:${branch}" --format="%(refname:short)" | grep -e "${branch_regex}" -e '^master$' | awk 'NR==2{print;exit}')

# this is the case when the branch is actually behind master... we then
# still want to rebase against master
if [ -z "${rebase_target}" ] ; then
rebase_target=master
fi

branch_map["${branch}"]="${rebase_target}"
done < <(printf '%s\n' "${input_branches[@]}")

} >&2

# flatten recursively
for key in "${!branch_map[@]}"; do
value=${branch_map[$key]}
if [ "${value}" = "master" ] ; then
if ! array_contains branch_list "${key}" ; then
branch_list+=( "${key}" )
fi
else
# shellcheck disable=SC2207
branch_list+=( $(backtrack branch_map "$key" "master") )
fi
done
unset key

result=( )
for key in "${branch_list[@]}"; do
result+=( "${key}:${branch_map[$key]}" )
done
echo "${result[@]}"

35 changes: 35 additions & 0 deletions .github/scripts/test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#!/bin/bash

set -eux

env
pwd
ls -lah

cd out
case "${TARBALL_EXT}" in
zip)
unzip ./cabal-install-*-"${ARTIFACT}.${TARBALL_EXT}"
;;
tar.xz)
tar xf ./cabal-install-*-"${ARTIFACT}.${TARBALL_EXT}"
;;
*)
fail "Unknown TARBALL_EXT: ${TARBALL_EXT}"
;;
esac
cd ..

ghcup --no-verbose install ghc --set --install-targets "${GHC_TARGETS}" "${GHC_VERSION}"

cabal update

# TODO: we want to avoid building here... we should just
# be using the previously built 'cabal-tests' binary
cabal run ${ADD_CABAL_ARGS} cabal-testsuite:cabal-tests -- \
--with-cabal "$(pwd)/out/cabal" \
--intree-cabal-lib "$(pwd)" \
--test-tmp "$(pwd)/testdb" \
--skip-setup-tests \
-j "$(nproc)"

Loading
Loading