mirror of
https://github.com/shadowsocks/ShadowsocksX-NG.git
synced 2026-11-01 15:43:45 +00:00
233 lines
9.5 KiB
YAML
233 lines
9.5 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'
|
|
STRICT: '{{default "false" .STRICT}}'
|
|
STRICT_BUILD_ARGS: '{{if eq .STRICT "true"}}SWIFT_SUPPRESS_WARNINGS=NO SWIFT_TREAT_WARNINGS_AS_ERRORS=YES GCC_TREAT_WARNINGS_AS_ERRORS=YES{{end}}'
|
|
|
|
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}}
|
|
STRICT={{.STRICT | 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}}
|
|
{{.STRICT_BUILD_ARGS}}
|
|
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}}
|
|
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 --config .swiftlint.yml --no-cache
|
|
|
|
lint:fix:
|
|
desc: 'Automatically fix SwiftLint violations'
|
|
cmds:
|
|
- swiftlint lint --fix --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}}
|
|
{{.STRICT_BUILD_ARGS}}
|
|
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}}
|
|
{{.STRICT_BUILD_ARGS}}
|
|
test
|
|
|
|
clean:
|
|
cmds:
|
|
- rm -rf {{ .BUILD_DIR }}
|