diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 08b5a5e..a2c6aec 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -7,7 +7,7 @@ build-android: script: - export version="$CI_COMMIT_REF_NAME-$CI_COMMIT_SHORT_SHA" && echo "building version $version" - bash ./setup-ndk.sh - - bin/update && bin/apply && cd works/core + - bin/update && bin/apply-ci && cd works/core - git submodule update --init --recursive - git tag v$version -f - make lib_install diff --git a/bin/apply-ci b/bin/apply-ci new file mode 100755 index 0000000..5ab4236 --- /dev/null +++ b/bin/apply-ci @@ -0,0 +1,91 @@ +#!/bin/sh +set -e + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +ROOT="$(dirname "$SCRIPT_DIR")" +SING_BOX="$ROOT/works/sing-box" +PATCH_DIR="$ROOT/works/patch" +OUTPUT="$ROOT/works/core" +REV_FILE="$ROOT/works/rev" + +# defaults +REPO_URL="git@git.inker.bot:arknights/sing-box.git" +UPSTREAM_BRANCH="main" + +if [ ! -z "$CI_JOB_TOKEN" ]; then + git config --global user.name imabot + git config --global user.email ci@inker.bot + git config --global url."https://gitlab-ci-token:${CI_JOB_TOKEN}@git.inker.bot/".insteadOf "git@git.inker.bot:" +fi + +CONFIG="$ROOT/works/config" +if [ -f "$CONFIG" ]; then + . "$CONFIG" +fi + +# Clone if not present +if [ ! -d "$SING_BOX/.git" ]; then + echo "Cloning sing-box..." + if [ -n "$UPSTREAM_BRANCH" ]; then + git clone -b "$UPSTREAM_BRANCH" "$REPO_URL" "$SING_BOX" + else + git clone "$REPO_URL" "$SING_BOX" + fi +fi + +# Checkout stored rev +if [ -f "$REV_FILE" ]; then + REV="$(cat "$REV_FILE" | tr -d '[:space:]')" + echo "Checking out stored rev: $REV" + git -C "$SING_BOX" fetch --all + git -C "$SING_BOX" checkout "$REV" +else + echo "Warning: works/rev not found, using current HEAD." >&2 +fi + +echo "Initializing works/core/ from works/sing-box/ (retaining .git)..." +rm -rf "$OUTPUT" +cp -a "$SING_BOX" "$OUTPUT" + +echo "Applying patches..." +applied=0 +failed=0 +failed_list="" + +if [ -d "$PATCH_DIR" ]; then + patch_list="$(mktemp)" + trap 'rm -f "$patch_list"' EXIT + find "$PATCH_DIR" -name "*.patch" | sort > "$patch_list" + + while IFS= read -r patch_file; do + rel="${patch_file#$PATCH_DIR/}" + rel="${rel%.patch}" + dst="$OUTPUT/$rel" + + mkdir -p "$(dirname "$dst")" + if patch --merge --no-backup-if-mismatch --force "$dst" < "$patch_file"; then + applied=$((applied + 1)) + else + echo " FAILED: $rel" >&2 + failed=$((failed + 1)) + failed_list="${failed_list} ${rel} +" + fi + done < "$patch_list" +fi + +# Commit applied patches to keep history and clean worktree +git -C "$OUTPUT" add -A +git -C "$OUTPUT" commit -m "patches applied" --allow-empty + +total=$((applied + failed)) +echo "" +echo "Result: $applied/$total patches applied." +if [ "$failed" -gt 0 ]; then + echo "" + echo "Failed patches (merge conflicts written to files):" + printf "%s" "$failed_list" + exit 1 +fi + +echo "Done." diff --git a/bin/apply-ci.ps1 b/bin/apply-ci.ps1 new file mode 100644 index 0000000..190ee43 --- /dev/null +++ b/bin/apply-ci.ps1 @@ -0,0 +1,95 @@ +$ErrorActionPreference = 'Stop' + +$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path +$Root = Split-Path -Parent $ScriptDir +$SingBox = Join-Path $Root 'works/sing-box' +$PatchDir = Join-Path $Root 'works/patch' +$Output = Join-Path $Root 'works/core' +$RevFile = Join-Path $Root 'works/rev' + +# defaults +$RepoUrl = 'git@git.inker.bot:arknights/sing-box.git' +$UpstreamBranch = 'main' + +if ($env:CI_JOB_TOKEN) { + git config --global user.name imabot + git config --global user.email ci@inker.bot + $insteadOf = "https://gitlab-ci-token:${env:CI_JOB_TOKEN}@git.inker.bot/" + git config --global url.$insteadOf.insteadOf "git@git.inker.bot:" +} + +$ConfigFile = Join-Path $Root 'works/config' +if (Test-Path $ConfigFile) { + Get-Content $ConfigFile | ForEach-Object { + if ($_ -match '^([^#=]+)=(.*)$') { + $key = $Matches[1].Trim() + $val = $Matches[2].Trim() + if ($key -eq 'REPO_URL') { $RepoUrl = $val } + elseif ($key -eq 'UPSTREAM_BRANCH') { $UpstreamBranch = $val } + } + } +} + +# Clone if not present +if (-not (Test-Path (Join-Path $SingBox '.git'))) { + Write-Host 'Cloning sing-box...' + if ($UpstreamBranch) { + git clone -b $UpstreamBranch $RepoUrl $SingBox + } else { + git clone $RepoUrl $SingBox + } +} + +# Checkout stored rev +if (Test-Path $RevFile) { + $Rev = (Get-Content $RevFile -Raw).Trim() + Write-Host "Checking out stored rev: $Rev" + git -C $SingBox fetch --all + git -C $SingBox checkout $Rev +} else { + Write-Host 'Warning: works/rev not found, using current HEAD.' -ForegroundColor Yellow +} + +Write-Host 'Initializing works/core/ from works/sing-box/ (retaining .git)...' +if (Test-Path $Output) { Remove-Item -Recurse -Force $Output } +Copy-Item -Path $SingBox -Destination $Output -Recurse -Force + +Write-Host 'Applying patches...' +$applied = 0 +$failed = 0 +$failedList = @() + +if (Test-Path $PatchDir) { + Get-ChildItem -Path $PatchDir -Recurse -Filter '*.patch' | Sort-Object FullName | ForEach-Object { + $rel = $_.FullName.Substring($PatchDir.Length + 1) -replace '\.patch$', '' + $dst = Join-Path $Output $rel + $dstDir = Split-Path -Parent $dst + if (-not (Test-Path $dstDir)) { New-Item -ItemType Directory -Path $dstDir -Force | Out-Null } + + & patch --merge --no-backup-if-mismatch --force -i $_.FullName $dst 2>&1 + if ($LASTEXITCODE -eq 0) { + $applied++ + } else { + Write-Host " FAILED: $rel" -ForegroundColor Red + $failed++ + $failedList += $rel + } + } +} + +git -C $Output add -A +git -C $Output commit -m 'patches applied' --allow-empty + +$total = $applied + $failed +Write-Host "" +Write-Host "Result: $applied/$total patches applied." +if ($failed -gt 0) { + Write-Host "" + Write-Host "Failed patches (merge conflicts written to files):" -ForegroundColor Red + foreach ($f in $failedList) { + Write-Host " $f" -ForegroundColor Red + } + exit 1 +} + +Write-Host 'Done.'