Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 12 additions & 9 deletions .build/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,25 +1,28 @@
FROM alpine:latest
FROM alpine
WORKDIR /build
COPY . .
RUN find /lib /usr/lib -name '*.so*' | sed 's|.*/||' | awk '{print "--noinclude-dlls="$0}' > nuitka_exclude_so.txt
RUN apk add py3-pip python3-dev patchelf build-base libffi-dev
RUN pip3 install -U nuitka --break-system-packages
RUN python3 -m nuitka run.py \
RUN python3 .build/remove_python2.py
RUN python3 -O -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\
--lto=yes \
--onefile-tempdir-spec="{TEMP}/{PRODUCT}_{VERSION}" \
--python-flag=no_site,no_asserts,no_docstrings,isolated,static_hashes\
--nofollow-import-to=unittest,pydoc\
--onefile-tempdir-spec="{CACHE_DIR}/{PRODUCT}/{VERSION}"
RUN mkdir bin
RUN cp dist/ddns bin/
RUN cp .build/entrypoint.sh bin/
--nofollow-import-to=tkinter,unittest,pydoc,doctest,distutils,setuptools,lib2to3,test,idlelib,lzma \
--noinclude-dlls=liblzma.so.* \
$(cat nuitka_exclude_so.txt)
RUN mkdir docker-bin && cp dist/ddns docker-bin/ && cp .build/entrypoint.sh docker-bin/

FROM alpine:latest
FROM alpine
LABEL maintainer="NN708, newfuture"
WORKDIR /ddns
COPY --from=0 /build/bin/* /bin/
COPY --from=0 /build/docker-bin/* /bin/
ENTRYPOINT [ "/bin/entrypoint.sh" ]
4 changes: 1 addition & 3 deletions .build/entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@
if [ $# -eq 0 ]; then
printenv > /etc/environment
echo "*/5 * * * * cd /ddns && /bin/ddns" > /etc/crontabs/root
/bin/ddns
echo "Cron daemon will run every 5 minutes..."
exec crond -f
/bin/ddns && echo "Cron daemon will run every 5 minutes..." && exec crond -f
else
first=`echo $1 | cut -c1`
if [ "$first" = "-" ]; then
Expand Down
65 changes: 65 additions & 0 deletions .build/remove_python2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#!/usr/bin/env python3
"""
自动将所有 try-except python2/3 兼容导入替换为 python3 only 导入,并显示处理日志
"""
import os
import re

ROOT = '.'
# 匹配 try-except 块,去除导入前缩进,保证import顶格,删除的行用空行代替
PATTERN = re.compile(
r'^[ \t]*try:[^\n]*python 3[^\n]*\n' # try: # python 3
r'((?:[ \t]+[^\n]*\n)+?)' # python3 导入内容
r'^[ \t]*except ImportError:[^\n]*\n' # except ImportError: # python 2
r'((?:[ \t]+from[^\n]*\n|[ \t]+import[^\n]*\n)*)', # except块内容
re.MULTILINE
)


def dedent_imports_with_blank(import_block, try_block, except_block):
"""
保留python3导入并去除缩进,try/except及except内容用空行代替
"""
try_lines = try_block.count('\n')
except_lines = except_block.count('\n')
imports = ''.join(line.lstrip()
for line in import_block.splitlines(keepends=True))
return ('\n' * try_lines) + imports + ('\n' * except_lines)


def main():
"""
遍历所有py文件并替换兼容导入
"""
changed_files = 0
for dirpath, _, filenames in os.walk(ROOT):
for fname in filenames:
if fname.endswith('.py'):
fpath = os.path.join(dirpath, fname)
with open(fpath, 'r', encoding='utf-8') as f:
content = f.read()

def repl(match):
try_block = re.match(
r'^[ \t]*try:[^\n]*python 3[^\n]*\n', match.group(0)
).group(0)
except_block = re.search(
r'^[ \t]*except ImportError:[^\n]*\n((?:[ \t]+from[^\n]*\n|[ \t]+import[^\n]*\n)*)',
match.group(0), re.MULTILINE
)
except_block = except_block.group(
0) if except_block else ''
return dedent_imports_with_blank(match.group(1), try_block, except_block)

new_content, n = PATTERN.subn(repl, content)
if n > 0:
with open(fpath, 'w', encoding='utf-8') as f:
f.write(new_content)
print(f'change: {fpath}')
changed_files += 1
print('done')
print(f'Total changed files: {changed_files}')


