#!/bin/bash # Migrate assignments for Gitea-Issues after a Gitea2Gitea-Migration # 2024 Benjamin Winter set -eu readonly PROGNAME=`/usr/bin/basename $0` readonly PROGPATH=`echo $0 | sed -e 's,[\\/][^\\/][^\\/]*$,,'` readonly REVISION="0.0.1-WIP" repo="" login_old="" login_new="" dry_run=true # # FUNCTIONS # print_help() { 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 - 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 - if your titles include a ¬ character, the script may could behave funny as this i used as separator INSTALLATION AND PREPARATION - install - jq - Command-line JSON processor - tea: 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 2 } # @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 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 # get data echo -e "\n# checking access to OLD (\"$login_old\") and NEW (\"$login_new\")" json_old=$(tea issues list --output json --login "$login_old" --repo "$repo" --state all --fields index,assignees,title) json_new=$(tea issues list --output json --login "$login_new" --repo "$repo" --state all --fields index,assignees,title) # check data readonly json_old_ids=$(echo "$json_old" | jq ".[] | .index") readonly json_new_ids=$(echo "$json_new" | jq ".[] | .index") 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 3; fi # process data while IFS="¬"; read -r index assignees title; do echo "processing issue #${index} - \"${title}\", assigned to \"${assignees}\"" done< <(echo "$json_old" | jq --raw-output '.[] | "\(.index)¬\(.assignees)¬\(.title)"') exit 0