GitRoot

craft your forge, build your project, grow your community freely
   1#!/usr/bin/env bash
   2
   3# SPDX-FileCopyrightText: 2025 Romain Maneschi <romain@gitroot.dev>
   4#
   5# SPDX-License-Identifier: EUPL-1.2
   6
   7trap 'catch $LINENO' ERR
   8
   9EXPECTED_ERROR=0
  10
  11catch() {
  12    if [[ $EXPECTED_ERROR == 0 ]]; then
  13        echo "🛑 unexpected error line $1"
  14        exit 1
  15    fi
  16    report "🟢 expected err line $1"
  17}
  18
  19quiet_git() {
  20    echo "🚀 git $@" >> /tmp/mylog.txt
  21    GIT_TRACE=false GIT_TRACE_PACKET=false git "$@" &>> /tmp/mylog.txt
  22}
  23
  24report() {
  25    echo "$1" >> /tmp/mylog.txt
  26    echo "$1"
  27}
  28
  29mySleep() {
  30    echo "🕐 $1" >> /tmp/mylog.txt
  31    sleep $1
  32}
  33
  34function wait_for() {
  35    start=`date +%s`
  36    timeout=100
  37    until [ $timeout -le 0 ] || (grep -q $1 $2 &> /dev/null); do
  38        sleep 0.1
  39        timeout=$(( timeout - 1 ))
  40    done
  41    if [ $timeout -le 0 ]; then
  42        return 1
  43    fi
  44    end=`date +%s`
  45    echo "🕐 $@ in `expr $end - $start` seconds"
  46}
  47
  48function wait_ls() {
  49    start=`date +%s`
  50    timeout=100
  51    until [ $timeout -le 0 ] || [ $(ls $1 | wc -l) -eq 3 ]; do
  52        sleep 0.1
  53        timeout=$(( timeout - 1 ))
  54    done
  55    if [ $timeout -le 0 ]; then
  56        return 1
  57    fi
  58    end=`date +%s`
  59    echo "🕐 $@ in `expr $end - $start` seconds"
  60    mySleep 0.3
  61}
  62
  63EXIT_CODE=0
  64
  65SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
  66
  67SERVER_PORT="4545"
  68SERVER_URL=${1:-"127.0.0.1:$SERVER_PORT"}
  69SERVER_DATA_DIR="/tmp/gitrootData"
  70
  71ROOT_REPO_NAME="root"
  72ROOT_REPO_URL="ssh://user@${SERVER_URL}/${ROOT_REPO_NAME}"
  73REPO1_NAME="repo1"
  74REPO1_URL="ssh://user@${SERVER_URL}/${REPO1_NAME}"
  75REPO2_NAME="repo2"
  76REPO2_URL="ssh://user@${SERVER_URL}/${REPO2_NAME}"
  77REPO3_NAME="repo3"
  78REPO3_URL="ssh://user@${SERVER_URL}/${REPO3_NAME}"
  79
  80SSH_KEY="${SCRIPT_DIR}/user1/ed25519"
  81SSH_KEY2="${SCRIPT_DIR}/user2/ed25519"
  82
  83##### clean
  84report "🏁 clean"
  85
  86cd /tmp
  87rm -rf ${SERVER_DATA_DIR}
  88rm -rf ${ROOT_REPO_NAME}
  89rm -rf ${ROOT_REPO_NAME}_2
  90rm -rf ${REPO1_NAME}
  91rm -rf ${REPO2_NAME}
  92rm -rf ${REPO1_NAME}_2
  93rm -rf ${REPO2_NAME}_2
  94rm -rf ${REPO3_NAME}
  95rm -f /tmp/mylog.txt
  96APP=$(lsof -i tcp:${SERVER_PORT} | awk 'NR!=1 {print $2}') 
  97if [ -z "$APP" ]; then
  98    report "🟢 Gitroot not launched"
  99else 
 100    kill ${APP}
 101    report "🟢 Gitroot killed"
 102fi
 103ssh-keygen -f "$HOME/.ssh/known_hosts" -R "[127.0.0.1]:$SERVER_PORT"
 104
 105##### launch gitroot
 106report "🏁 launch gitroot"
 107
 108cd ${SCRIPT_DIR}/../server
 109GIT_TRACE_PACKET=false go run -race . -data="${SERVER_DATA_DIR}" &>> /tmp/mylog.txt &
 110
 111wait_for "starting SSH server on" /tmp/mylog.txt
 112
 113##### forgeConfig
 114report "🏁 forgeConfig"
 115
 116cd /tmp
 117quiet_git clone --quiet -c "core.sshCommand=ssh -i ${SSH_KEY} -o IdentitiesOnly=yes -o StrictHostKeyChecking=accept-new" ${ROOT_REPO_URL}
 118cd ${ROOT_REPO_NAME}
 119.gitroot/init.sh --pubKey "${SSH_KEY}.pub" --privKey "${SSH_KEY}" --email forgeConfig@gitroot.dev --name forgeConfig >> /tmp/mylog.txt
 120
 121DIFF=$(git status --porcelain .gitroot/allowed_signers)
 122if [[ $DIFF =~ "M .gitroot/allowed_signers" ]]; then
 123    report "🟢 ${ROOT_REPO_NAME}/.gitroot/allowed_signers"
 124else
 125    report "🛑 ${ROOT_REPO_NAME}/.gitroot/allowed_signers"
 126    EXIT_CODE=1
 127fi
 128
 129DIFF=$(git status --porcelain .gitroot/users.yml)
 130if [[ $DIFF =~ "M .gitroot/users.yml" ]]; then
 131    report "🟢 ${ROOT_REPO_NAME}/.gitroot/users.yml"
 132else
 133    report "🛑 ${ROOT_REPO_NAME}/.gitroot/users.yml"
 134    EXIT_CODE=1
 135fi
 136
 137quiet_git add .
 138quiet_git commit -m "init user"
 139report "🟢 ${ROOT_REPO_NAME} commit user"
 140
 141printf "${REPO1_NAME}:\n  defaultbranch: main" >> .gitroot/repositories.yml
 142quiet_git add .
 143quiet_git commit -m "create first repo"
 144quiet_git push origin main
 145report "🟢 ${ROOT_REPO_NAME} push first repo"
 146
 147mySleep 0.05
 148
 149##### Repo1
 150report "🏁 Repo1"
 151
 152cd /tmp
 153GIT_SSH_COMMAND="ssh -i ${SSH_KEY} -o IdentitiesOnly=yes" quiet_git clone --quiet "${REPO1_URL}"
 154cd ${REPO1_NAME}
 155.gitroot/init.sh --pubKey "${SSH_KEY}.pub" --privKey "${SSH_KEY}" --email repo1@gitroot.dev --name user1 >> /tmp/mylog.txt
 156
 157DIFF=$(git status --porcelain .gitroot/allowed_signers)
 158if [[ $DIFF =~ "M .gitroot/allowed_signers" ]]; then
 159    report "🟢 ${REPO1_NAME}/.gitroot/allowed_signers"
 160else
 161    report "🛑 ${REPO1_NAME}/.gitroot/allowed_signers"
 162    EXIT_CODE=1
 163fi
 164
 165DIFF2=$(git status --porcelain .gitroot/users.yml)
 166if [[ $DIFF2 =~ "M .gitroot/users.yml" ]]; then
 167    report "🟢 ${REPO1_NAME}/.gitroot/users.yml"
 168else
 169    report "🛑 ${REPO1_NAME}/.gitroot/users.yml"
 170    EXIT_CODE=1
 171fi
 172
 173quiet_git add .
 174quiet_git commit -m "init user"
 175report "🟢 ${REPO1_NAME} commit user"
 176
 177quiet_git checkout -b "branch1"
 178quiet_git push origin main branch1
 179report "🟢 ${REPO1_NAME} push main+branch1"
 180quiet_git checkout main
 181quiet_git push origin :branch1
 182report "🟢 ${REPO1_NAME} delete :branch1"
 183quiet_git push origin main
 184report "🟢 ${REPO1_NAME} push empty main"
 185
 186##### first plugin
 187report "🏁 first plugin"
 188
 189cd /tmp/${ROOT_REPO_NAME}
 190echo "- url: '${SCRIPT_DIR}/../plugins/ladybug/ladybug-0.0.1.wasm'" >> .gitroot/plugins.yml
 191echo "  crc32: null" >> .gitroot/plugins.yml
 192echo "  name: ladybug" >> .gitroot/plugins.yml
 193quiet_git add .
 194quiet_git commit -m "init ladybug plugin"
 195printf "\n${REPO2_NAME}:\n  defaultbranch: main" >> .gitroot/repositories.yml
 196quiet_git add .
 197quiet_git commit -m "create second repo"
 198quiet_git push origin main
 199report "🟢 ${ROOT_REPO_NAME} push first plugin and second repo"
 200
 201wait_ls "${SERVER_DATA_DIR}/data/plugins/ladybug"
 202
 203if [[ $(ls "${SERVER_DATA_DIR}/data/plugins/ladybug" | wc -l) -eq 3 ]]; then
 204    report "🟢 ${SERVER_DATA_DIR}/data/plugins/ladybug loaded"
 205else
 206    report "🛑 ${SERVER_DATA_DIR}/data/plugins/ladybug not downloaded"
 207    EXIT_CODE=1
 208fi
 209
 210quiet_git pull origin main
 211if grep -Fxq "      metadata:" .gitroot/plugins.yml
 212then
 213    report "🟢 ${ROOT_REPO_NAME} plugin config initialized"
 214else
 215    report "🛑 ${ROOT_REPO_NAME} not initialized"
 216    EXIT_CODE=1
 217fi
 218
 219if grep -Fxq "    - ladybug@localhost" .gitroot/users.yml
 220then
 221    report "🟢 ${ROOT_REPO_NAME} plugin user initialized"
 222else
 223    report "🛑 ${ROOT_REPO_NAME}  plugin user not initialized"
 224    EXIT_CODE=1
 225fi
 226
 227cd /tmp
 228GIT_SSH_COMMAND="ssh -i ${SSH_KEY} -o IdentitiesOnly=yes" quiet_git clone --quiet "${REPO2_URL}"
 229cd ${REPO2_NAME}
 230.gitroot/init.sh --pubKey "${SSH_KEY}.pub" --privKey "${SSH_KEY}" --email repo2@gitroot.dev  --name user1 >> /tmp/mylog.txt
 231
 232if grep -Fxq "      metadata:" .gitroot/plugins.yml
 233then
 234    report "🟢 ${REPO2_NAME} plugin config initialized"
 235else
 236    report "🛑 ${REPO2_NAME} not initialized"
 237    EXIT_CODE=1
 238fi
 239
 240if grep -q "      - path: issues/\\*\\*/\\*.md" .gitroot/plugins.yml
 241then
 242    report "🟢 ${REPO2_NAME} plugin path initialized"
 243else
 244    report "🛑 ${REPO2_NAME} not initialized"
 245    EXIT_CODE=1
 246fi
 247
 248sed -i -e 's/active: false/active: true/g' .gitroot/plugins.yml
 249
 250mkdir issues
 251echo "#my Issue" >> issues/1.md
 252echo "Beatiful issue" >> issues/1.md
 253quiet_git add .
 254quiet_git commit -m "first issue in second repo"
 255quiet_git push origin main
 256report "🟢 ${REPO2_NAME} first issue in second repo"
 257
 258mySleep 0.05
 259
 260quiet_git pull
 261
 262if grep -q "priority: 50" issues/1.md
 263then
 264    report "🟢 issues/1.md initialized"
 265else
 266    report "🛑 issues/1.md not initialized"
 267    EXIT_CODE=1
 268fi
 269
 270##### repo1 should have issue available
 271report "🏁 repo1 should have issue available"
 272
 273cd /tmp/${REPO1_NAME}
 274
 275quiet_git pull
 276
 277if grep -q "      - path: issues/\\*\\*/\\*.md" .gitroot/plugins.yml
 278then
 279    report "🟢 ${REPO1_NAME} plugin path initialized"
 280else
 281    report "🛑 ${REPO1_NAME} not initialized"
 282    EXIT_CODE=1
 283fi
 284
 285sed -i -e 's/active: false/active: true/g' .gitroot/plugins.yml
 286
 287mkdir issues
 288echo "#my Issue" >> issues/1.md
 289echo "Beatiful issue" >> issues/1.md
 290quiet_git add .
 291quiet_git commit -m "first issue in first repo"
 292quiet_git push origin main
 293report "🟢 ${REPO1_NAME} first issue in first repo"
 294
 295mySleep 0.05
 296
 297quiet_git pull
 298
 299if grep -q "priority: 50" issues/1.md
 300then
 301    report "🟢 issues/1.md initialized"
 302else
 303    report "🛑 issues/1.md not initialized"
 304    EXIT_CODE=1
 305fi
 306
 307##### user2 rights
 308report "🏁 user2 rights"
 309
 310cd /tmp
 311GIT_SSH_COMMAND="ssh -i ${SSH_KEY2} -o IdentitiesOnly=yes" quiet_git clone --quiet "${REPO1_URL}" ${REPO1_NAME}_2
 312cd ${REPO1_NAME}_2
 313.gitroot/init.sh --pubKey "${SSH_KEY2}.pub" --privKey "${SSH_KEY2}" --email user2repo1@gitroot.dev  --name user2 >> /tmp/mylog.txt
 314
 315echo "#my Issue" >> issues/cac-1.md
 316echo "Beatiful issue" >> issues/cac-1.md
 317
 318quiet_git add .
 319quiet_git commit -m "user2 config and an issue"
 320EXPECTED_ERROR=1
 321quiet_git push origin main
 322if [[ "$?" == "0" ]]; then
 323    report "🛑 user2 has push on main in repo1"
 324    EXIT_CODE=1
 325else
 326    report "🟢 user2 can not push on main in repo1"
 327fi
 328EXPECTED_ERROR=0
 329
 330quiet_git reset --soft HEAD~1 
 331quiet_git checkout -b user2_branch_on_repo1
 332quiet_git add .
 333quiet_git commit -m "user2 config and an issue"
 334quiet_git push origin user2_branch_on_repo1
 335
 336if [[ "$?" == "0" ]]; then
 337    report "🟢 user2 can push on user2_branch_on_repo1 branch in repo1"
 338else
 339    report "🛑 user2 can not push on user2_branch_on_repo1 branch in repo1"
 340    EXIT_CODE=1
 341fi
 342
 343mySleep 0.05
 344quiet_git pull origin user2_branch_on_repo1
 345
 346if grep -q "priority: 50" issues/cac-1.md
 347then
 348    report "🟢 issues/cac-1.md initialized"
 349else
 350    report "🛑 issues/cac-1.md not initialized"
 351    EXIT_CODE=1
 352fi
 353
 354echo "New readme" > "README.md"
 355quiet_git add .
 356quiet_git commit -m "update readme"
 357quiet_git push origin user2_branch_on_repo1
 358
 359if [[ "$?" == "0" ]]; then
 360    report "🟢 user2 can push on user2_branch_on_repo1 branch in repo1 second time"
 361else
 362    report "🛑 user2 can not push on user2_branch_on_repo1 branch in repo1 second time"
 363    EXIT_CODE=1
 364fi
 365
 366quiet_git checkout main
 367
 368cd /tmp/${REPO1_NAME}
 369quiet_git fetch origin user2_branch_on_repo1
 370quiet_git checkout user2_branch_on_repo1
 371
 372echo "New readme by user 1" > "README.md"
 373quiet_git add .
 374quiet_git commit -m "update readme"
 375quiet_git push origin user2_branch_on_repo1
 376report "🟢 user1 can push on user2_branch_on_repo1 branch in repo1"
 377
 378quiet_git checkout main
 379
 380##### verify commit
 381report "🏁 verify commits"
 382cd /tmp/${ROOT_REPO_NAME}
 383git reflog show main |  awk '{ print $1 }' | xargs git verify-commit &> /dev/null
 384report "🟢 ${ROOT_REPO_NAME}"
 385
 386cd /tmp/${REPO1_NAME}
 387git reflog show main |  awk '{ print $1 }' | xargs git verify-commit &> /dev/null
 388report "🟢 ${REPO1_NAME}"
 389
 390cd /tmp/${REPO2_NAME}
 391git reflog show main |  awk '{ print $1 }' | xargs git verify-commit &> /dev/null
 392report "🟢 ${REPO2_NAME}"
 393
 394##### second plugin
 395report "🏁 second plugin"
 396
 397cd /tmp/${ROOT_REPO_NAME}
 398echo "- url: '${SCRIPT_DIR}/../plugins/silo/silo-0.0.1.wasm'" >> .gitroot/plugins.yml
 399echo "  crc32: null" >> .gitroot/plugins.yml
 400echo "  name: silo" >> .gitroot/plugins.yml
 401quiet_git add .
 402quiet_git commit -m "init silo plugin"
 403quiet_git push origin main
 404echo "🟢 ${ROOT_REPO_NAME} push second plugin"
 405
 406wait_ls "${SERVER_DATA_DIR}/data/plugins/silo"
 407
 408quiet_git pull origin main
 409
 410cd /tmp/${REPO1_NAME}
 411
 412quiet_git pull
 413
 414if grep -q "title: "Roadmaps"" .gitroot/plugins.yml
 415then
 416    report "🟢 ${REPO1_NAME} plugin path initialized"
 417else
 418    report "🛑 ${REPO1_NAME} not initialized"
 419    EXIT_CODE=1
 420fi
 421
 422sed -i -e 's/active: false/active: true/g' .gitroot/plugins.yml
 423
 424echo "---" >> issues/roadmap1.md
 425echo "id: 22C3" >> issues/roadmap1.md
 426echo "priority: 50" >> issues/roadmap1.md
 427echo "assignee: null" >> issues/roadmap1.md
 428echo "kind: 'roadmap'" >> issues/roadmap1.md
 429echo "---" >> issues/roadmap1.md
 430echo "# step 1: conquers the world" >> issues/roadmap1.md
 431echo "" >> issues/roadmap1.md
 432echo "To do that just imagine the world is small." >> issues/roadmap1.md
 433
 434echo "---" >> issues/roadmap2.md
 435echo "id: 22C3" >> issues/roadmap2.md
 436echo "priority: 10" >> issues/roadmap2.md
 437echo "assignee: null" >> issues/roadmap2.md
 438echo "kind: 'roadmap'" >> issues/roadmap2.md
 439echo "---" >> issues/roadmap2.md
 440echo "# step 2: profit" >> issues/roadmap2.md
 441echo "" >> issues/roadmap2.md
 442echo "Finally take in peace." >> issues/roadmap2.md
 443
 444quiet_git add .
 445quiet_git commit -m "active silo and build first roadmap ticket"
 446quiet_git push origin main
 447
 448mySleep 0.1
 449
 450quiet_git pull
 451
 452if grep -q "issues/roadmap1.md" boards/roadmap.md
 453then
 454    report "🟢 ${REPO1_NAME} roadmap initialized"
 455else
 456    report "🛑 ${REPO1_NAME} roadmap not initialized"
 457    EXIT_CODE=1
 458fi
 459
 460if grep -q "issues/1.md" boards/issues.md
 461then
 462    report "🟢 ${REPO1_NAME} issues board initialized"
 463else
 464    report "🛑 ${REPO1_NAME} issues board not initialized"
 465    EXIT_CODE=1
 466fi
 467
 468if grep -q "issues/1.md" boards/triage.md
 469then
 470    report "🟢 ${REPO1_NAME} triage board initialized"
 471else
 472    report "🛑 ${REPO1_NAME} triage board not initialized"
 473    EXIT_CODE=1
 474fi
 475
 476quiet_git pull --rebase origin main
 477
 478for (( i=0; i<=50; i++ ))
 479do
 480    echo "# My issue $i" >> issues/issue_$i.md
 481    echo "" >> issues/issue_$i.md
 482    echo "Beatiful issue" >> issues/issue_$i.md
 483done
 484
 485quiet_git add .
 486quiet_git commit -m "create lot of issues"
 487quiet_git push origin main
 488
 489mySleep 0.5
 490
 491quiet_git pull
 492
 493for (( i=0; i<=50; i++ ))
 494do
 495    PRIO=$(shuf -i 0-99 -n 1)
 496    sed -i -e "s/priority: 50/priority: $PRIO/g" issues/issue_$i.md
 497done
 498
 499quiet_git add .
 500quiet_git commit -m "update random prio of lot of issues"
 501quiet_git push origin main
 502
 503mySleep 0.05
 504
 505quiet_git pull
 506
 507##### Repo2 don't allow anonymous contrib
 508report "🏁 Repo2 don't allow anonymous contrib"
 509
 510cd /tmp/${REPO2_NAME}
 511
 512quiet_git pull
 513
 514echo "" >> .gitroot/users.yml
 515echo "\"*\":" >> .gitroot/users.yml
 516echo "  branches:" >> .gitroot/users.yml
 517echo "    - name: \"*\"" >> .gitroot/users.yml
 518echo "  users: []" >> .gitroot/users.yml
 519
 520quiet_git add .
 521quiet_git commit -m "block all modifications of anonymous users"
 522quiet_git push origin main
 523
 524cd /tmp
 525GIT_SSH_COMMAND="ssh -i ${SSH_KEY2} -o IdentitiesOnly=yes" quiet_git clone --quiet "${REPO2_URL}" ${REPO2_NAME}_2
 526cd ${REPO2_NAME}_2
 527.gitroot/init.sh --pubKey "${SSH_KEY2}.pub" --privKey "${SSH_KEY2}" --email user2repo2@gitroot.dev --name user2 >> /tmp/mylog.txt
 528
 529quiet_git checkout -b tryToAddMe
 530quiet_git add .
 531quiet_git commit -m "user2 config"
 532
 533EXPECTED_ERROR=1
 534quiet_git push origin tryToAddMe
 535if [[ "$?" == "0" ]]; then
 536    report "🛑 user2 can push on tryToAddMe branch in repo2"
 537    EXIT_CODE=1
 538else
 539    report "🟢 user2 can not push on tryToAddMe branch in repo2"
 540fi
 541EXPECTED_ERROR=0
 542
 543##### User2 can add issue in repo1 on branch user2_issue_on_repo1
 544report "🏁 User2 can add issue in repo1 on branch user2_issue_on_repo1"
 545
 546cd /tmp/${REPO1_NAME}_2
 547
 548quiet_git pull origin main
 549
 550quiet_git checkout -b user2_issue_on_repo1
 551
 552echo "# My issue" >> issues/2.md
 553echo "" >> issues/2.md
 554echo "This is my issue" >> issues/2.md
 555
 556quiet_git add .
 557quiet_git commit -m "user2 issue 1"
 558
 559echo "---" >> issues/roadmap3.md
 560echo "id: 22E3" >> issues/roadmap3.md
 561echo "priority: 40" >> issues/roadmap3.md
 562echo "assignee: null" >> issues/roadmap3.md
 563echo "kind: 'roadmap'" >> issues/roadmap3.md
 564echo "---" >> issues/roadmap3.md
 565echo "# step 3: give" >> issues/roadmap3.md
 566echo "" >> issues/roadmap3.md
 567echo "Just fun." >> issues/roadmap3.md
 568
 569quiet_git add .
 570quiet_git commit -m "user2 roadmap 3"
 571
 572quiet_git push origin user2_issue_on_repo1 :user2_branch_on_repo1
 573
 574mySleep 0.05
 575
 576quiet_git pull origin user2_issue_on_repo1
 577
 578if grep -q "id:" issues/2.md
 579then
 580    report "🟢 ${REPO1_NAME}_2 issues/2.md initialized"
 581else
 582    report "🛑 ${REPO1_NAME}_2 issues/2.md not initialized"
 583    EXIT_CODE=1
 584fi
 585
 586if grep -q "step 3: give" boards/roadmap.md
 587then
 588    report "🛑 ${REPO1_NAME}_2 boards/roadmap should not be updated has silo is only on main"
 589    EXIT_CODE=1
 590else
 591    report "🟢 ${REPO1_NAME}_2 boards/roadmap not updated"
 592fi
 593
 594quiet_git checkout -b user2_issue2_on_repo1
 595
 596echo "# My issue" >> issues/3.md
 597echo "" >> issues/3.md
 598echo "This is my issue" >> issues/3.md
 599
 600quiet_git add .
 601quiet_git commit -m "user2 issue 2"
 602quiet_git push origin user2_issue2_on_repo1
 603
 604mySleep 0.05
 605
 606quiet_git pull origin user2_issue2_on_repo1
 607
 608if grep -q "id:" issues/3.md
 609then
 610    report "🟢 ${REPO1_NAME}_2 issues/3.md initialized"
 611else
 612    report "🛑 ${REPO1_NAME}_2 issues/3.md not initialized"
 613    EXIT_CODE=1
 614fi
 615
 616NB_SILO=$(grep "step 3: give" boards/roadmap.md | wc -l)
 617if [[ "$NB_SILO" == "0" ]]; then
 618    report "🟢 ${REPO1_NAME}_2 silo has not been called"
 619else
 620    report "🛑 ${REPO1_NAME}_2 silo has been called $NB_SILO times"
 621    EXIT_CODE=1
 622fi
 623
 624##### User1 push force in repo1 on main
 625report "🏁 User1 push force in repo1 on main"
 626cd /tmp/${REPO1_NAME}
 627mySleep 0.1
 628quiet_git pull
 629echo "not authorized" > issues/1.md
 630quiet_git add .
 631quiet_git commit --amend --no-edit
 632
 633EXPECTED_ERROR=1
 634quiet_git push -f origin main
 635if [[ "$?" == "0" ]]; then
 636    report "🛑 user1 can push force on main"
 637    EXIT_CODE=1
 638else
 639    report "🟢 user1 can not push force on main"
 640fi
 641EXPECTED_ERROR=0
 642quiet_git reset --hard origin/HEAD
 643
 644##### User2 push force in repo1 on branch user2_branch2_on_repo1
 645report "🏁 User2 push force in repo1 on branch user2_branch2_on_repo1"
 646
 647cd /tmp/${REPO1_NAME}_2
 648quiet_git checkout main
 649quiet_git checkout -b user2_branch2_on_repo1
 650
 651#add a commit
 652cd /tmp/${REPO1_NAME}
 653quiet_git checkout main
 654echo "hello" >> README.md
 655quiet_git add .
 656quiet_git commit -m "fake commit"
 657quiet_git push origin main
 658
 659mySleep 0.1
 660
 661cd /tmp/${REPO1_NAME}_2
 662echo "---" >> issues/roadmap4.md
 663echo "id: 22C3" >> issues/roadmap4.md
 664echo "priority: 50" >> issues/roadmap4.md
 665echo "assignee: null" >> issues/roadmap4.md
 666echo "kind: 'roadmap'" >> issues/roadmap4.md
 667echo "---" >> issues/roadmap4.md
 668echo "# step 1: conquers the world" >> issues/roadmap4.md
 669echo "" >> issues/roadmap4.md
 670echo "To do that just imagine the world is small." >> issues/roadmap4.md
 671
 672quiet_git add .
 673quiet_git commit -m "roadmap4"
 674quiet_git push origin user2_branch2_on_repo1
 675
 676quiet_git checkout main
 677quiet_git pull --rebase origin main
 678quiet_git checkout user2_branch2_on_repo1
 679
 680quiet_git rebase -X ours main
 681report "🟢 Rebase ok"
 682
 683quiet_git push -f origin user2_branch2_on_repo1
 684mySleep 0.05
 685report "🟢 Push -f ok"
 686
 687NB_SILO=$(grep "step 1:" boards/roadmap.md | wc -l)
 688if [[ "$NB_SILO" == "1" ]]; then
 689    report "🟢 ${REPO1_NAME}_2 silo has not been called"
 690else
 691    report "🛑 ${REPO1_NAME}_2 silo has been called $NB_SILO times"
 692    EXIT_CODE=1
 693fi
 694
 695##### Add grafter plugin in repo1
 696report "🏁 Add grafter plugin in repo1"
 697
 698cd /tmp/${ROOT_REPO_NAME}
 699echo "- url: '${SCRIPT_DIR}/../plugins/grafter/grafter-0.0.1.wasm'" >> .gitroot/plugins.yml
 700echo "  crc32: null" >> .gitroot/plugins.yml
 701echo "  name: grafter" >> .gitroot/plugins.yml
 702quiet_git add .
 703quiet_git commit -m "init grafter plugin"
 704quiet_git push origin main
 705
 706wait_ls "${SERVER_DATA_DIR}/data/plugins/grafter"
 707quiet_git pull origin main
 708
 709cd /tmp/${REPO1_NAME}
 710quiet_git pull origin main
 711sed -i -e 's/active: false/active: true/g' .gitroot/plugins.yml
 712report "🟢 ${REPO1_NAME} grafter plugin initialized"
 713quiet_git add .
 714quiet_git commit -m "active grafter plugin"
 715quiet_git push origin main
 716
 717mySleep 0.05
 718
 719quiet_git pull origin main
 720
 721report "🟢 ${REPO1_NAME} grafter plugin activated"
 722quiet_git checkout -b graft_something
 723echo "hello" >> tada.md
 724quiet_git add .
 725quiet_git commit -m "first graft"
 726quiet_git push origin graft_something
 727
 728mySleep 0.1
 729
 730quiet_git pull origin graft_something
 731NB_STATUS_DRAFT=$(grep "status: draft" grafts/graft_something.md | wc -l)
 732if [[ "$NB_STATUS_DRAFT" == "1" ]]; then
 733    report "🟢 ${REPO1_NAME} status: draft ok"
 734else
 735    report "🛑 ${REPO1_NAME} status: draft ko"
 736    EXIT_CODE=1
 737fi
 738report "🟢 ${REPO1_NAME} first graft created"
 739
 740rm issues/1.md
 741quiet_git add .
 742quiet_git commit -m "rm issue first graft"
 743echo "second" > issues/2.md
 744quiet_git add .
 745quiet_git commit -m "second issue first graft"
 746mv issues/roadmap1.md issues/roadmap.md
 747quiet_git add .
 748quiet_git commit -m "move roadmap first graft"
 749quiet_git push origin graft_something
 750
 751mySleep 0.1
 752
 753quiet_git pull origin graft_something
 754NB_PUSH=$(grep "Push " grafts/graft_something.md | wc -l)
 755NB_COMMIT=$(grep "### " grafts/graft_something.md | wc -l)
 756if [[ "$NB_COMMIT" == "5" ]] && [[ "$NB_PUSH" == "3" ]]; then
 757    report "🟢 ${REPO1_NAME} graft has 3 push and 5 commits"
 758else
 759    report "🛑 ${REPO1_NAME} graft has $NB_PUSH push and $NB_COMMIT commits"
 760    EXIT_CODE=1
 761fi
 762
 763NB_COMMIT=$(git log --oneline graft_something ^main | wc -l)
 764if [[ $NB_COMMIT -eq 9 ]]; then
 765    report "🟢 ${REPO1_NAME} has 9 commits on branch graft_something"
 766else
 767    report "🛑 ${REPO1_NAME} has $NB_COMMIT commits on branch graft_something"
 768    EXIT_CODE=1
 769fi
 770
 771echo "" >> grafts/graft_something.md
 772echo "---" >> grafts/graft_something.md
 773echo "/review" >> grafts/graft_something.md
 774quiet_git add .
 775quiet_git commit -m "review first graft"
 776quiet_git push origin graft_something
 777
 778mySleep 0.1
 779
 780quiet_git pull origin graft_something
 781NB_STATUS_DRAFT=$(grep "status: draft" grafts/graft_something.md | wc -l)
 782if [[ "$NB_STATUS_DRAFT" == "0" ]]; then
 783    report "🟢 ${REPO1_NAME} status no more draft"
 784else
 785    report "🛑 ${REPO1_NAME} status: draft ko"
 786    EXIT_CODE=1
 787fi
 788NB_REVIEWERS=$(grep "reviewers: " grafts/graft_something.md | wc -l)
 789if [[ "$NB_REVIEWERS" == "1" ]]; then
 790    report "🟢 ${REPO1_NAME} reviewers added"
 791else
 792    report "🛑 ${REPO1_NAME} reviewers ko"
 793    EXIT_CODE=1
 794fi
 795NB_MENTION_OF_REVIEW=$(grep "review first graft" grafts/graft_something.md | wc -l)
 796if [[ "$NB_MENTION_OF_REVIEW" == "0" ]]; then
 797    report "🟢 ${REPO1_NAME} commit review skipped"
 798else
 799    report "🛑 ${REPO1_NAME} commit review not skipped"
 800    EXIT_CODE=1
 801fi
 802report "🟢 ${REPO1_NAME} first graft ready to review"
 803
 804echo "second is 2" > issues/2.md
 805quiet_git add .
 806quiet_git commit -m "second issue review first graft"
 807quiet_git push origin graft_something
 808
 809mySleep 0.05
 810
 811quiet_git pull origin graft_something
 812NB_DIFF=$(grep -F '```diff' grafts/graft_something.md | wc -l)
 813if [[ "$NB_DIFF" == "2" ]]; then
 814    report "🟢 ${REPO1_NAME} diff added"
 815else
 816    report "🛑 ${REPO1_NAME} diff ko $NB_DIFF"
 817    EXIT_CODE=1
 818fi
 819
 820echo "---" >> grafts/graft_something.md
 821echo "" >> grafts/graft_something.md
 822echo "/merge" >> grafts/graft_something.md
 823quiet_git add .
 824quiet_git commit -m "merge first graft"
 825quiet_git push origin graft_something
 826
 827mySleep 0.1
 828
 829quiet_git checkout main
 830quiet_git pull --rebase origin main
 831cat grafts/graft_something.md
 832
 833mySleep 0.5
 834
 835##### Add apex plugin in repo1
 836report "🏁 Add apex plugin in repo1"
 837
 838cd /tmp/${ROOT_REPO_NAME}
 839echo "- url: '${SCRIPT_DIR}/../plugins/apex/apex-0.0.1.wasm'" >> .gitroot/plugins.yml
 840echo "  crc32: null" >> .gitroot/plugins.yml
 841echo "  name: apex" >> .gitroot/plugins.yml
 842quiet_git add .
 843quiet_git commit -m "init apex plugin"
 844quiet_git push origin main
 845
 846wait_ls "${SERVER_DATA_DIR}/data/plugins/apex"
 847quiet_git pull origin main
 848report "🟢 ${ROOT_REPO_NAME} apex plugin installed"
 849
 850cd /tmp/${REPO1_NAME}
 851quiet_git pull origin main
 852sed -i -e 's/active: false/active: true/g' .gitroot/plugins.yml
 853report "🟢 ${REPO1_NAME} apex plugin initialized"
 854quiet_git add .
 855quiet_git commit -m "active apex plugin"
 856quiet_git push origin main
 857
 858mySleep 0.5
 859
 860quiet_git pull origin main
 861
 862report "🟢 ${REPO1_NAME} apex plugin activated"
 863echo "# hello" > hello2.md
 864echo "## hello2" >> hello2.md
 865echo "### hello3" >> hello2.md
 866quiet_git add .
 867quiet_git commit -m "first html"
 868quiet_git push origin main
 869
 870mySleep 0.1
 871
 872sed -i -e 's/active: true/active: false/g' .gitroot/plugins.yml
 873
 874quiet_git add .
 875quiet_git commit -m "inactive all plugins"
 876quiet_git push origin main
 877
 878mySleep 0.1
 879
 880sed -i -e 's/active: false/active: true/g' .gitroot/plugins.yml
 881sed -i -e 's/style: simple.min.css/style: style.css/g' .gitroot/plugins.yml
 882
 883cp ${SCRIPT_DIR}/../server/resources/styles/simple.min.css style.css
 884cat ${SCRIPT_DIR}/../plugins/apex/resources/styles/add.css >> style.css
 885echo "body { background-color: 010409 }" >> style.css
 886echo "body > header { background-color: 010409; text-align: left; padding: 0 1rem }" >> style.css
 887echo "body > header h1 { font-size: 1rem }" >> style.css
 888echo "header > nav  ul { place-content: normal }" >> style.css
 889echo "header > nav  a { margin: 0 .5rem; border: 0 }" >> style.css
 890
 891quiet_git add .
 892quiet_git commit -m "perso style"
 893quiet_git push origin main
 894
 895##### User2 can create repo3
 896report "🏁 User2 can create repo3 with master branch"
 897
 898cd /tmp/${ROOT_REPO_NAME}
 899sed -i -e 's/active: false/active: true/g' .gitroot/plugins.yml
 900report "🟢 ${ROOT_REPO_NAME} plugins will activate"
 901quiet_git add .
 902quiet_git commit -m "active all plugins"
 903quiet_git push origin main
 904
 905mySleep 1
 906
 907quiet_git pull origin main
 908report "🟢 ${ROOT_REPO_NAME} plugins activated"
 909
 910cd /tmp
 911GIT_SSH_COMMAND="ssh -i ${SSH_KEY2} -o IdentitiesOnly=yes" quiet_git clone --quiet "${ROOT_REPO_URL}" ${ROOT_REPO_NAME}_2
 912cd ${ROOT_REPO_NAME}_2
 913quiet_git checkout -b create_repo3
 914.gitroot/init.sh --pubKey "${SSH_KEY2}.pub" --privKey "${SSH_KEY2}" --email user2root@gitroot.dev  --name user2 >> /tmp/mylog.txt
 915PUB=$(cat ${SSH_KEY2}.pub)
 916printf "\n${REPO3_NAME}:\n  defaultbranch: master\n  owners:\n   - ${PUB}" >> .gitroot/repositories.yml
 917quiet_git add .
 918quiet_git commit -m "create repo3"
 919quiet_git push origin create_repo3
 920report "🟢 ${ROOT_REPO_NAME}_2 push create_repo3 repo"
 921
 922mySleep 0.1
 923
 924cd /tmp/${ROOT_REPO_NAME}
 925quiet_git pull --rebase origin main
 926quiet_git fetch origin create_repo3
 927quiet_git checkout create_repo3
 928echo "---" >> grafts/create_repo3.md
 929echo "" >> grafts/create_repo3.md
 930echo "/merge" >> grafts/create_repo3.md
 931quiet_git add .
 932quiet_git commit -m "merge create_repo3 graft"
 933quiet_git push origin create_repo3
 934
 935mySleep 0.1
 936
 937cd /tmp
 938GIT_SSH_COMMAND="ssh -i ${SSH_KEY2} -o IdentitiesOnly=yes" quiet_git clone --quiet "${REPO3_URL}"
 939
 940cd ${REPO3_NAME}
 941.gitroot/init.sh --pubKey "${SSH_KEY2}.pub" --privKey "${SSH_KEY2}" --email user2repo3@gitroot.dev  --name user2 >> /tmp/mylog.txt
 942echo "works" > README.md
 943quiet_git add .
 944quiet_git commit -m "mine readme"
 945quiet_git push origin master
 946
 947##### Shallow
 948report "🏁 Shallow"
 949
 950cd /tmp
 951rm -rf repo1_shallow
 952GIT_SSH_COMMAND="ssh -i ${SSH_KEY2} -o IdentitiesOnly=yes" quiet_git clone --quiet --depth 1 ssh://git@127.0.0.1:4545/repo1 repo1_shallow
 953cd repo1_shallow
 954.gitroot/init.sh --pubKey "${SSH_KEY2}.pub" --privKey "${SSH_KEY2}" --email user2repo1Shallow@gitroot.dev  --name user2 >> /tmp/mylog.txt
 955
 956NB_COMMIT=$(git rev-list HEAD --count)
 957if [[ $NB_COMMIT -eq 1 ]]; then
 958    report "🟢 repo1_shallow has 1 commit"
 959else
 960    report "🛑 repo1_shallow has $NB_COMMIT commits"
 961    EXIT_CODE=1
 962fi
 963
 964quiet_git fetch --deepen 1 origin main
 965NB_COMMIT=$(git rev-list HEAD --count)
 966if [[ $NB_COMMIT -eq 2 ]]; then
 967    report "🟢 repo1_shallow has 2 commits"
 968else
 969    report "🛑 repo1_shallow has $NB_COMMIT commits"
 970    EXIT_CODE=1
 971fi
 972
 973quiet_git fetch --shallow-exclude=graft_something origin main
 974NB_COMMIT=$(git rev-list HEAD --count)
 975if [[ $NB_COMMIT -eq 11 ]]; then
 976    report "🟢 repo1_shallow has 11 commits"
 977else
 978    report "🛑 repo1_shallow has $NB_COMMIT commits"
 979    EXIT_CODE=1
 980fi
 981
 982##### Finish
 983report "🏁 Finish"
 984if grep -q -i "error" /tmp/mylog.txt
 985then
 986    report "🛑 Logs contains error"
 987    EXIT_CODE=1
 988else
 989    report "🟢 Logs no error"
 990fi
 991
 992if grep -q -i "WARNING: DATA RACE" /tmp/mylog.txt
 993then
 994    report "🛑 Logs contains data race"
 995    EXIT_CODE=1
 996else
 997    report "🟢 Logs no data race"
 998fi
 999
1000report ""
1001report "✎ Find all logs in /tmp/mylog.txt"
1002exit $EXIT_CODE