if __name__ == '__main__':
main()
86 changes: 70 additions & 16 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,23 @@ jobs:
- name: check complexity and length # the GitHub editor is 127 chars wide
run: flake8 . --count --max-complexity=12 --max-line-length=127 --statistics

python:
strategy:
fail-fast: false
matrix:
python-version: [ "2.7","3" ]
runs-on: ubuntu-22.04
timeout-minutes: 5
steps:
- uses: actions/checkout@v4
- run: sudo apt-get update && sudo apt-get install -y python${{ matrix.python-version }}
- name: test help command
run: python${{ matrix.python-version }} run.py -h
- name: test config generation
run: python${{ matrix.python-version }} run.py || test -e config.json
- name: test version
run: python${{ matrix.python-version }} run.py --version

pypi:
runs-on: ubuntu-latest
timeout-minutes: 5
Expand All @@ -55,6 +72,7 @@ jobs:
path: dist/
retention-days: 5


pyinstaller:
strategy:
# fail-fast: false
Expand Down Expand Up @@ -95,6 +113,7 @@ jobs:
retention-days: 3

nuitka:
needs: [ python ]
strategy:
fail-fast: false
matrix:
Expand Down Expand Up @@ -122,8 +141,9 @@ jobs:
with:
python-version: 3.x
architecture: ${{ matrix.arch }}
- name: Install dependencies
run: python3 -m pip install -U nuitka

- name: remove python2 code
run: python3 .build/remove_python2.py

# Prepare build version and cert
- name: Replace build version
Expand All @@ -133,34 +153,67 @@ jobs:
- name: Set up on Linux
if: runner.os == 'Linux'
run: |
sudo apt-get update
sudo apt-get install -y patchelf
echo " --static-libpython=yes --linux-icon=.build/icon.png" >> .build/nuitka.cmd
sudo apt-get update && sudo apt-get install -y patchelf
cp /etc/ssl/certs/ca-certificates.crt cert.pem && export SSL_CERT_FILE=${PWD}/cert.pem

- name: Set up on macOS
if: runner.os == 'macOS'
run: |
python3 -m pip install imageio
echo " --macos-app-name=DDNS --macos-app-icon=.build/icon.png" >> .build/nuitka.cmd

run: python3 -m pip install imageio

- run: python3 ./run.py -h

- name: Package binary
run: ./.build/nuitka.cmd
- name: Build Executable
uses: Nuitka/Nuitka-Action@main
with:
nuitka-version: main
script-name: run.py
mode: onefile
output-dir: dist
output-file: ddns
no-deployment-flag: self-execution
include-module: |
dns.dnspod
dns.alidns
dns.dnspod_com
dns.dnscom
dns.cloudflare
dns.he
dns.huaweidns
dns.callback
file-description: "DDNS Client 更新域名解析本机IP"
product-name: DDNS
company-name: "New Future"
copyright: "https://ddns.newfuture.cc"
assume-yes-for-downloads: true
lto: auto
python-flag: no_site,no_asserts,no_docstrings,isolated,static_hashes
nofollow-import-to: tkinter,unittest,pydoc,doctest,distutils,setuptools,lib2to3,test,idlelib,lzma
onefile-tempdir-spec: "{CACHE_DIR}/{PRODUCT}_{VERSION}"
windows-icon-from-ico: ${{ runner.os == 'Windows' && 'favicon.ico' || '' }}
linux-icon: ${{ runner.os == 'Linux' && '.build/icon.png' || '' }}
static-libpython: ${{ runner.os == 'yes' || 'auto' }}
macos-app-name: ${{ runner.os == 'macOS' && 'DDNS' || '' }}
macos-app-icon: ${{ runner.os == 'macOS' && '.build/icon.png' || '' }}


- run: ./dist/ddns || test -e config.json
- run: ./dist/ddns -h

