Skip to content

Commit d0103bb

Browse files
authored
Update release actions and documentation and config (NewFuture#466)
Enhance release actions and documentation, support array inputs for index4 and index6, and fix minor typos. Rename the script to patch.py for clarity.
2 parents da19b8c + 8456c34 commit d0103bb

12 files changed

Lines changed: 391 additions & 184 deletions

File tree

.build/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ COPY . .
44
RUN find /lib /usr/lib -name '*.so*' | sed 's|.*/||' | awk '{print "--noinclude-dlls="$0}' > nuitka_exclude_so.txt
55
RUN apk add py3-pip python3-dev patchelf build-base libffi-dev
66
RUN pip3 install -U nuitka --break-system-packages
7-
RUN python3 .build/remove_python2.py
7+
RUN python3 .build/patch.py
88
RUN python3 -O -m nuitka run.py \
99
--mode=onefile\
1010
--output-dir=./dist\
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
python3 -m nuitka run.py --mode=onefile --output-dir=./dist --no-deployment-flag=self-execution --output-filename=ddns --remove-output --include-module=dns.dnspod --include-module=dns.alidns --include-module=dns.dnspod_com --include-module=dns.dnscom --include-module=dns.cloudflare --include-module=dns.he --include-module=dns.huaweidns --include-module=dns.callback --product-name=DDNS --file-description="DDNS Client 自动更新域名解析到本机IP" --company-name="New Future" --copyright="https://ddns.newfuture.cc" --windows-icon-from-ico="favicon.ico" --assume-yes-for-downloads --lto=yes --nofollow-import-to=unittest,pydoc --onefile-tempdir-spec="{CACHE_DIR}/{PRODUCT}/{VERSION}"
1+
python3 -m nuitka run.py --mode=onefile --output-dir=./dist --no-deployment-flag=self-execution --output-filename=ddns --remove-output --include-module=dns.dnspod --include-module=dns.alidns --include-module=dns.dnspod_com --include-module=dns.dnscom --include-module=dns.cloudflare --include-module=dns.he --include-module=dns.huaweidns --include-module=dns.callback --product-name=DDNS --file-description="DDNS Client 自动更新域名解析到本机IP" --company-name="New Future" --copyright="https://ddns.newfuture.cc" --windows-icon-from-ico="favicon.ico" --assume-yes-for-downloads --lto=yes --nofollow-import-to=unittest,pydoc --onefile-tempdir-spec="{CACHE_DIR}/{PRODUCT}/{VERSION}" --linux-icon=doc/img/ddns.svg

.build/patch.py

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
#!/usr/bin/env python3
2+
"""
3+
自动将所有 try-except python2/3 兼容导入替换为 python3 only 导入,并显示处理日志
4+
"""
5+
import os
6+
import re
7+
8+
ROOT = '.'
9+
# 匹配 try-except 块,去除导入前缩进,保证import顶格,删除的行用空行代替
10+
PATTERN = re.compile(
11+
r'^[ \t]*try:[^\n]*python 3[^\n]*\n' # try: # python 3
12+
r'((?:[ \t]+[^\n]*\n)+?)' # python3 导入内容
13+
r'^[ \t]*except ImportError:[^\n]*\n' # except ImportError: # python 2
14+
r'((?:[ \t]+from[^\n]*\n|[ \t]+import[^\n]*\n)*)', # except块内容
15+
re.MULTILINE
16+
)
17+
18+
19+
def dedent_imports_with_blank(import_block, try_block, except_block):
20+
"""
21+
保留python3导入并去除缩进,try/except及except内容用空行代替
22+
"""
23+
try_lines = try_block.count('\n')
24+
except_lines = except_block.count('\n')
25+
imports = ''.join(line.lstrip()
26+
for line in import_block.splitlines(keepends=True))
27+
return ('\n' * try_lines) + imports + ('\n' * except_lines)
28+
29+
30+
def extract_pure_version(version_str):
31+
"""
32+
提取前4组数字并用点拼接,如 v1.2.3.beta4.5 -> 1.2.3.4
33+
"""
34+
import re
35+
nums = re.findall(r'\d+', version_str)
36+
return '.'.join(nums[:4]) if nums else "0.0.0"
37+
38+
39+
def update_nuitka_version(pyfile):
40+
"""
41+
读取 __version__ 并替换 nuitka-project 版本号
42+
"""
43+
with open(pyfile, 'r', encoding='utf-8') as f:
44+
content = f.read()
45+
46+
# 提取 __version__ 变量
47+
version_match = re.search(r'__version__\s*=\s*[\'"]([^\'"]+)[\'"]', content)
48+
if not version_match:
49+
print(f'No __version__ found in {pyfile}')
50+
return False
51+
52+
version_str = version_match.group(1)
53+
pure_version = extract_pure_version(version_str)
54+
55+
# 替换 nuitka-project 行
56+
new_content, n = re.subn(
57+
r'(# nuitka-project: --product-version=)[^\n]*',
58+
r'\g<1>' + pure_version,
59+
content
60+
)
61+
if n > 0:
62+
with open(pyfile, 'w', encoding='utf-8') as f:
63+
f.write(new_content)
64+
print(f'update nuitka-project version: {pure_version} in {pyfile}')
65+
return True
66+
return False
67+
68+
69+
def remove_windows_textiowrapper(pyfile):
70+
"""
71+
如果当前系统不是 Windows,则删除 run.py 中的 TextIOWrapper 兼容代码块
72+
"""
73+
if os.name == 'nt':
74+
return # Windows 下不处理
75+
76+
with open(pyfile, 'r', encoding='utf-8') as f:
77+
content = f.read()
78+
79+
# 匹配并删除 if sys.version_info.major == 3 and os_name == 'nt': ... 代码块
80+
pattern = re.compile(
81+
r'(?m)^[ \t]*if sys\.version_info\.major == 3 and os_name == [\'"]nt[\'"]:\n'
82+
r'(?:[ \t]+from io import TextIOWrapper\n)?'
83+
r'(?:[ \t]+sys\.stdout = TextIOWrapper\(sys\.stdout\.detach\(\), encoding=[\'"]utf-8[\'"]\)\n)?'
84+
r'(?:[ \t]+sys\.stderr = TextIOWrapper\(sys\.stderr\.detach\(\), encoding=[\'"]utf-8[\'"]\)\n)?'
85+
)
86+
new_content, n = pattern.subn('', content)
87+
if n > 0:
88+
with open(pyfile, 'w', encoding='utf-8') as f:
89+
f.write(new_content)
90+
print(f'Removed Windows TextIOWrapper code from {pyfile}')
91+
92+
93+
def main():
94+
"""
95+
遍历所有py文件并替换兼容导入,同时更新nuitka版本号
96+
"""
97+
changed_files = 0
98+
# 先处理 run.py 的 nuitka-project 版本号
99+
update_nuitka_version(os.path.join(ROOT, "run.py"))
100+
# 非 Windows 平台,移除 TextIOWrapper 兼容代码
101+
remove_windows_textiowrapper(os.path.join(ROOT, "run.py"))
102+
for dirpath, _, filenames in os.walk(ROOT):
103+
for fname in filenames:
104+
if fname.endswith('.py'):
105+
fpath = os.path.join(dirpath, fname)
106+
with open(fpath, 'r', encoding='utf-8') as f:
107+
content = f.read()
108+
109+
def repl(match):
110+
try_block = re.match(
111+
r'^[ \t]*try:[^\n]*python 3[^\n]*\n', match.group(0)
112+
).group(0)
113+
except_block = re.search(
114+
r'^[ \t]*except ImportError:[^\n]*\n((?:[ \t]+from[^\n]*\n|[ \t]+import[^\n]*\n)*)',
115+
match.group(0), re.MULTILINE
116+
)
117+
except_block = except_block.group(
118+
0) if except_block else ''
119+
return dedent_imports_with_blank(match.group(1), try_block, except_block)
120+
121+
new_content, n = PATTERN.subn(repl, content)
122+
if n > 0:
123+
with open(fpath, 'w', encoding='utf-8') as f:
124+
f.write(new_content)
125+
print(f'change: {fpath}')
126+
changed_files += 1
127+
print('done')
128+
print(f'Total changed files: {changed_files}')
129+
130+
131+
if __name__ == '__main__':
132+
main()

.build/remove_python2.py

Lines changed: 0 additions & 65 deletions
This file was deleted.

.github/release.md

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
[![PyPI version](https://img.shields.io/badge/DDNS-${BUILD_VERSION}-1abc9c.svg?style=social)](https://pypi.org/project/ddns/${BUILD_VERSION}/) ![Deploy OK](https://img.shields.io/badge/release-success-brightgreen.svg?style=flat-square)
2+
3+
## 版本下载方式一览表
4+
5+
| 平台/方式 |架构支持 |
6+
| ----------- |---------------------- |
7+
| Docker | `newfuture/ddns:${BUILD_VERSION}` 8种架构|
8+
| Windows | [64位(x64)](https://github.com/NewFuture/DDNS/releases/download/${BUILD_VERSION}/ddns-windows-x64.exe) / [32位(x86)](https://github.com/NewFuture/DDNS/releases/download/${BUILD_VERSION}/ddns-windows-x86.exe) / [arm64](https://github.com/NewFuture/DDNS/releases/download/${BUILD_VERSION}/ddns-windows-arm64.exe) |
9+
| Linux | [64位(x64)](https://github.com/NewFuture/DDNS/releases/download/${BUILD_VERSION}/ddns-linux-x64) / [arm64](https://github.com/NewFuture/DDNS/releases/download/${BUILD_VERSION}/ddns-linux-arm64) |
10+
| Mac OS X | [Apple Silicon (ARM64)](https://github.com/NewFuture/DDNS/releases/download/${BUILD_VERSION}/ddns-mac-arm64.app) / [Intel x64](https://github.com/NewFuture/DDNS/releases/download/${BUILD_VERSION}/ddns-mac-x64.app) |
11+
| Python/PIP | any |
12+
13+
## Docker (推荐) ![Docker Image Size (latest by date)](https://img.shields.io/docker/image-size/newfuture/ddns/${BUILD_VERSION}?style=flat-square)[![Docker Platforms](https://img.shields.io/badge/arch-amd64%20%7C%20arm64%20%7C%20arm%2Fv7%20%7C%20arm%2Fv6%20%7C%20ppc64le%20%7C%20s390x%20%7C%20386%20%7C%20mips64le-blue?logo=docker&style=flat-square)](https://hub.docker.com/r/newfuture/ddns)
14+
15+
```bash
16+
# 当前版本
17+
docker --name ddns -v $(pwd)/:/DDNS newfuture/ddns:${BUILD_VERSION} -h
18+
# 最新版本(可能有缓存)
19+
docker --name ddns -v $(pwd)/:/DDNS newfuture/ddns -h
20+
```
21+
22+
请将 `$(pwd)/` 替换为你的配置文件夹。
23+
24+
* 命令行参数使用 `-h`
25+
* 配置文件config.json,使用vscode等编辑会有自动提示
26+
* 环境变量`DDNS_XXX`
27+
28+
支持源:
29+
30+
* Docker官方源: [docker.io/newfuture/ddns](https://hub.docker.com/r/newfuture/ddns)
31+
* Github镜像源: [ghcr.io/newfuture/ddns](https://github.com/NewFuture/DDNS/pkgs/container/ddns/426721813?tag=${BUILD_VERSION})
32+
33+
---
34+
35+
## 使用二进制文件 ![cross platform](https://img.shields.io/badge/system-windows_%7C%20linux_%7C%20osx-success.svg?style=flat-square)
36+
37+
各平台下载/使用方式
38+
39+
* ### Windows
40+
41+
1. 下载 [`ddns-windows-x64.exe`](https://github.com/NewFuture/DDNS/releases/download/${BUILD_VERSION}/ddns-windows-x64.exe) 或者 [`ddns-windows-x32.exe`](https://github.com/NewFuture/DDNS/releases/download/${BUILD_VERSION}/ddns-windows-x32.exe) 或者[`ddns-windows-arm64.exe`](https://github.com/NewFuture/DDNS/releases/download/${BUILD_VERSION}/ddns-windows-arm64.exe) 保存为`ddns.exe` 运行
42+
2. [可选] 定时任务 下载 [`create-task.bat`](https://github.com/NewFuture/DDNS/releases/download/${BUILD_VERSION}/create-task.bat)**相同目录**,以管理员权限运行
43+
44+
* ### Linux 系统
45+
46+
```bash
47+
# 1. 下载ddns
48+
# x64 版本
49+
curl https://github.com/NewFuture/DDNS/releases/download/${BUILD_VERSION}/ddns-linux-x64 -#SLo ddns && chmod +x ddns
50+
51+
# arm64 版本
52+
curl https://github.com/NewFuture/DDNS/releases/download/${BUILD_VERSION}/ddns-linux-arm64 -#SLo ddns && chmod +x ddns
53+
54+
# 2. [可选] 定时任务(当前目录):
55+
curl -sSL https://github.com/NewFuture/DDNS/releases/download/${BUILD_VERSION}/create-task.sh | bash
56+
```
57+
58+
* ### Mac OSX
59+
60+
```sh
61+
# 命令行下载
62+
# arm64
63+
curl https://github.com/NewFuture/DDNS/releases/download/${BUILD_VERSION}/ddns-mac-arm64.app -#SLo ddns && chmod +x ddns
64+
65+
# intel x64
66+
curl https://github.com/NewFuture/DDNS/releases/download/${BUILD_VERSION}/ddns-mac-x64.app -#SLo ddns && chmod +x ddns
67+
```
68+
69+
## 使用PIP 安装 ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/ddns/${BUILD_VERSION}.svg?style=flat-square) ![PyPI - Wheel](https://img.shields.io/pypi/wheel/ddns.svg?style=flat-square)
70+
71+
Pypi 安装当前版本或者更新最新版本
72+
73+
* 安装当前版本[current version]: `pip install ddns=${BUILD_VERSION}`
74+
* 更新最新版[update latest version]: `pip install -U ddns`

.github/workflows/build.yml

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,6 @@ jobs:
115115
nuitka:
116116
needs: [ python ]
117117
strategy:
118-
fail-fast: false
119118
matrix:
120119
include:
121120
- os: windows-latest
@@ -143,7 +142,7 @@ jobs:
143142
architecture: ${{ matrix.arch }}
144143

145144
- name: remove python2 code
146-
run: python3 .build/remove_python2.py
145+
run: python3 .build/patch.py
147146

148147
# Prepare build version and cert
149148
- name: Replace build version
@@ -180,7 +179,7 @@ jobs:
180179
dns.he
181180
dns.huaweidns
182181
dns.callback
183-
file-description: "DDNS Client 更新域名解析本机IP"
182+
file-description: "DDNS Client 更新域名解析本机IP-预览版"
184183
product-name: DDNS
185184
company-name: "New Future"
186185
copyright: "https://ddns.newfuture.cc"
@@ -190,10 +189,10 @@ jobs:
190189
nofollow-import-to: tkinter,unittest,pydoc,doctest,distutils,setuptools,lib2to3,test,idlelib,lzma
191190
onefile-tempdir-spec: "{CACHE_DIR}/{PRODUCT}_{VERSION}"
192191
windows-icon-from-ico: ${{ runner.os == 'Windows' && 'favicon.ico' || '' }}
193-
linux-icon: ${{ runner.os == 'Linux' && '.build/ddns.svg' || '' }}
192+
linux-icon: ${{ runner.os == 'Linux' && 'doc/img/ddns.svg' || '' }}
194193
static-libpython: ${{ runner.os == 'Linux' && 'yes' || 'auto' }}
195194
macos-app-name: ${{ runner.os == 'macOS' && 'DDNS' || '' }}
196-
macos-app-icon: ${{ runner.os == 'macOS' && '.build/ddns.svg' || '' }}
195+
macos-app-icon: ${{ runner.os == 'macOS' && 'doc/img/ddns.svg' || '' }}
197196

198197

199198
- run: ./dist/ddns || test -e config.json
@@ -212,12 +211,13 @@ jobs:
212211
dist/ddns
213212
214213
nuitka-linux:
214+
needs: [ python ]
215215
strategy:
216216
fail-fast: false
217217
matrix:
218218
os: [ ubuntu-latest, ubuntu-24.04-arm ]
219219
runs-on: ${{ matrix.os }}
220-
timeout-minutes: 30
220+
timeout-minutes: 10
221221
steps:
222222
- uses: actions/checkout@v4
223223

@@ -238,7 +238,7 @@ jobs:
238238
&& dnf repolist \
239239
&& dnf install -y gcc strace patchelf ccache gdb make python3-devel python3-zstandard python3-ordered-set
240240
python3 -m pip install nuitka
241-
cd /DDNS && python3 .build/remove_python2.py && .build/nuitka.cmd
241+
cd /DDNS && python3 .build/patch.py && .build/nuitka.sh
242242
243243
- run: ./dist/ddns || test -e config.json
244244
- run: ./dist/ddns -h

0 commit comments

Comments
 (0)