Files
ShadowsocksX-NG/ShadowsocksX-NG2/Taskfile.dist.yml
T
Qiu Yuzhou e38d333a71 build: enforce strict checks across taskfile tasks
Inline strict SwiftLint and compiler flags in lint, build, and test tasks. Remove the STRICT configuration and forwarding from validation and CI, and update development documentation.
2026-10-25 23:24:13 +08:00

231 lines
9.6 KiB
YAML

# https://taskfile.dev/
version: '3'
includes:
packaging:
taskfile: ./Taskfile.package.yml
flatten: true
publishing:
taskfile: ./Taskfile.publish.yml
flatten: true
vars:
PROJECT_NAME: "ShadowsocksX-NG2"
BUILD_DIR: "{{ .TASKFILE_DIR }}/.build"
DERIVED_DATA_DIR: '{{default (printf "%s/derivedData" .BUILD_DIR) .DERIVED_DATA_DIR}}'
RELEASE_VERSION_PATTERN: '^v?[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$'
TEST_TIMEOUT_ARGS: '-test-timeouts-enabled YES -default-test-execution-time-allowance 120 -maximum-test-execution-time-allowance 300'
tasks:
validate:
desc: 'Run validation gates in order and retain logs/results; stop on first failure'
dir: '{{.TASKFILE_DIR}}'
silent: true
vars:
GATES: '{{default "lint test build" .CLI_ARGS | trim}}'
RUN_DIR:
sh: |
mkdir -p {{.BUILD_DIR | shellQuote}}/validation
mktemp -d {{.BUILD_DIR | shellQuote}}/validation/$(date -u +%Y%m%dT%H%M%SZ)-XXXXXX
preconditions:
- sh: '{{if regexMatch "^(format:check|lint|test|test:smoke|build)( (format:check|lint|test|test:smoke|build))*$" .GATES}}true{{else}}false{{end}}'
msg: 'Choose validation gates: format:check, lint, test, test:smoke, build (space separated).'
- sh: '{{if eq (len (splitList " " .GATES)) (len (uniq (splitList " " .GATES)))}}true{{else}}false{{end}}'
msg: 'Choose each validation gate at most once.'
cmds:
- defer:
task: validate:summary
vars:
RUN_DIR: '{{.RUN_DIR}}'
GATES: '{{.GATES}}'
CODE: '{{default "0" .EXIT_CODE}}'
- "printf '%s\n' {{printf \"Validation results: %s\" .RUN_DIR | shellQuote}}"
- for: {var: GATES, split: ' '}
task: validate:gate
vars:
RUN_DIR: '{{.RUN_DIR}}'
GATE: '{{.ITEM}}'
validate:gate:
internal: true
dir: '{{.TASKFILE_DIR}}'
silent: true
vars:
GATE_DIR: '{{.RUN_DIR}}/{{.GATE | replace ":" "-"}}'
cmds:
- mkdir -p {{.GATE_DIR | shellQuote}}
- defer:
task: validate:result
vars:
GATE: '{{.GATE}}'
GATE_DIR: '{{.GATE_DIR}}'
CODE: '{{default "0" .EXIT_CODE}}'
- "printf '%s\n' {{printf \"[%s] running; log: %s/raw.log\" .GATE .GATE_DIR | shellQuote}}"
- >-
task --exit-code --taskfile {{.TASKFILE_DIR | shellQuote}}/Taskfile.dist.yml {{.GATE | shellQuote}}
RESULT_BUNDLE_PATH={{.GATE_DIR | shellQuote}}/result.xcresult
> {{.GATE_DIR | shellQuote}}/raw.log 2>&1
validate:result:
internal: true
silent: true
cmds:
- |
status=failed
if [ {{.CODE | shellQuote}} = 0 ]; then status=passed; fi
echo "[{{.GATE}}] $status; exit={{.CODE}}" > {{.GATE_DIR | shellQuote}}/status.txt
- cmd: |
{{if and (ne .GATE "lint") (ne .GATE "format:check")}}
if [ ! -d {{.GATE_DIR | shellQuote}}/result.xcresult ]; then
echo '[{{.GATE}}] evidence incomplete: result bundle missing; test counts unknown' >> {{.GATE_DIR | shellQuote}}/status.txt
{{if ne .GATE "build"}}
elif xcrun xcresulttool get test-results summary --path {{.GATE_DIR | shellQuote}}/result.xcresult > {{.GATE_DIR | shellQuote}}/test-summary.json 2> {{.GATE_DIR | shellQuote}}/test-summary.stderr.log; then
if passed=$(plutil -extract passedTests raw -expect integer {{.GATE_DIR | shellQuote}}/test-summary.json) &&
failed=$(plutil -extract failedTests raw -expect integer {{.GATE_DIR | shellQuote}}/test-summary.json) &&
skipped=$(plutil -extract skippedTests raw -expect integer {{.GATE_DIR | shellQuote}}/test-summary.json) &&
expected=$(plutil -extract expectedFailures raw -expect integer {{.GATE_DIR | shellQuote}}/test-summary.json) &&
total=$(plutil -extract totalTestCount raw -expect integer {{.GATE_DIR | shellQuote}}/test-summary.json); then
echo "[{{.GATE}}] tests: passed=$passed failed=$failed skipped=$skipped expectedFailures=$expected total=$total" >> {{.GATE_DIR | shellQuote}}/status.txt
else
printf '%s\n' "$passed" "$failed" "$skipped" "$expected" "$total" >> {{.GATE_DIR | shellQuote}}/count-reader.log
echo '[{{.GATE}}] evidence incomplete: invalid test summary; test counts unknown (see count-reader.log)' >> {{.GATE_DIR | shellQuote}}/status.txt
fi 2> {{.GATE_DIR | shellQuote}}/count-reader.log
else
echo '[{{.GATE}}] evidence incomplete: xcresulttool failed; test counts unknown (see test-summary.stderr.log)' >> {{.GATE_DIR | shellQuote}}/status.txt
{{end}}
fi
{{end}}
- cat {{.GATE_DIR | shellQuote}}/status.txt
validate:summary:
internal: true
silent: true
cmds:
- |
echo 'Validation command exit={{.CODE}}' > {{.RUN_DIR | shellQuote}}/summary.txt
echo 'Selected gates: {{.GATES}}' >> {{.RUN_DIR | shellQuote}}/summary.txt
- for: {var: GATES, split: ' '}
cmd: |
if [ -f {{.RUN_DIR | shellQuote}}/{{.ITEM | replace ":" "-"}}/status.txt ]; then
cat {{.RUN_DIR | shellQuote}}/{{.ITEM | replace ":" "-"}}/status.txt >> {{.RUN_DIR | shellQuote}}/summary.txt
else
echo '[{{.ITEM}}] not_run' >> {{.RUN_DIR | shellQuote}}/summary.txt
fi
- cat {{.RUN_DIR | shellQuote}}/summary.txt
- "printf '%s\n' {{printf \"Summary: %s/summary.txt\" .RUN_DIR | shellQuote}}"
gen:prj:
desc: 'Generate xcode project by xcodegen'
cmds:
- xcodegen generate
build:
desc: Build the ShadowsocksX-NG2 macOS application with Debug Config
deps:
- gen:prj
cmds:
- >-
xcodebuild
-project ShadowsocksX-NG2.xcodeproj
-scheme ShadowsocksX-NG2
-configuration Debug
-destination 'platform=macOS,arch=arm64'
-derivedDataPath {{.DERIVED_DATA_DIR | shellQuote}}
{{if .RESULT_BUNDLE_PATH}}-resultBundlePath {{.RESULT_BUNDLE_PATH | shellQuote}}{{end}}
SWIFT_SUPPRESS_WARNINGS=NO SWIFT_TREAT_WARNINGS_AS_ERRORS=YES GCC_TREAT_WARNINGS_AS_ERRORS=YES
build
build:release:
desc: Build the ShadowsocksX-NG2 macOS application with Release Config
requires:
vars: [MARKETING_VERSION, CURRENT_PROJECT_VERSION]
vars:
BUNDLE_MARKETING_VERSION: '{{regexFind "[0-9]+\\.[0-9]+\\.[0-9]+" (default "" .MARKETING_VERSION)}}'
preconditions:
- sh: '{{if regexMatch .RELEASE_VERSION_PATTERN .MARKETING_VERSION}}true{{else}}false{{end}}'
msg: 'MARKETING_VERSION must be a release version (for example, 2.1.0 or v2.0.0-alpha-1).'
- sh: '{{if regexMatch "^[0-9]+(\\.[0-9]+){0,2}$" .CURRENT_PROJECT_VERSION}}true{{else}}false{{end}}'
msg: 'CURRENT_PROJECT_VERSION must have one to three numeric components.'
cmds:
- task: gen:prj
- >-
xcodebuild
-project ShadowsocksX-NG2.xcodeproj
-scheme ShadowsocksX-NG2
-configuration Release
-destination 'platform=macOS,arch=arm64'
-derivedDataPath {{.DERIVED_DATA_DIR | shellQuote}}
{{printf "MARKETING_VERSION=%s" .BUNDLE_MARKETING_VERSION | shellQuote}}
{{printf "CURRENT_PROJECT_VERSION=%s" .CURRENT_PROJECT_VERSION | shellQuote}}
SWIFT_SUPPRESS_WARNINGS=NO SWIFT_TREAT_WARNINGS_AS_ERRORS=YES GCC_TREAT_WARNINGS_AS_ERRORS=YES
build
format:
desc: 'Format the code by swift-format'
cmds:
- swift format format --in-place --recursive --configuration .swift-format App Tests Domain Agent
format:check:
desc: 'Check Swift formatting without modifying files'
cmds:
- swift format lint --strict --recursive --configuration .swift-format App Tests Domain Agent
lint:
desc: 'Lint the swift code by swiftlint'
cmds:
- swiftlint lint --strict --config .swiftlint.yml --no-cache
lint:fix:
desc: 'Automatically fix SwiftLint violations'
cmds:
- swiftlint lint --fix --strict --config .swiftlint.yml --no-cache
test:
desc: 'Run conversion and unit tests'
deps:
- gen:prj
cmds:
- task: test:binaries
- task: test:rules
- >-
xcodebuild
-project ShadowsocksX-NG2.xcodeproj
-scheme ShadowsocksX-NG2
-destination 'platform=macOS,arch=arm64'
-derivedDataPath {{.DERIVED_DATA_DIR | shellQuote}}
{{if .RESULT_BUNDLE_PATH}}-resultBundlePath {{.RESULT_BUNDLE_PATH | shellQuote}}{{end}}
{{.TEST_TIMEOUT_ARGS}}
SWIFT_SUPPRESS_WARNINGS=NO SWIFT_TREAT_WARNINGS_AS_ERRORS=YES GCC_TREAT_WARNINGS_AS_ERRORS=YES
test
test:binaries:
desc: 'Verify pinned external binary downloads with local assets'
cmds:
- PYTHONDONTWRITEBYTECODE=1 python3 Scripts/test-external-binary-fetch.py
test:rules:
desc: 'Run offline rule conversion and generated fixture checks'
cmds:
- PYTHONDONTWRITEBYTECODE=1 python3 Scripts/test-rule-snapshot-converters.py
- PYTHONDONTWRITEBYTECODE=1 python3 Scripts/test-rule-conversion-behavior.py
test:smoke:
desc: 'Run real-process smoke tests (real sslocal; release gate)'
deps:
- gen:prj
cmds:
- >-
xcodebuild
-project ShadowsocksX-NG2.xcodeproj
-scheme ShadowsocksX-NG2Smoke
-destination 'platform=macOS,arch=arm64'
-derivedDataPath {{.DERIVED_DATA_DIR | shellQuote}}
{{if .RESULT_BUNDLE_PATH}}-resultBundlePath {{.RESULT_BUNDLE_PATH | shellQuote}}{{end}}
{{.TEST_TIMEOUT_ARGS}}
SWIFT_SUPPRESS_WARNINGS=NO SWIFT_TREAT_WARNINGS_AS_ERRORS=YES GCC_TREAT_WARNINGS_AS_ERRORS=YES
test
clean:
cmds:
- rm -rf {{ .BUILD_DIR }}