diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 71f22006c..c75ec9b2c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,47 +1,68 @@ -name: Build +name: Build Progs Artifacts on: + workflow_dispatch: + inputs: + reason: + description: "Reason for running" + required: false + default: "Manual check" push: jobs: - build: - + build-artifacts: runs-on: ubuntu-latest - steps: - - - name: Checkout + - name: Checkout Repository uses: actions/checkout@v4 + with: + # Create partial clone + # See: https://git-scm.com/docs/git-rev-list#Documentation/git-rev-list.txt---filterfilter-spec + filter: blob:none + submodules: false + fetch-depth: 0 + fetch-tags: true + + - name: Initialize xonotic submodule + # Create a small clone, with full history to improve workflow speed. + # For example, original size of xonotic-data.pk3dir is ~4GB + # with: git submodules update --init --filter=blob:none xonotic + # The size is reduced to ~700MB + # https://git-scm.com/docs/git-rev-list#Documentation/git-rev-list.txt---filterfilter-spec + run: git submodule update --init --filter=blob:none xonotic + + - name: Get gmqcc Commit ID + id: get-gmqcc-commit-id + run: echo "GMQCC_SHA=$(git rev-parse :gmqcc)" >> "$GITHUB_OUTPUT" + + - name: Cache gmqcc Binary + id: cache-gmqcc + uses: actions/cache@v4 + with: + path: gmqcc/gmqcc + key: ${{ runner.os }}-gmqcc-bin-${{ steps.get-gmqcc-commit-id.outputs.GMQCC_SHA }} + + - if: steps.cache-gmqcc.outputs.cache-hit != 'true' + name: Initialize gmqcc submodule + run: git submodule update --init --filter=blob:none gmqcc + + - if: steps.cache-gmqcc.outputs.cache-hit != 'true' + name: Compile gmqcc Binary + run: make -C gmqcc -j$(nproc) + + - name: Build Progs + run: ./build.sh -a - - name: Prepare - run: ./update.sh - env: - CI: true - ARCHIVE: 1 - - - name: Build - run: ./build.sh - env: - TERM: xterm - ARCHIVE: 1 - - - name: Set artifact name + - name: Generate Artifact Name run: | - git fetch --tags - echo "ARTIFACT_NAME=progs-$(git describe --tags --dirty='~' --always)" >> $GITHUB_ENV + CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD) + VERSION_TAG=$(git describe --tags --dirty="~" --always) + echo "CURRENT_BRANCH=${CURRENT_BRANCH}" >> "$GITHUB_ENV" + echo "VERSION_TAG=${VERSION_TAG}" >> "$GITHUB_ENV" + echo "ARTIFACT_NAME=progs-${CURRENT_BRANCH}-${VERSION_TAG}" >> "$GITHUB_ENV" - - name: Store artifacts - uses: actions/upload-artifact@v4 + # Upload the files in build folder + - name: Upload Artifacts + uses: actions/upload-artifact@v7 with: name: ${{ env.ARTIFACT_NAME }} - path: | - compiled/* - if-no-files-found: error - # retention-days: 14 - - - name: Publish a release - if: startsWith(github.ref, 'refs/tags/') - uses: softprops/action-gh-release@v2 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - files: | - compiled/* + path: build/${{ env.CURRENT_BRANCH }} diff --git a/.github/workflows/daily.yml b/.github/workflows/daily.yml index a80ecdcd2..0f01b9bcb 100644 --- a/.github/workflows/daily.yml +++ b/.github/workflows/daily.yml @@ -1,31 +1,72 @@ -name: QC Master Daily +name: Test Build Against QC Master Daily on: schedule: - - cron: '19 0 * * *' + - cron: "19 0 * * *" workflow_dispatch: + inputs: + reason: + description: "Reason for Running" + required: false + default: "Manual Check" jobs: - qc-master-daily: - + test-build-artifacts: runs-on: ubuntu-latest - steps: - - - name: Checkout + - name: Checkout Repository uses: actions/checkout@v4 + with: + # Create partial clone + # See: https://git-scm.com/docs/git-rev-list#Documentation/git-rev-list.txt---filterfilter-spec + filter: blob:none + submodules: false + fetch-depth: 0 + fetch-tags: true - - name: Prepare - run: ./update.sh - env: - CI: true - ARCHIVE: 1 - - - name: Checkout xonotic-data master + - name: Initialize xonotic submodule + # Create a small clone, with full history to improve workflow speed. + # For example, original size of xonotic-data.pk3dir is ~4GB + # with: git submodules update --init --filter=blob:none xonotic + # The size is reduced to ~700MB + # https://git-scm.com/docs/git-rev-list#Documentation/git-rev-list.txt---filterfilter-spec run: | + git submodule update --init --filter=blob:none xonotic git -C xonotic checkout master + git -C xonotic pull origin master + + - name: Get gmqcc Commit ID + id: get-gmqcc-commit-id + run: echo "GMQCC_SHA=$(git rev-parse :gmqcc)" >> "$GITHUB_OUTPUT" + + - name: Cache gmqcc Binary + id: cache-gmqcc + uses: actions/cache@v4 + with: + path: gmqcc/gmqcc + key: ${{ runner.os }}-gmqcc-bin-${{ steps.get-gmqcc-commit-id.outputs.GMQCC_SHA }} + + - if: steps.cache-gmqcc.outputs.cache-hit != 'true' + name: Initialize gmqcc submodule + run: git submodule update --init --filter=blob:none gmqcc + + - if: steps.cache-gmqcc.outputs.cache-hit != 'true' + name: Compile gmqcc Binary + run: make -C gmqcc -j$(nproc) + + - name: Build Progs + run: ./build.sh -a - - name: Build - run: ./build.sh - env: - TERM: xterm - ARCHIVE: 1 + # - name: Generate Artifact Name + # run: | + # CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD) + # VERSION_TAG=$(git describe --tags --dirty="~" --always) + # echo "CURRENT_BRANCH=${CURRENT_BRANCH}" >> "$GITHUB_ENV" + # echo "VERSION_TAG=${VERSION_TAG}" >> "$GITHUB_ENV" + # echo "ARTIFACT_NAME=progs-${CURRENT_BRANCH}-${VERSION_TAG}" >> "$GITHUB_ENV" + # + # # Upload the files in build folder + # - name: Upload Artifacts + # uses: actions/upload-artifact@v7 + # with: + # name: ${{ env.ARTIFACT_NAME }} + # path: build/${{ env.CURRENT_BRANCH }} diff --git a/.gitignore b/.gitignore index 0ebc74bfc..af83a810a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,3 @@ -compiled/ -gmqcc/ -*.dat -*.lno +build/ .cache/ .DS_Store diff --git a/.gitmodules b/.gitmodules index 23fe43be3..770d3127f 100644 --- a/.gitmodules +++ b/.gitmodules @@ -2,3 +2,6 @@ path = xonotic url = https://gitlab.com/smbxon/xonotic-data.pk3dir.git branch = main +[submodule "gmqcc"] + path = gmqcc + url = https://gitlab.com/xonotic/gmqcc.git diff --git a/build.sh b/build.sh index 692980d92..051b8856b 100755 --- a/build.sh +++ b/build.sh @@ -1,60 +1,160 @@ #!/usr/bin/env bash -if [ -n "${ZIP:-}" ]; then - tput bold; tput setaf 3; echo "WARNING: Processing without compression..."; tput sgr0 + +TARGET_ALL=0 +CLEAN_BUILD=0 +MAKE_TARGETS=("qc") +FILTER_FLAGS="--filter=blob:none" + +if [[ "$CI" == "true" ]]; then + INIT_SUBMODULES=0 +else + INIT_SUBMODULES=1 fi -if [ -e $(dirname "$0")/compiled/csprogs.dat -o -e $(dirname "$0")/compiled/menu.dat -o -e $(dirname "$0")/compiled/progs.dat -o -e $(dirname "$0")/compiled/csprogs.lno -o -e $(dirname "$0")/compiled/menu.lno -o -e $(dirname "$0")/compiled/progs.lno -o -e $(dirname "$0")/compiled/*.pk3 -o -e $(dirname "$0")/csprogs.dat -o -e $(dirname "$0")/menu.dat -o -e $(dirname "$0")/progs.dat -o -e $(dirname "$0")/csprogs.lno -o -e $(dirname "$0")/menu.lno -o -e $(dirname "$0")/progs.lno ]; then - tput bold; tput setaf 3; echo "There are compiled files here. The operation will proceed to delete the current compiled files in and out of the 'compiled' directory, replace and get new compiled ones (*.dat, *.lno, and *.pk3 files will be removed)." - # deletes any remaining compiled files that weren't moved to 'compiled' directory - tput bold; tput setaf 1 +set -eu + +usage() { + echo "build.sh [-c|--clean] [-a|-all] [-nf|--no-filter] [-ni|--no-init] [-h|--help]" + echo + echo " -c | --clean Remove compiled .dat and .pk3 file before rebuilding." + echo " -a | --all Build both qc and pk3 targets." + echo " -h | --help Show this message." + echo " -nf | --no-filter Don't use --filter flag when initializing submodules." + echo " -ni | --no-init Skip initializing submodules, manual initialization." + echo + echo "NOTE: Default target is 'qc' only." +} + +# Filter repeating arguments. +# Who would pass same arguments multiple times tho?! +if [[ $# -gt 0 ]]; then + readarray -t arguments < <(printf '%s\n' "$@" | sort -u) +else + # No arguments were provided + arguments=() +fi - rm -vf $(dirname "$0")/*.dat - rm -vf $(dirname "$0")/*.lno - rm -vf $(dirname "$0")/*.pk3 +# Parse CLI arguments +for i in "${arguments[@]}"; do + case $i in + -a | --all) + TARGET_ALL=1 + MAKE_TARGETS+=("pk3") + ;; + -c | --clean) + CLEAN_BUILD=1 + ;; + -h | --help) + usage + exit 0 + ;; + -ni | --no-init) + INIT_SUBMODULES=0 + ;; + -nf | --no-filter) + FILTER_FLAGS="" + ;; + *) + echo "Unknown flag: '$i' ... aborting" + exit 1 + ;; + esac +done - rm -vf $(dirname "$0")/compiled/*.dat - rm -vf $(dirname "$0")/compiled/*.lno - rm -vf $(dirname "$0")/compiled/*.pk3 +cd "${0%/*}" - tput sgr0 +if ! CURRENT_BRANCH="$(git rev-parse --abbrev-ref HEAD)"; then + echo "=> Failed to parse git branch name... aborting" + exit 1 +else + echo "=> Current Branch is ${CURRENT_BRANCH}" fi -cd ${0%[\\/]*} -set -eu +submodule_gmqcc_status=$(git submodule status gmqcc | awk '{ print $1 }') +if ((INIT_SUBMODULES == 1)); then + if [[ "${submodule_gmqcc_status:0:1}" == "+" || "${submodule_gmqcc_status:0:1}" == "-" ]]; then + echo "=> Submodule gmqcc not initialized... (commit: ${submodule_gmqcc_status})" + if ! git submodule update --init $FILTER_FLAGS gmqcc; then + echo " -> Failed to initialize gmqcc submodule... aborting" + exit 1 + fi + else + echo "=> Submodule gmqcc already initialized. (commit: ${submodule_gmqcc_status})" + fi +else + echo "=> Skipping gmqcc initialization... (commit: ${submodule_gmqcc_status})" +fi -declare base=xonotic -if [ ! -d "$base" ]; then - echo "RTFM (README.md)" +if [[ ! -f "gmqcc/gmqcc" ]]; then + echo "=> Building gmqcc..." + if ! make -C gmqcc -j"$(nproc)"; then + echo " -> Failed to build gmqcc... aborting" exit 1 + fi +else + echo "=> Using existing gmqcc binary (VERSION: $(gmqcc/gmqcc --version))" fi -: ${PROGS_OUT:=$PWD} -export PROGS_OUT +if [[ ! -d "build/${CURRENT_BRANCH}" ]]; then + echo "=> Creating build directory... (build/${CURRENT_BRANCH})" + if ! mkdir -p "build/${CURRENT_BRANCH}"; then + echo " -> Could not create build directory... aborting" + exit 1 + fi +fi -: ${QCC:=$PWD/gmqcc/gmqcc} -export QCC +submodule_xonotic_status=$(git submodule status xonotic | awk '{ print $1 }') +if ((INIT_SUBMODULES == 1)); then + if [[ "${submodule_xonotic_status:0:1}" == "+" || "${submodule_xonotic_status:0:1}" == "-" ]]; then + echo "=> Submodule xonotic not initialized... (commit: ${submodule_xonotic_status})" + if ! git submodule update --init $FILTER_FLAGS xonotic; then + echo " -> Failed to initialize xonotic submodule... aborting" + exit 1 + fi + else + echo "=> Submodule xonotic already initialized. (commit: ${submodule_xonotic_status})" + fi +else + echo "=> Skipping xonotic submodule initialization... (commit: ${submodule_xonotic_status})" +fi -export QCCFLAGS_WATERMARK=$(git describe --tags --dirty='~' --always) +export XONOTIC=${XONOTIC:-1} +export QCC=${QCC:-"$(pwd)/gmqcc/gmqcc"} -relpath() { - b=; s=$(cd $(readlink -f ${1%%/}); pwd); d=$(cd $2; pwd) - while [ "${d#$s/}" == "${d}" ]; do s=$(dirname ${s}); b="../${b}"; done - echo ${b}${d#${s}/} -} +if ! WATERMARK="$(git describe --tags --dirty='~' --always)"; then + echo "-> Error: Failed to generate QCCFLAGS_WATERMARK... aborting" + exit 1 +else + echo "=> Version tag is: ${WATERMARK}" +fi +export QCCFLAGS_WATERMARK="${WATERMARK}" +export PROGS_OUT=${PROGS_OUT:-"$(pwd)/build/${CURRENT_BRANCH}"} -export BUILD_MOD="$(relpath $base/qcsrc $PWD)" -export XONOTIC=1 -make -C ${base} +if ! TMP_MOD="$(realpath --relative-to=xonotic/qcsrc "$(pwd)")"; then + echo "-> Error: could not calculate BUILD_MOD... aborting" + exit 1 +fi -tput bold; tput setaf 2; echo "Compiled successfully!"; tput sgr0 -mkdir -vp $(dirname "$0")/compiled -mv -v *.lno $(dirname "$0")/compiled -mv -v *.dat $(dirname "$0")/compiled +if [[ -z "$TMP_MOD" ]]; then + echo "TMP_MOD is empty! ... aborting" + exit 1 +fi -if [ -n "${ZIP:-}" ]; then - tput bold; tput setaf 3; echo "Done without compression."; tput sgr0 -else - cp -v $base/qcsrc/csprogs-*.pk3 ./compiled +export BUILD_MOD="${TMP_MOD}" + +if ((CLEAN_BUILD == 1)); then + echo "=> Cleaning old build artifacts in build/${CURRENT_BRANCH}" + make -C xonotic clean + rm -f "${PROGS_OUT}/"csprogs-*.pk3 fi -tput bold; tput setaf 3; echo "Now you can look at the compiled files inside $(dirname "$0")/compiled directory." +echo "=> Starting Compilation..." +if ! make -C xonotic "${MAKE_TARGETS[@]}"; then + echo " -> Modpack compilation failed... aborting" + exit 1 +else + if ((TARGET_ALL == 1)); then + cp xonotic/qcsrc/csprogs-*.pk3 "${PROGS_OUT}" + fi + exit 0 +fi diff --git a/gmqcc b/gmqcc new file mode 160000 index 000000000..b2a319efb --- /dev/null +++ b/gmqcc @@ -0,0 +1 @@ +Subproject commit b2a319efb41069b9a250e76991dbe505ff8d030d diff --git a/update.sh b/update.sh deleted file mode 100755 index 3fd829147..000000000 --- a/update.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/usr/bin/env bash -cd ${0%[\\/]*} -set -eu - -git fetch --tags -if [ -z "${CI-}" ]; then - git pull -fi - -git submodule update --init --depth 100 - -declare qccDir='gmqcc' -declare qccRepo='https://gitlab.com/xonotic/gmqcc.git' -declare qccBranch='main' - -#if [ -z "${CI-}" ]; then -# wget -P .cache -c https://github.com/MarioSMB/csprogs/raw/master/csprogs-$(git describe --tags --dirty=*).pk3 -#fi - -if [ ! -d "$qccDir" ]; then - git clone --depth=1 --branch=${qccBranch} ${qccRepo} ${qccDir} -else - pushd ${qccDir} && git pull - popd -fi - -pushd ${qccDir} && make -popd