From c1ec85004ad655eeacfc41edca33d860c3faa8fc Mon Sep 17 00:00:00 2001 From: Alireza Sadraii Rad Date: Mon, 22 Apr 2024 23:41:17 +0200 Subject: [PATCH 01/11] add ci/cd build docker image --- .github/workflows/main.yml | 95 ++++++++++ utils/appimage/Dockerfile.builder-1804 | 36 ++++ utils/appimage/Dockerfile.builder-2004 | 30 ++++ utils/appimage/Dockerfile.builder-2404 | 24 +++ utils/appimage/build_appimage.sh | 39 ++++ utils/appimage/build_code.sh | 8 + utils/appimage/rcssserver.desktop | 14 ++ utils/appimage/rcssserver.png | Bin 0 -> 25317 bytes utils/docker/Dockerfile | 59 ++++++ utils/docker/README.md | 43 +++++ utils/docker/docker-entrypoint.sh | 237 +++++++++++++++++++++++++ 11 files changed, 585 insertions(+) create mode 100644 .github/workflows/main.yml create mode 100644 utils/appimage/Dockerfile.builder-1804 create mode 100644 utils/appimage/Dockerfile.builder-2004 create mode 100644 utils/appimage/Dockerfile.builder-2404 create mode 100755 utils/appimage/build_appimage.sh create mode 100755 utils/appimage/build_code.sh create mode 100644 utils/appimage/rcssserver.desktop create mode 100644 utils/appimage/rcssserver.png create mode 100644 utils/docker/Dockerfile create mode 100644 utils/docker/README.md create mode 100755 utils/docker/docker-entrypoint.sh diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 00000000..081b8581 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,95 @@ +name: ci + +on: + push: + branches: + - "master" + tags: + - "*" + +env: + BASE_IMAGE: crosslanguagesoccerframework/rcssserver + BASE_TAG: latest + +jobs: + docker: + runs-on: ubuntu-latest + name: Build & Push Docker + if: startsWith(github.ref, 'refs/tags/') + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Find CMakeLists.txt version + id: cmake_version + run: | + cmake_version=$(grep -oP 'project\(.* VERSION \K[0-9]+\.[0-9]+\.[0-9]+' CMakeLists.txt) + echo "::set-output name=version::${cmake_version}" + + + - name: Login to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Build and push RCSSServer + uses: docker/build-push-action@v5 + with: + context: . + file: ./utils/docker/Dockerfile + push: true + tags: "${{ env.BASE_IMAGE }}:latest,${{ env.BASE_IMAGE }}:ubuntu-24-${{ github.ref_name }}-${{ steps.cmake_version.outputs.version }}" + + - name: Docker Hub Description + uses: peter-evans/dockerhub-description@v4 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + repository: ${{ env.BASE_IMAGE }} + readme-filepath: utils/docker/README.md + short-description: "RoboCup Soccer Simulator Server" + + app-image: + runs-on: ubuntu-latest + name: Build AppImage + steps: + - uses: actions/checkout@v4 + + - name: Create release folder + run: | + mkdir -p ${{ github.workspace }}/artifact + + # ------------------------------------------- Ubuntu 20.04 AppImage + - name: Prepare builder image for 20.04 + run: | + docker build -t builder-image:2004 -f ./utils/appimage/Dockerfile.builder-2004 . + + - name: Build app image on 20.04 + run: | + docker run --privileged --name builder-2004 \ + builder-image:2004 /rcssserver/utils/appimage/build_appimage.sh + docker cp builder-2004:/rcssserver-x86_64.AppImage ${{ github.workspace }}/artifact/rcssserver-x86_64-2004.AppImage + + # ------------------------------------------- Artifact + - name: Upload Artifact + uses: actions/upload-artifact@v4 + with: + name: rcssserver-x86_64 + path: ${{ github.workspace }}/artifact/* + retention-days: 5 + + # ------------------------------------------- Release + - uses: ncipollo/release-action@v1 + if: startsWith(github.ref, 'refs/tags/') + with: + artifacts: "${{ github.workspace }}/artifact/*" + token: ${{ secrets.GITHUB_TOKEN }} + # tag text is like "v1.2.3" so we need to remove the "v" from the tag + tag: "${{ github.ref_name }}" diff --git a/utils/appimage/Dockerfile.builder-1804 b/utils/appimage/Dockerfile.builder-1804 new file mode 100644 index 00000000..c34733fc --- /dev/null +++ b/utils/appimage/Dockerfile.builder-1804 @@ -0,0 +1,36 @@ +FROM ubuntu:18.04 + +COPY . /rcssserver + +RUN apt-get clean && apt-get update --allow-insecure-repositories && \ + DEBIAN_FRONTEND="noninteractive" apt-get -y install \ + tzdata \ + gcc \ + g++ \ + wget \ + libfl-dev \ + flex \ + bison \ + libboost-all-dev \ + automake \ + make \ + cmake \ + iputils-ping \ + build-essential \ + libtool \ + fuse \ + libfuse-dev \ + zlib1g-dev + +RUN cd /rcssserver && \ + find . -type f -name "*.cpp" -exec sed -i 's/#include /#include /g' {} \; && \ + find . -type f -name "*.h" -exec sed -i 's/#include /#include /g' {} \; && \ + find . -type f -name "*.hpp" -exec sed -i 's/#include /#include /g' {} \; && \ + find . -type f -name "*.cpp" -exec sed -i 's/std::filesystem/std::experimental::filesystem/g' {} \; && \ + find . -type f -name "*.h" -exec sed -i 's/std::filesystem/std::experimental::filesystem/g' {} \; && \ + find . -type f -name "*.hpp" -exec sed -i 's/std::filesystem/std::experimental::filesystem/g' {} \; && \ + mkdir build && \ + cd build && \ + cmake .. && \ + make && \ + cd .. \ No newline at end of file diff --git a/utils/appimage/Dockerfile.builder-2004 b/utils/appimage/Dockerfile.builder-2004 new file mode 100644 index 00000000..91035f26 --- /dev/null +++ b/utils/appimage/Dockerfile.builder-2004 @@ -0,0 +1,30 @@ +FROM ubuntu:20.04 + +COPY . /rcssserver + +RUN apt-get clean && apt-get update --allow-insecure-repositories && \ + DEBIAN_FRONTEND="noninteractive" apt-get -y install \ + tzdata \ + gcc \ + g++ \ + wget \ + libfl-dev \ + flex \ + bison \ + libboost-all-dev \ + automake \ + make \ + cmake \ + iputils-ping \ + build-essential \ + libtool \ + fuse \ + libfuse-dev \ + zlib1g-dev + +RUN cd /rcssserver && \ + mkdir build && \ + cd build && \ + cmake .. && \ + make && \ + cd .. diff --git a/utils/appimage/Dockerfile.builder-2404 b/utils/appimage/Dockerfile.builder-2404 new file mode 100644 index 00000000..73de5c1d --- /dev/null +++ b/utils/appimage/Dockerfile.builder-2404 @@ -0,0 +1,24 @@ +FROM ubuntu:24.04 + +COPY . /rcssserver + +RUN apt-get clean && apt-get update --allow-insecure-repositories && \ + DEBIAN_FRONTEND="noninteractive" apt-get -y install \ + tzdata \ + gcc \ + g++ \ + wget \ + libfl-dev \ + flex \ + bison \ + libboost-all-dev \ + automake \ + make \ + cmake \ + iputils-ping \ + build-essential \ + libtool \ + fuse \ + libfuse-dev + +RUN cd /rcssserver && ./utils/appimage/build_code.sh \ No newline at end of file diff --git a/utils/appimage/build_appimage.sh b/utils/appimage/build_appimage.sh new file mode 100755 index 00000000..6bd2b776 --- /dev/null +++ b/utils/appimage/build_appimage.sh @@ -0,0 +1,39 @@ +#!/bin/bash +set -e + +wget -c "https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage" -O linuxdeploy-x86_64.AppImage +chmod +x linuxdeploy-x86_64.AppImage +mkdir rcssserver-x86_64 + +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) +BUILD_PWD="${SCRIPT_DIR}/../../build" +APP_IMAGE_DIR="${SCRIPT_DIR}" + + +# find libc and libstdc++ libz dependencies +LIBSTDCPP_PATH=$(ldd $BUILD_PWD/rcssserver | grep libstdc++ | awk '{ print $3 }') +LIBZ_PATH=$(ldd $BUILD_PWD/rcssserver | grep libz.so | awk '{ print $3 }') +LIBRCSSCLANGPARSER_PATH=$(ldd $BUILD_PWD/rcssserver | grep librcssclangparser.so | awk '{ print $3 }') +LIBRCSSCONFPARSER_PATH=$(ldd $BUILD_PWD/rcssserver | grep librcssconfparser.so | awk '{ print $3 }') +LIBRCSSGZ_PATH=$(ldd $BUILD_PWD/rcssserver | grep librcssgz.so | awk '{ print $3 }') +LIBRCSSNET_PATH=$(ldd $BUILD_PWD/rcssserver | grep librcssnet.so | awk '{ print $3 }') + +echo "LIBSTDCPP_PATH=" $LIBSTDCPP_PATH +echo "LIBZ_PATH=" $LIBZ_PATH +echo "LIBRCSSCLANGPARSER_PATH=" $LIBRCSSCLANGPARSER_PATH +echo "LIBRCSSCONFPARSER_PATH=" $LIBRCSSCONFPARSER_PATH +echo "LIBRCSSGZ_PATH=" $LIBRCSSGZ_PATH +echo "LIBRCSSNET_PATH=" $LIBRCSSNET_PATH + +./linuxdeploy-x86_64.AppImage --appdir ./rcssserver-x86_64 \ + -e $BUILD_PWD/rcssserver \ + -l $LIBRCSSCLANGPARSER_PATH \ + -l $LIBRCSSCONFPARSER_PATH \ + -l $LIBRCSSGZ_PATH \ + -l $LIBRCSSNET_PATH \ + -l $LIBSTDCPP_PATH \ + -l $LIBZ_PATH \ + -d $APP_IMAGE_DIR/rcssserver.desktop \ + -i $APP_IMAGE_DIR/rcssserver.png \ + --output appimage +echo "App Image Created." diff --git a/utils/appimage/build_code.sh b/utils/appimage/build_code.sh new file mode 100755 index 00000000..01236968 --- /dev/null +++ b/utils/appimage/build_code.sh @@ -0,0 +1,8 @@ +#!/bin/bash +set -e + +mkdir build +cd build +cmake -DCMAKE_CXX_STANDARD=17 .. +make +cd .. \ No newline at end of file diff --git a/utils/appimage/rcssserver.desktop b/utils/appimage/rcssserver.desktop new file mode 100644 index 00000000..5d011484 --- /dev/null +++ b/utils/appimage/rcssserver.desktop @@ -0,0 +1,14 @@ +[Desktop Entry] +Version=1.0 +Type=Application +Name=rcssserver +Comment=Robocup 2D Soccer Simulation Server +TryExec=rcssserver +Exec=rcssserver +Icon=rcssserver +MimeType=image/x-foo; +Categories=Development; +X-KDE-Library=librcssserver +X-KDE-FactoryName=rcssserverfactory +X-KDE-ServiceType=RcssserverService + diff --git a/utils/appimage/rcssserver.png b/utils/appimage/rcssserver.png new file mode 100644 index 0000000000000000000000000000000000000000..2c29a89633552a123f3d7ce9005955acf698c498 GIT binary patch literal 25317 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 literal 0 HcmV?d00001 diff --git a/utils/docker/Dockerfile b/utils/docker/Dockerfile new file mode 100644 index 00000000..385d748b --- /dev/null +++ b/utils/docker/Dockerfile @@ -0,0 +1,59 @@ +#------------------------------------------------------ +# build stage +#------------------------------------------------------ + +FROM ubuntu:24.04 AS BUILD + +WORKDIR /rcssserver + +# set environment variables +ENV config_file=server.conf \ + DATE_FORMAT="%Y%m%d%H%M%S" \ + VERSION=18.1.3 + + +# install dependencies +RUN apt-get clean && apt-get update --allow-insecure-repositories && \ + DEBIAN_FRONTEND="noninteractive" apt-get -y install \ + tzdata \ + sudo \ + gcc \ + g++ \ + wget \ + flex \ + bison \ + libboost-all-dev \ + automake \ + make \ + cmake \ + iputils-ping + +# copy rcssserver source code +COPY . /rcssserver + +# make and install rcssserver +RUN cd /rcssserver/ \ + && ./bootstrap \ + && ./configure --prefix=`pwd`/server-bin \ + && make \ + && make install \ + && ldconfig + + + + +#------------------------------------------------------ +# run stage +#------------------------------------------------------ +FROM ubuntu:24.04 AS RUN + +ENV LD_LIBRARY_PATH=/app/server-bin/lib:/usr/local/lib:/usr/lib:/lib \ + PATH=/app/server-bin/bin:$PATH + +WORKDIR /app + +COPY --from=BUILD /rcssserver/server-bin /app/server-bin + +COPY utils/docker/docker-entrypoint.sh /app/docker-entrypoint.sh + +CMD [ "bash", "/app/docker-entrypoint.sh" ] \ No newline at end of file diff --git a/utils/docker/README.md b/utils/docker/README.md new file mode 100644 index 00000000..567ad942 --- /dev/null +++ b/utils/docker/README.md @@ -0,0 +1,43 @@ +# RoboCup Soccer Simulator Server +This image contains the RoboCup Soccer Simulator Server (rcssserver) installed and ready to use. + +## Tags +- latest + +## How to use this image + +Run the following command to start the server: +```bash +docker run --name rcssserver --network host -it rcssserver:latest +``` +Now you can connect to the server using the monitor or a client. + +## How to use custom configuration files +1. You can mount a volume with your custom configuration files, like: +```bash +docker run --name rcssserver --network host -v /path/to/your/configs:/root/.rcssserver -it rcssserver:latest +``` +2. You can add your custom configuration as environment variables, like: +```bash +docker run --name rcssserver --network host -e 'synch_mode=true' -it rcssserver:latest +``` +3. You can run server with custom command line arguments, like: +```bash +docker run --name rcssserver --network host -it rcssserver:latest rcssserver server::synch_mode=true + +``` + + +**Note**: You can either use one of the above methods at a time. +It means: +* if there is a server configuration file environment variable will be ignored. +* if you use third method, the second method will be ignored. + + + +## :incoming_envelope: Contributing + +For bug reports, feature requests and latest updates, please goto +https://github.com/rcsoccersim/rcssserver and open an issue or a pull request. + +> The RoboCup Soccer Server Maintainance Group diff --git a/utils/docker/docker-entrypoint.sh b/utils/docker/docker-entrypoint.sh new file mode 100755 index 00000000..f6955e3a --- /dev/null +++ b/utils/docker/docker-entrypoint.sh @@ -0,0 +1,237 @@ +#!/bin/env bash + +SERVER_CONFIG_FOLDER='/root/.rcssserver' +LOGS_FOLDER='/root/rcssserver-logs' + +mkdir -p ${LOGS_FOLDER} + +SERVER_OPTIONS=( + 'catch_ban_cycle' '' + 'clang_advice_win' '' + 'clang_define_win' '' + 'clang_del_win' '' + 'clang_info_win' '' + 'clang_mess_delay' '' + 'clang_mess_per_cycle' '' + 'clang_meta_win' '' + 'clang_rule_win' '' + 'clang_win_size' '' + 'coach_port' '' + 'connect_wait' '' + 'drop_ball_time' '' + 'extra_half_time' '' + 'foul_cycles' '' + 'freeform_send_period' '' + 'freeform_wait_period' '' + 'game_log_compression' '' + 'game_log_version' '' + 'game_over_wait' '' + 'goalie_max_moves' '' + 'half_time' '' + 'hear_decay' '' + 'hear_inc' '' + 'hear_max' '' + 'illegal_defense_duration' '' + 'illegal_defense_number' '' + 'keepaway_start' '' + 'kick_off_wait' '' + 'max_goal_kicks' '' + 'max_monitors' '' + 'nr_extra_halfs' '' + 'nr_normal_halfs' '' + 'olcoach_port' '' + 'pen_before_setup_wait' '' + 'pen_max_extra_kicks' '' + 'pen_nr_kicks' '' + 'pen_ready_wait' '' + 'pen_setup_wait' '' + 'pen_taken_wait' '' + 'point_to_ban' '' + 'point_to_duration' '' + 'port' '' + 'recv_step' '' + 'say_coach_cnt_max' '' + 'say_coach_msg_size' '' + 'say_msg_size' '' + 'send_step' '' + 'send_vi_step' '' + 'sense_body_step' '' + 'simulator_step' '' + 'slow_down_factor' '' + 'start_goal_l' '' + 'start_goal_r' '' + 'synch_micro_sleep' '' + 'synch_offset' '' + 'synch_see_offset' '' + 'tackle_cycles' '' + 'text_log_compression' '' + 'auto_mode' '' + 'back_passes' '' + 'coach' '' + 'coach_w_referee' '' + 'forbid_kick_off_offside' '' + 'free_kick_faults' '' + 'fullstate_l' '' + 'fullstate_r' '' + 'game_log_dated' '' + 'game_log_fixed' '' + 'game_logging' '' + 'golden_goal' '' + 'keepaway' '' + 'keepaway_log_dated' '' + 'keepaway_log_fixed' '' + 'keepaway_logging' '' + 'log_times' '' + 'old_coach_hear' '' + 'pen_allow_mult_kicks' '' + 'pen_coach_moves_players' '' + 'pen_random_winner' '' + 'penalty_shoot_outs' '' + 'profile' '' + 'proper_goal_kicks' '' + 'record_messages' '' + 'send_comms' '' + 'synch_mode' '' + 'team_actuator_noise' '' + 'text_log_dated' '' + 'text_log_fixed' '' + 'text_logging' '' + 'use_offside' '' + 'verbose' '' + 'wind_none' '' + 'wind_random' '' + 'audio_cut_dist' '' + 'back_dash_rate' '' + 'ball_accel_max' '' + 'ball_decay' '' + 'ball_rand' '' + 'ball_size' '' + 'ball_speed_max' '' + 'ball_stuck_area' '' + 'ball_weight' '' + 'catch_probability' '' + 'catchable_area_l' '' + 'catchable_area_w' '' + 'ckick_margin' '' + 'control_radius' '' + 'dash_angle_step' '' + 'dash_power_rate' '' + 'effort_dec' '' + 'effort_dec_thr' '' + 'effort_inc' '' + 'effort_inc_thr' '' + 'effort_init' '' + 'effort_min' '' + 'extra_stamina' '' + 'foul_detect_probability' '' + 'foul_exponent' '' + 'goal_width' '' + 'illegal_defense_dist_x' '' + 'illegal_defense_width' '' + 'inertia_moment' '' + 'keepaway_length' '' + 'keepaway_width' '' + 'kick_power_rate' '' + 'kick_rand' '' + 'kick_rand_factor_l' '' + 'kick_rand_factor_r' '' + 'kickable_margin' '' + 'max_back_tackle_power' '' + 'max_catch_angle' '' + 'max_dash_angle' '' + 'max_dash_power' '' + 'max_tackle_power' '' + 'maxmoment' '' + 'maxneckang' '' + 'maxneckmoment' '' + 'maxpower' '' + 'min_catch_angle' '' + 'min_dash_angle' '' + 'min_dash_power' '' + 'minmoment' '' + 'minneckang' '' + 'minneckmoment' '' + 'minpower' '' + 'offside_active_area_size' '' + 'offside_kick_margin' '' + 'pen_dist_x' '' + 'pen_max_goalie_dist_x' '' + 'player_accel_max' '' + 'player_decay' '' + 'player_rand' '' + 'player_size' '' + 'player_speed_max' '' + 'player_speed_max_min' '' + 'player_weight' '' + 'prand_factor_l' '' + 'prand_factor_r' '' + 'quantize_step' '' + 'quantize_step_l' '' + 'recover_dec' '' + 'recover_dec_thr' '' + 'recover_init' '' + 'recover_min' '' + 'red_card_probability' '' + 'side_dash_rate' '' + 'slowness_on_top_for_left_team' '' + 'slowness_on_top_for_right_team' '' + 'stamina_capacity' '' + 'stamina_inc_max' '' + 'stamina_max' '' + 'stopped_ball_vel' '' + 'tackle_back_dist' '' + 'tackle_dist' '' + 'tackle_exponent' '' + 'tackle_power_rate' '' + 'tackle_rand_factor' '' + 'tackle_width' '' + 'visible_angle' '' + 'visible_distance' '' + 'wind_ang' '' + 'wind_dir' '' + 'wind_force' '' + 'wind_rand' '' + 'coach_msg_file' '' + 'fixed_teamname_l' '' + 'fixed_teamname_r' '' + 'game_log_dir' "${LOGS_FOLDER}" + 'game_log_fixed_name' '' + 'keepaway_log_dir' "${LOGS_FOLDER}" + 'keepaway_log_fixed_name' '' + 'landmark_file' '' + 'log_date_format' '' + 'team_l_start' '' + 'team_r_start' '' + 'text_log_dir' "${LOGS_FOLDER}" + 'text_log_fixed_name' '' +) + +# First Config Priority : Server Config files +# if server config does exist then run with it +if [ -f "${SERVER_CONFIG_FOLDER}/server.conf" ]; then + rcssserver + exit 0 +fi + +# Second Config Priority : Environment Variables +# if environment variables are set then run with them +# loop through the default values if they are in the environment variable change the array value +for ((i=0; i<${#SERVER_OPTIONS[@]}; i+=2)); do + if [ -n "${!SERVER_OPTIONS[i]}" ]; then + SERVER_OPTIONS[i+1]="${!SERVER_OPTIONS[i]}" + echo "ENV Loaded ${SERVER_OPTIONS[i]}=${SERVER_OPTIONS[i+1]}" + fi +done + +# run server with options +opt="" +for ((i=0; i<${#SERVER_OPTIONS[@]}; i+=2)); do + if [ -n "${SERVER_OPTIONS[i+1]}" ]; then + opt="${opt} server::${SERVER_OPTIONS[i]}=${SERVER_OPTIONS[i+1]}" + fi +done + +echo "Running server with options: ${opt}" +rcssserver ${opt} + + From e057fde5b5f15c00fa0e0a6811e8928b2bdae920 Mon Sep 17 00:00:00 2001 From: Alireza Sadraii Rad Date: Tue, 23 Apr 2024 00:05:21 +0200 Subject: [PATCH 02/11] add artifact --- .github/workflows/main.yml | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 081b8581..8e9d0801 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -85,11 +85,21 @@ jobs: path: ${{ github.workspace }}/artifact/* retention-days: 5 + - name: Check if there is no release with the same tag + id: check_release + run: | + curl -s -o /dev/null -w "%{http_code}" https://api.github.com/repos/${{ github.repository }}/releases/tags/${{ github.ref_name }} -u ${{ secrets.GITHUB_TOKEN }}: + echo "::set-output name=release_exists::${{ steps.check_release.outputs.stdout }}" # ------------------------------------------- Release - - uses: ncipollo/release-action@v1 - if: startsWith(github.ref, 'refs/tags/') + - name: Create Release + id: create_release + uses: ncipollo/release-action@v1 + if: steps.check_release.outputs.release_exists == '404' with: artifacts: "${{ github.workspace }}/artifact/*" token: ${{ secrets.GITHUB_TOKEN }} - # tag text is like "v1.2.3" so we need to remove the "v" from the tag tag: "${{ github.ref_name }}" + release_name: "${{ github.ref_name }}" + release_body: "RoboCup Soccer Simulator Server" + draft: false + prerelease: false From 32aaebda4a640d8e86018f15c0547693d1ce0a34 Mon Sep 17 00:00:00 2001 From: Alireza Sadraii Rad Date: Tue, 23 Apr 2024 00:23:11 +0200 Subject: [PATCH 03/11] test dockerfile --- utils/docker/Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/utils/docker/Dockerfile b/utils/docker/Dockerfile index 385d748b..62b9dd11 100644 --- a/utils/docker/Dockerfile +++ b/utils/docker/Dockerfile @@ -52,6 +52,7 @@ ENV LD_LIBRARY_PATH=/app/server-bin/lib:/usr/local/lib:/usr/lib:/lib \ WORKDIR /app + COPY --from=BUILD /rcssserver/server-bin /app/server-bin COPY utils/docker/docker-entrypoint.sh /app/docker-entrypoint.sh From b5a75630f997ede8a4177676dc47736eef9d0485 Mon Sep 17 00:00:00 2001 From: Alireza Sadraii Rad Date: Tue, 23 Apr 2024 00:46:25 +0200 Subject: [PATCH 04/11] update pipeline --- .github/workflows/main.yml | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 8e9d0801..a55d71b8 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -15,7 +15,6 @@ jobs: docker: runs-on: ubuntu-latest name: Build & Push Docker - if: startsWith(github.ref, 'refs/tags/') steps: - name: Checkout uses: actions/checkout@v4 @@ -32,6 +31,17 @@ jobs: cmake_version=$(grep -oP 'project\(.* VERSION \K[0-9]+\.[0-9]+\.[0-9]+' CMakeLists.txt) echo "::set-output name=version::${cmake_version}" + - name: Check if the version tag exist git then skip + id: check_tag + run: | + git tag -l | grep -q "${{ steps.cmake_version.outputs.version }}" && echo "Tag already exists" && exit 1 || echo "Tag does not exist" + continue-on-error: true + + - name: tag the version + if: steps.check_tag.outcome == 'success' + run: | + git tag -a "${{ steps.cmake_version.outputs.version }}" -m "Version ${{ steps.cmake_version.outputs.version }}" + git push origin "${{ steps.cmake_version.outputs.version }}" - name: Login to Docker Hub uses: docker/login-action@v3 @@ -45,7 +55,7 @@ jobs: context: . file: ./utils/docker/Dockerfile push: true - tags: "${{ env.BASE_IMAGE }}:latest,${{ env.BASE_IMAGE }}:ubuntu-24-${{ github.ref_name }}-${{ steps.cmake_version.outputs.version }}" + tags: "${{ env.BASE_IMAGE }}:latest,${{ env.BASE_IMAGE }}:ubuntu-24-${{ steps.cmake_version.outputs.version }}" - name: Docker Hub Description uses: peter-evans/dockerhub-description@v4 @@ -66,6 +76,12 @@ jobs: run: | mkdir -p ${{ github.workspace }}/artifact + - name: Find CMakeLists.txt version + id: cmake_version + run: | + cmake_version=$(grep -oP 'project\(.* VERSION \K[0-9]+\.[0-9]+\.[0-9]+' CMakeLists.txt) + echo "::set-output name=version::${cmake_version}" + # ------------------------------------------- Ubuntu 20.04 AppImage - name: Prepare builder image for 20.04 run: | @@ -75,7 +91,7 @@ jobs: run: | docker run --privileged --name builder-2004 \ builder-image:2004 /rcssserver/utils/appimage/build_appimage.sh - docker cp builder-2004:/rcssserver-x86_64.AppImage ${{ github.workspace }}/artifact/rcssserver-x86_64-2004.AppImage + docker cp builder-2004:/rcssserver-x86_64.AppImage ${{ github.workspace }}/artifact/rcssserver-x86_64-${{ steps.cmake_version.outputs.version }}.AppImage # ------------------------------------------- Artifact - name: Upload Artifact @@ -90,6 +106,7 @@ jobs: run: | curl -s -o /dev/null -w "%{http_code}" https://api.github.com/repos/${{ github.repository }}/releases/tags/${{ github.ref_name }} -u ${{ secrets.GITHUB_TOKEN }}: echo "::set-output name=release_exists::${{ steps.check_release.outputs.stdout }}" + # ------------------------------------------- Release - name: Create Release id: create_release From 8db68e5bb0adf4f116a9f090fac19d2d02771260 Mon Sep 17 00:00:00 2001 From: Alireza Sadraii Rad Date: Tue, 23 Apr 2024 00:51:36 +0200 Subject: [PATCH 05/11] add git name to build --- .github/workflows/main.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index a55d71b8..a4b94bcb 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -40,6 +40,8 @@ jobs: - name: tag the version if: steps.check_tag.outcome == 'success' run: | + git config --global user.email "action@github.com" + git config --global user.name "GitHub Action" git tag -a "${{ steps.cmake_version.outputs.version }}" -m "Version ${{ steps.cmake_version.outputs.version }}" git push origin "${{ steps.cmake_version.outputs.version }}" @@ -106,7 +108,7 @@ jobs: run: | curl -s -o /dev/null -w "%{http_code}" https://api.github.com/repos/${{ github.repository }}/releases/tags/${{ github.ref_name }} -u ${{ secrets.GITHUB_TOKEN }}: echo "::set-output name=release_exists::${{ steps.check_release.outputs.stdout }}" - + # ------------------------------------------- Release - name: Create Release id: create_release From 0822a0ac7e5f2c598dec6d9e2c46d24d90094091 Mon Sep 17 00:00:00 2001 From: Nader Zare Date: Mon, 22 Apr 2024 22:32:16 -0300 Subject: [PATCH 06/11] Update main.yml --- .github/workflows/main.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index a4b94bcb..5b6cf362 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,11 +1,13 @@ name: ci on: + workflow_dispatch: push: branches: - "master" tags: - "*" + env: BASE_IMAGE: crosslanguagesoccerframework/rcssserver From 842d7cb02042a1acd9bb0917ecbaf2b21c22ed8b Mon Sep 17 00:00:00 2001 From: Nader Zare Date: Mon, 22 Apr 2024 22:56:04 -0300 Subject: [PATCH 07/11] Update main.yml --- .github/workflows/main.yml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 5b6cf362..550b7c6a 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -104,12 +104,15 @@ jobs: name: rcssserver-x86_64 path: ${{ github.workspace }}/artifact/* retention-days: 5 - + + - name: List files in artifact directory + run: ls -l ${{ github.workspace }}/artifact/ + - name: Check if there is no release with the same tag id: check_release run: | - curl -s -o /dev/null -w "%{http_code}" https://api.github.com/repos/${{ github.repository }}/releases/tags/${{ github.ref_name }} -u ${{ secrets.GITHUB_TOKEN }}: - echo "::set-output name=release_exists::${{ steps.check_release.outputs.stdout }}" + result=$(curl -s -o /dev/null -w "%{http_code}" https://api.github.com/repos/${{ github.repository }}/releases/tags/${{ github.ref_name }} -u ${{ secrets.GITHUB_TOKEN }}) + echo "::set-output name=release_exists::$result" # ------------------------------------------- Release - name: Create Release From 10507b05f16e070923aca069e336d56c643e686c Mon Sep 17 00:00:00 2001 From: Nader Zare Date: Mon, 22 Apr 2024 23:18:08 -0300 Subject: [PATCH 08/11] Update main.yml --- .github/workflows/main.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 550b7c6a..03c13861 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -122,8 +122,8 @@ jobs: with: artifacts: "${{ github.workspace }}/artifact/*" token: ${{ secrets.GITHUB_TOKEN }} - tag: "${{ github.ref_name }}" - release_name: "${{ github.ref_name }}" + tag: "${{ steps.cmake_version.outputs.version }}" + release_name: "${{ steps.cmake_version.outputs.version }}" release_body: "RoboCup Soccer Simulator Server" draft: false prerelease: false From dc6e4d0f810d94d55d0002c56a006f2260269ba7 Mon Sep 17 00:00:00 2001 From: Nader Zare Date: Tue, 23 Apr 2024 00:03:52 -0300 Subject: [PATCH 09/11] Update README.md --- README.md | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 0c7db2c5..887a7528 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,35 @@ The RoboCup Soccer Simulator Server (rcssserver) is a research and educational t For further reading, please check [the user's manual](https://rcsoccersim.readthedocs.io/). -## :soccer: Quick Start +There are three different solutions to run the RoboCup Soccer Simulator Server. +- Download the AppImage release and run (Linux, Windows WSL) +- Build from source and run (Linux, Windows WSL) +- Use Docker Image + +## :gift_heart: AppImage +#### Download AppImage +Download "rcssserver-x86_64-?.?.?.AppImage" from the (release page)[https://github.com/CLSFramework/rcssserver/releases] / latest version +or use the below command to download the latest version of AppImage: +```bash +wget $(curl -s https://api.github.com/repos/clsframework/rcssserver/releases/latest | grep -oP '"browser_download_url": "\K(.*rcssserver-x86_64-.*\.AppImage)' | head -n 1) +``` + +#### Install dependency and update permission + +then you need to update the permission of the AppImage and install fuse: +```bash +chmod +x rcssserver-x86_64-*.AppImage +sudo apt-get install fuse +``` + +#### Run + +to run the AppImage: +```bash +./rcssserver-x86_64-?.?.?.AppImage +``` + +## :soccer: Build From Source rcssserver is implemented by C++14 and depends some libraries. Make sure you have the required dependencies installed on your system: From 589a771419ed3a3f547de26b3292cd10389ac20a Mon Sep 17 00:00:00 2001 From: Nader Zare Date: Tue, 23 Apr 2024 00:10:41 -0300 Subject: [PATCH 10/11] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 887a7528..416b4da1 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# RoboCup Soccer Simulator Server +# :soccer: RoboCup Soccer Simulator Server [![CircleCI](https://circleci.com/gh/rcsoccersim/rcssserver/tree/master.svg?style=svg)](https://circleci.com/gh/rcsoccersim/rcssserver/tree/master) ![License](https://img.shields.io/github/license/rcsoccersim/rcssserver.svg) @@ -37,7 +37,7 @@ to run the AppImage: ./rcssserver-x86_64-?.?.?.AppImage ``` -## :soccer: Build From Source +## :wrench: Build From Source rcssserver is implemented by C++14 and depends some libraries. Make sure you have the required dependencies installed on your system: From f8ec368bfea450a59b9d363f2f48260271033864 Mon Sep 17 00:00:00 2001 From: Nader Zare Date: Tue, 23 Apr 2024 00:12:49 -0300 Subject: [PATCH 11/11] Update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 416b4da1..3ef9acb2 100644 --- a/README.md +++ b/README.md @@ -26,8 +26,9 @@ wget $(curl -s https://api.github.com/repos/clsframework/rcssserver/releases/lat then you need to update the permission of the AppImage and install fuse: ```bash -chmod +x rcssserver-x86_64-*.AppImage +sudo apt update sudo apt-get install fuse +chmod +x rcssserver-x86_64-*.AppImage ``` #### Run