# Upload build result
- uses: actions/upload-artifact@v4
- name: Upload Artifacts
uses: actions/upload-artifact@v4
with:
name: ddns-${{ runner.os }}-${{ matrix.arch }}
path: dist/
retention-days: 7
if-no-files-found: error
path: |
dist/*.exe
dist/*.bin
dist/*.app
dist/ddns

docker:
if: github.event_name == 'pull_request'
needs: [ python ]
strategy:
matrix:
platforms: [ linux/386,linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64/v8,linux/ppc64le,linux/riscv64,linux/s390x ]
Expand Down Expand Up @@ -189,7 +242,7 @@ jobs:
preview-pypi:
runs-on: ubuntu-latest
if: github.event_name == 'push'
needs: [lint, pypi]
needs: [lint, pypi, python]
timeout-minutes: 3
environment:
name: preview
Expand All @@ -207,8 +260,9 @@ jobs:
print-hash: true

preview-docker:
runs-on: ubuntu-latest
if: github.event_name == 'push'
needs: [lint, python]
runs-on: ubuntu-latest
timeout-minutes: 120
environment:
name: preview
Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,9 @@ jobs:
run: sed -i.tmp -e "s#\${BUILD_VERSION}#${{ github.ref_name }}#" -e "s/\${BUILD_DATE}/$(date --iso-8601=seconds)/" run.py && rm run.py.tmp
shell: bash

- name: remove python2 code
run: python3 .build/remove_python2.py

- name: setup on Linux
if: runner.os == 'Linux'
run: |
Expand Down
10 changes: 4 additions & 6 deletions dns/alidns.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,12 @@
from logging import debug, info, warning
from datetime import datetime

try:
# python 2
from httplib import HTTPSConnection
from urllib import urlencode, quote_plus, quote
except ImportError:
# python 3
try: # python 3
from http.client import HTTPSConnection
from urllib.parse import urlencode, quote_plus, quote
except ImportError: # python 2
from httplib import HTTPSConnection
from urllib import urlencode, quote_plus, quote

__author__ = 'New Future'
# __all__ = ["request", "ID", "TOKEN", "PROXY"]
Expand Down
10 changes: 4 additions & 6 deletions dns/callback.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,13 @@
from logging import debug, info, warning
from time import time

try:
# python 2
try: # python 3
from http.client import HTTPSConnection, HTTPConnection
from urllib.parse import urlencode, urlparse, parse_qsl
except ImportError: # python 2
from httplib import HTTPSConnection, HTTPConnection
from urlparse import urlparse, parse_qsl
from urllib import urlencode
except ImportError:
# python 3
from http.client import HTTPSConnection, HTTPConnection
from urllib.parse import urlencode, urlparse, parse_qsl

__author__ = '老周部落'

Expand Down
10 changes: 4 additions & 6 deletions dns/cloudflare.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,12 @@
from json import loads as jsondecode, dumps as jsonencode
from logging import debug, info, warning

try:
# python 2
from httplib import HTTPSConnection
from urllib import urlencode
except ImportError:
# python 3
try: # python 3
from http.client import HTTPSConnection
from urllib.parse import urlencode
except ImportError: # python 2
from httplib import HTTPSConnection
from urllib import urlencode

__author__ = 'TongYifan'

Expand Down
11 changes: 4 additions & 7 deletions dns/dnscom.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,12 @@
from time import mktime
from datetime import datetime

try:
# python 2
from httplib import HTTPSConnection
from urllib import urlencode
except ImportError:
# python 3
try: # python 3
from http.client import HTTPSConnection
from urllib.parse import urlencode

except ImportError: # python 2
from httplib import HTTPSConnection
from urllib import urlencode

__author__ = 'Bigjin'
# __all__ = ["request", "ID", "TOKEN", "PROXY"]
Expand Down
11 changes: 5 additions & 6 deletions dns/dnspod.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,13 @@
from json import loads as jsondecode
from logging import debug, info, warning
from os import environ
try:
# python 2
from httplib import HTTPSConnection
from urllib import urlencode
except ImportError:
# python 3

try: # python 3
from http.client import HTTPSConnection
from urllib.parse import urlencode
except ImportError: # python 2
from httplib import HTTPSConnection
from urllib import urlencode

__author__ = 'New Future'

Expand Down
10 changes: 4 additions & 6 deletions dns/he.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,12 @@

from logging import debug, info, warning

try:
# python 2
from httplib import HTTPSConnection
from urllib import urlencode
except ImportError:
# python 3
try: # python 3
from http.client import HTTPSConnection
from urllib.parse import urlencode
except ImportError: # python 2
from httplib import HTTPSConnection
from urllib import urlencode

__author__ = 'NN708'

Expand Down
Loading
Loading