177 lines
5.6 KiB
Bash
Executable File
177 lines
5.6 KiB
Bash
Executable File
#!/bin/bash
|
|
# Migrate assignments for Gitea-Issues after a Gitea2Gitea-Migration
|
|
# 2024 Benjamin Winter, MILA
|
|
#
|
|
# errors
|
|
# 1 parameter error
|
|
# 2 repository-check error
|
|
# 5 internal error
|
|
# 42 command cannot be found
|
|
set -eu
|
|
|
|
readonly PROGNAME=`/usr/bin/basename $0`
|
|
readonly PROGPATH=`echo $0 | sed -e 's,[\\/][^\\/][^\\/]*$,,'`
|
|
readonly REVISION="1.0.0"
|
|
|
|
repo=""
|
|
login_old=""
|
|
login_new=""
|
|
dry_run=true
|
|
|
|
#
|
|
# FUNCTIONS
|
|
#
|
|
print_help()
|
|
{
|
|
echo "--- $PROGNAME $REVISION"
|
|
cat << "EOF"
|
|
PURPOSE
|
|
- Migrate assignments for Gitea-Issues after a Gitea2Gitea-Migration
|
|
- issues must have the same ID on both systems
|
|
- users must have the same NAME on both systems
|
|
- users must have the right to be assigned on both systems
|
|
- example
|
|
- OLD: https://oldgitea.example.com/my_organisation/my_repository
|
|
- NEW: https://newgitea.example.com/my_organisation/my_repository
|
|
- Typical Workflow
|
|
1. migrate your repository from your OLD Gitea instance to your NEW one
|
|
2. use this script to migrate the assignments
|
|
|
|
INFORMATION
|
|
- this script will start in DRY MODE by default - see --GO parameter
|
|
- this script will check the environment and stops on any error
|
|
- this script will check the OLD and NEW repository for inconsistencies
|
|
- issue-ids are checked; titles are not checked
|
|
- assignments in new repo are checked
|
|
- if your titles include a ¬ character, the script may could behave funny as this is used as separator
|
|
- Troubleshooting
|
|
- "Error: could not edit issue:"
|
|
- please check, if the assigned person(s) have the right to be assigned (are they in the Organisation? Collaborators?)
|
|
|
|
INSTALLATION AND PREPARATION
|
|
- install
|
|
- jq - Command-line JSON processor - https://github.com/stedolan/jq
|
|
- tea - Command line tool to interact with Gitea - https://gitea.com/gitea/tea
|
|
- create Gitea tokens for tea
|
|
- permissions on the OLD system:
|
|
- user: read
|
|
- issue: read
|
|
- permissions on the NEW system:
|
|
- user: read
|
|
- issue: read and write
|
|
- set up login via tea → "tea login add --help", i.e.
|
|
- tea login add --name OLD --url https://oldgitea.example.com --token 123456789123456789
|
|
- tea login add --name NEW --url https://newgitea.example.com --token 123459789123456789
|
|
|
|
USAGE
|
|
-h | --help print this help
|
|
-r | --repo required, i.e. "my_organisation/my_repository"
|
|
-o | --login_old required, tea-id of your old login
|
|
-n | --login_new required, tea-id of your new login
|
|
--GO stop dry mode
|
|
EOF
|
|
}
|
|
|
|
error_in_or_out_not_specified()
|
|
{
|
|
echo -e "Error: --repo, --login_old and --login_new must be specified\n";
|
|
print_help;
|
|
exit 1
|
|
}
|
|
|
|
# @param $1 "command" → the command to check for
|
|
checkCommand()
|
|
{
|
|
command -v "$1" >/dev/null 2>&1 || { echo >&2 "Command ${1} is required but it's not installed. Aborting."; exit 42; }
|
|
}
|
|
|
|
#
|
|
# PARAMETERS
|
|
#
|
|
if [[ "$@" == "" ]] ; then error_in_or_out_not_specified ; fi
|
|
readonly TEMP=$(getopt -o h,r:o:n: --long help,GO,repo:login_old:,login_new: -n "${PROGNAME}" -- "$@")
|
|
eval set -- "${TEMP}"
|
|
while true ; do
|
|
case "$1" in
|
|
--help|-h)
|
|
print_help
|
|
exit 0
|
|
;;
|
|
--repo|-r)
|
|
repo="$2"
|
|
shift
|
|
;;
|
|
--login_old|-o)
|
|
login_old="$2"
|
|
shift
|
|
;;
|
|
--login_new|-n)
|
|
login_new="$2"
|
|
shift
|
|
;;
|
|
--GO)
|
|
dry_run=false
|
|
;;
|
|
--) shift ; break ;;
|
|
*) echo "Internal error!"
|
|
exit 5
|
|
;;
|
|
esac
|
|
shift
|
|
done
|
|
|
|
# check required
|
|
if [[ -z "$repo" || -z "$login_old" || -z "$login_new" ]] ; then error_in_or_out_not_specified ; fi
|
|
|
|
#
|
|
# START
|
|
#
|
|
if $dry_run; then echo -e "###\n### DRY RUN - will not change anything\n###"; fi
|
|
|
|
# check commands
|
|
checkCommand tea
|
|
checkCommand jq
|
|
checkCommand sort
|
|
checkCommand tr
|
|
|
|
# check access and get data
|
|
echo -e "\n# checking access to OLD (\"$login_old\") and NEW (\"$login_new\")"
|
|
readonly json_old=$(tea issues list --output json --login "$login_old" --repo "$repo" --state all --fields index,assignees,title)
|
|
readonly json_new=$(tea issues list --output json --login "$login_new" --repo "$repo" --state all --fields index,assignees,title)
|
|
|
|
echo -e "\n# running consitency checks"
|
|
readonly json_old_ids=$(echo "$json_old" | jq ".[] | .index" | sort -n)
|
|
readonly json_new_ids=$(echo "$json_new" | jq ".[] | .index" | sort -n)
|
|
# check if issues
|
|
if [[ "$json_old_ids" == "" || "$json_new_ids" == "" ]]; then echo >&2 "OLD and/or NEW repo contains no issues. Aborting."; exit 2; fi
|
|
# check same issues
|
|
if [[ "$json_old_ids" != "$json_new_ids" ]]; then
|
|
echo >&2 "OLD repositories' ids differ from NEW repository. Aborting.";
|
|
echo >&2 "OLD repositories' ids: $(echo "$json_old_ids" | tr '\n' ,)";
|
|
echo >&2 "NEW repositories' ids: $(echo "$json_new_ids" | tr '\n' ,)";
|
|
exit 2;
|
|
fi
|
|
# check if NEW.assignments are empty
|
|
readonly json_new_assignments=$(echo "$json_new" | jq --join-output ".[] | .assignees" )
|
|
if [[ "$json_new_assignments" != "" ]]; then echo >&2 "NEW repo already contains issues with assignments. Aborting."; exit 2; fi
|
|
|
|
|
|
# process data
|
|
echo -e "\n# processing data"
|
|
while IFS="¬"; read -r index assignees title; do
|
|
assignees=$(echo "$assignees" | tr ' ' ,)
|
|
issueinfo="… issue#$index - \"$title\" - assigned to \"$assignees\""
|
|
|
|
if [[ -n $assignees ]]; then
|
|
echo "$issueinfo"
|
|
if [ $dry_run = false ]; then
|
|
tea issue edit --login "$login_new" --repo "$repo" --add-assignees "$assignees" "$index" >/dev/null
|
|
fi
|
|
else
|
|
echo "$issueinfo - SKIPPED"
|
|
fi
|
|
|
|
done< <(echo "$json_old" | jq --raw-output '.[] | "\(.index)¬\(.assignees)¬\(.title)"')
|
|
|
|
exit 0
|