GitHub Action: 自动发布WordPress主题插件新版本

主要功能 当主题或插件修改提交commit 并 push到Github时,自动打包主题插件发布一个Realease 判断当前版本号,如果与之前版本号相同则不发布 .releaseignore文件设置忽略的文件或文件夹,不打包进release 主题 必须按照WordPress主题开发规范,在style.css顶部注释版本号(Version:) 文件位置: .github/workflows/release-on-version-change.yml 内容: name: Release on version change on: push: branches: - main - master permissions: contents: write packages: write jobs: release: runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v4 - name: Get previous commit hash id: prev run: | echo "prev_commit=$(git rev-parse HEAD^)" >> $GITHUB_ENV - name: Extract current version from style.css id: current_version run: | version=$(grep -E '^(Version:|版本:)' style.css | sed 's/.*[::] *//') if [ -z "$version" ]; then echo "❌ 未能在当前 style.css 中找到版本号" exit 1 fi echo "current_version=$version" >> $GITHUB_ENV echo "当前版本: $version" - name: Extract previous version from last commit id: prev_version run: | git show ${{ env.prev_commit }}:style.css > old_style.css || true version=$(grep -E '^(Version:|版本:)' old_style.css | sed 's/.*[::] *//') echo "prev_version=$version" >> $GITHUB_ENV echo "上一个版本: $version" - name: Compare versions id: compare run: | if [ "${{ env.current_version }}" != "${{ env.prev_version }}" ]; then echo "version_changed=true" >> $GITHUB_ENV echo "🔄 版本变化: ${{ env.prev_version }} → ${{ env.current_version }}" else echo "version_changed=false" >> $GITHUB_ENV echo "ℹ️ 版本未变化,无需发布" fi - name: Stop if version not changed if: env.version_changed == 'false' run: exit 0 - name: Check if tag already exists id: tag_check run: | if git rev-parse "v${{ env.current_version }}" >/dev/null 2>&1; then echo "tag_exists=true" >> $GITHUB_ENV echo "⚠️ Tag v${{ env.current_version }} 已存在,跳过发布" else echo "tag_exists=false" >> $GITHUB_ENV fi - name: Stop if tag already exists if: env.tag_exists == 'true' run: exit 0 - name: Create Git tag if: env.tag_exists == 'false' run: | git config user.name "github-actions[bot]" git config user.email "41898282+github-actions[bot]@users.noreply.github.com" git tag -a "v${{ env.current_version }}" -m "Release v${{ env.current_version }}" git push origin "v${{ env.current_version }}" - name: Create ZIP package (with ignore list) run: | ZIP_FILE="${{ github.event.repository.name }}-${{ env.current_version }}.zip" EXCLUDE_ARGS="-x '*.git*' '.github/*'" if [ -f ".releaseignore" ]; then echo "🧾 使用 .releaseignore 过滤以下内容:" while IFS= read -r line; do if [ -n "$line" ] && [[ ! "$line" =~ ^# ]]; then echo " - $line" EXCLUDE_ARGS="$EXCLUDE_ARGS '$line'" fi done < .releaseignore else echo "⚠️ 未找到 .releaseignore,使用默认排除规则。" fi eval zip -r "$ZIP_FILE" . $EXCLUDE_ARGS echo "✅ 打包完成:$ZIP_FILE" - name: Create GitHub Release uses: softprops/action-gh-release@v2 with: tag_name: v${{ env.current_version }} name: "Release v${{ env.current_version }}" body: | 🎉 自动发布版本 v${{ env.current_version }} 🔖 来自 commit: ${{ github.sha }} files: ${{ github.event.repository.name }}-${{ env.current_version }}.zip env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 文件位置: ...

2025-11-03 · 4 min · Duke Yin

WordPress另一更新正在进行

进入PHPMyAdmin,对应数据库执行 delete from wp_options where option_name='core_updater.lock'; 注意如果你的数据库前缀如果有修改,需要将wp-option 换成更换后的前缀

2024-09-17 · 1 min · Duke Yin

WordPress 将Debug写入文件

在wp-config中打开debug后,出错会直接显示在前端,但这会影响成品站点的用户体验,添加如下两个定义后可以不显示在前端,并且记录在wp-content/debug.log中。 define( 'WP_DEBUG_LOG', true ); define( 'WP_DEBUG_DISPLAY', false ); 但是由于WordPress内核本身年代久远,如果你使用新的PHP版本比如8,log将会记录大量由WordPress本身造成的deprecated的提示,虽然官方文档针对log的等级可以用如下来设置: error_reporting( E_ALL & ~E_DEPRECATED ); 但是由于wp-config加载比较靠前,错误报告设置极大可能会被后面的某一些项给改写。我尝试过在新安装的WordPress中,剔除Depreacated信息都是不起作用的。 所以有了如下解决方案: define( 'WP_DEBUG', true ); define( 'WP_DEBUG_LOG', true ); define( 'WP_DEBUG_DISPLAY', false ); $GLOBALS['wp_filter'] = array( 'enable_wp_debug_mode_checks' => array( 10 => array( array( 'accepted_args' => 0, 'function' => function () { if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) { // *** This is the key line - change to adjust to whatever logging state you want error_reporting( E_ALL & ~E_DEPRECATED ); ini_set( 'display_errors', defined( 'WP_DEBUG_DISPLAY' ) &amp;&amp; WP_DEBUG_DISPLAY ? 1 : 0 ); if ( in_array( strtolower( (string) WP_DEBUG_LOG ), array( 'true', '1' ), true ) ) { $log_path = WP_CONTENT_DIR . '/debug.log'; } elseif ( is_string( WP_DEBUG_LOG ) ) { $log_path = WP_DEBUG_LOG; } else { $log_path = false; } if ( $log_path ) { ini_set( 'log_errors', 1 ); ini_set( 'error_log', $log_path ); } if ( defined( 'XMLRPC_REQUEST' ) || defined( 'REST_REQUEST' ) || defined( 'MS_FILES_REQUEST' ) || ( defined( 'WP_INSTALLING' ) &amp;&amp; WP_INSTALLING ) || wp_doing_ajax() || wp_is_json_request() ) { ini_set( 'display_errors', 0 ); } } return false; }, ), ), ));</code></pre> 使用wp_filter去处理,不会被覆写,有多种情况处理,log文件不记录depracated信息,甚至你可以根据自己的需求去编辑log等级。

2024-07-29 · 1 min · Duke Yin

wp_remote_get $args

wp_remote_get( $url, $args = array() ) /** * @param string|array $args { * Optional. Array or string of HTTP request arguments. * * @type string $method Request method. Accepts 'GET', 'POST', 'HEAD', 'PUT', 'DELETE', * 'TRACE', 'OPTIONS', or 'PATCH'. * Some transports technically allow others, but should not be * assumed. Default 'GET'. * @type float $timeout How long the connection should stay open in seconds. Default 5. * @type int $redirection Number of allowed redirects. Not supported by all transports * Default 5. * @type string $httpversion Version of the HTTP protocol to use. Accepts '1.0' and '1.1'. * Default '1.0'. * @type string $user-agent User-agent value sent. * Default 'WordPress/' . get_bloginfo( 'version' ) . '; ' . get_bloginfo( 'url' ). * @type bool $reject_unsafe_urls Whether to pass URLs through wp_http_validate_url(). * Default false. * @type bool $blocking Whether the calling code requires the result of the request. * If set to false, the request will be sent to the remote server, * and processing returned to the calling code immediately, the caller * will know if the request succeeded or failed, but will not receive * any response from the remote server. Default true. * @type string|array $headers Array or string of headers to send with the request. * Default empty array. * @type array $cookies List of cookies to send with the request. Default empty array. * @type string|array $body Body to send with the request. Default null. * @type bool $compress Whether to compress the $body when sending the request. * Default false. * @type bool $decompress Whether to decompress a compressed response. If set to false and * compressed content is returned in the response anyway, it will * need to be separately decompressed. Default true. * @type bool $sslverify Whether to verify SSL for the request. Default true. * @type string $sslcertificates Absolute path to an SSL certificate .crt file. * Default ABSPATH . WPINC . '/certificates/ca-bundle.crt'. * @type bool $stream Whether to stream to a file. If set to true and no filename was * given, it will be droped it in the WP temp dir and its name will * be set using the basename of the URL. Default false. * @type string $filename Filename of the file to write to when streaming. $stream must be * set to true. Default null. * @type int $limit_response_size Size in bytes to limit the response to. Default null. * * } */

2023-07-31 · 2 min · Duke Yin

保证WordPress Cron Job执行

WordPress的定时任务有个缺陷,它不一定会按照定好的计划执行。 因为WordPress的 Cron Job依赖前端访问,而不是直接跟操作系统挂钩,所以当WordPress网站的访问量很低,或者是不公开的WordPress实例,其Cron Job就不能按时执行任务。 不按时执行任务除了会影响既定程序的运行,也会影响WP核心的检查更新,维护任务,安全方面也是很大的风险。 情况1 如果你的站点是公开的,可以在Linux 的CronTab上制定一个较为频繁的任务,定时访问站点,触发WordPress检查CronJob: wget --delete-after https://www.website.com/wp-cron.php 将这个命令保存到系统级crontab里,建议每30分钟执行,即可。记得替换https://www.website.com/为你的站点首页地址。 情况2 如果你的网站是私密的外界无法通过域名访问,则可以: cd /path/to/your/website/rootfolder; wp cron event run --due-now >/dev/null 2>&1 替换/path/to/your/website/rootfolder为你的站点在本机的路径,即可。同样推荐每半小时执行一次。 情况3 如果你的操作系统是Windows,则可以用Windows 计划任务 制定一个系统级计划任务触发PHP执行任务。 shellscript.vbs Set WinScriptHost = CreateObject("WScript.Shell") WinScriptHost.Run Chr(34) & "C:\path\to\script\script.bat" & Chr(34), 0 Set WinScriptHost = Nothing script.bat ...

2023-06-15 · 1 min · Duke Yin

群晖Docker安装独立WordPress容器

需要两个映像: mariadb wordpress mariadb 无需高级权限 建议开启资源限制,内存根据实际情况限制最高值 打开自动重启 选桥接网络,自动映射端口 映射本地任意文件夹到 /var/lib/mysql 环境变量 如下: MYSQL_DATABASE: name_your_database MYSQL_ROOT_PASSWORD: choose_root_password MYSQL_USER: your_user_name MYSQL_PASSWORD: choose_user_password 提前启动。 WordPress 无需高级权限 打开资源限制 自动重启 桥接网络,映射80到你需要访问的端口 链接(Links),容器名称填刚刚创建的mariadb的容器名,别称mysql 文件夹映射: docker/somesite/www/ : /var/www/html docker/somesite/wordpress.ini : /usr/local/etc/php/conf.d/wordpress.ini ini 文件即为php配置,添加如下内容: file_uploads = On memory_limit = 256M upload_max_filesize = 128M post_max_size = 256M max_execution_time = 300 max_input_vars = 5000 可解决上传附件尺寸限制问题。 ...

2023-05-30 · 1 min · Duke Yin

WordPress阻止未授权域名访问REST API

方法1 在wp-config.php添加如下字段即可。域名为白名单,不在白名单的域名讲无法访问REST API define( 'WP_HTTP_BLOCK_EXTERNAL', TRUE ); define( 'WP_ACCESSIBLE_HOSTS', 'example.com, domain.com' ); 方法2 数组为白名单域名 登陆后必须要开放,因为编辑文章需要用到REST API function restrict_rest_api_to_localhost() { $whitelist = [ '127.0.0.1', "::1" ]; if( ! in_array($_SERVER['REMOTE_ADDR'], $whitelist ) ){ die( 'REST API is disabled' ); } } if (!is_user_logged_in() ) { add_action( ‘rest_api_init’, ‘restrict_rest_api_to_localhost’, 0 ); }

2023-03-28 · 1 min · Duke Yin

Wordpress Code Snippets

Admin Notice function dk_admin_notice() { ?> <div class="notice notice-success is-dismissible"> <p><?php _e( 'This is a success notice.', 'dukeyin' ); ?></p> </div> <?php } add_action( 'admin_notices', 'dk_admin_notice' ); //notice-success //notice-danger //notice-warning //notice-info Enqueue Style and JavaScripts Styles // Enqueue own styles function dk_enqueue_custom_styles() { wp_enqueue_style( 'main',get_template_directory_uri() .'/assets/css/main.css', array(),'1.0','all'); } add_action( ‘wp_enqueue_scripts’, ‘dk_enqueue_custom_styles’ ); //in frontend ...

2023-02-01 · 15 min · Duke Yin

WordPress主题文件结构

示例1 air-light theme themes/your-theme-name/ # → Root of your air-light based theme ├── 404.php # → Default "not found" page ├── archive.php # → Default archive template ├── bin/ # → Scripts │ ├── ... # → This scripts are used for generating themes or new Air-light version │ └── newtheme.sh # → The start script for creating YOUR own theme out of Air-light ├── comments.php # → Default comments template (can be deleted if not needed) ├── css/ # → CSS files for production (never edit) │ ├── dev/ # → Unminified stylesheet files for debugging (never edit) │ └── prod/ # → Minified stylesheet files for production (never edit) ├── fonts/ # → Your webfont files (woff, woff2, ttf needed) ├── footer.php # → Site footer ├── front-page.php # → Demo front-page template (not included in wordpress.org version) ├── functions.php # → Set up your theme basic settings ├── gulp/ # → Gulp related settings and tasks │ └── ... # ├── gulpfile.js # → Core gulpfile for air-light development ├── header.php # → Site header ├── images/ # → Your theme images, for example default featured images and placeholders ├── inc/ # → Theme core PHP │ ├── hooks/ # → Hook functions │ ├── includes/ # → Non-template features │ ├── template-tags/ # → Template functions and helpers │ ├── post-types/ # → Custom Post Types │ ├── taxonomies/ # → Custom Taxonomies │ ├── hooks.php # → All hooks the theme runs are here │ ├── includes.php # → Include non-template features │ └── template-tags.php # → Include template functions and helpers ├── js/ # → JavaScript files │ ├── dev/ # → Unminified script files for debugging (never edit) │ ├── prod/ # → Minified script files for production (never edit) │ └── src/ # → Script files for development (edit these) │ ├── navigation.js # → Accessible multi-level navigation (from 3.4.5) │ ├── front-end.js # → Theme core JavaScript file (from 1.0.0, before: scripts.js) │ └── sticky-nav.js # → Sticky nav functionality (optional) ├── package.json # → Node.js dependencies and scripts ├── page.php # → Default page template ├── phpcs.xml # → PHPCodeSniffer/WordPress Theme Coding Standards settings ├── sass/ # → SCSS files for CSS development │ ├── base/ # → Theme base styles │ │ └── _accessibility.scss # → Accessibility │ ├── global.scss # → Core CSS file that calls all the modular files │ ├── gutenberg-editor-styles.scss # → Core CSS file for Gutenberg editor and blocks │ ├── components/ # → Add your style components to this folder │ ├── features/ # → Fuctionality styles │ │ ├── _gallery.scss # → Default WordPress gallery feature styles │ │ ├── _gravity-forms.scss # → Defaults for Gravity Forms + WCAG 2.0 form fields for Gravity Forms │ │ ├── _lazyload.scss # → Styles for air-helper lazyload feature (lazyload.js needed) │ │ ├── _top.scss # → Back to top styles │ │ ├── _pagination.scss # → Numbered pagination styles │ │ ├── _sticky-nav.scss # → Sticky nav styles (not included by default) │ │ └── _slick.scss # → Styles for slick-carousel (not included by default) │ ├── gutenberg/ # → Gutenberg block styles for both core and custom blocks │ │ └── ... # → WIP │ ├── helpers/ # → Helper mixins and functions │ │ ├── _animations.scss # → Animations and effects │ │ ├── _aspect-ratio.scss # → A mixin for aspect ratio │ │ ├── _general.scss # → Mixins for general use, or helpers of other mixins │ │ ├── _grid.scss # → CSS Grid helper mixin │ │ └── _typography.scss # → Typography style mixins │ ├── layout/ # → Fuctionality styles │ │ ├── _forms.scss # → Styles for general forms and Gravity Forms │ │ ├── _site-footer.scss # → Footer styles │ │ ├── _site-header.scss # → Header styles │ │ ├── _typography.scss # → Defaults for typography and fonts │ │ └── _gutenberg.scss # → Site-side styles for Gutenberg (pratically for single.php) │ ├── navigation/ # → Navigation styles │ │ ├── _burger.scss # → Burger styles and animations │ │ ├── _nav-desktop.scss # → Desktop navigation styles and dropdowns │ │ └── _nav-mobile.scss # → Navigation styles for mobile and touch devices │ ├── variables/ # → Configurations │ │ ├── _breakpoints.scss # → Widths from mobile to TV screens │ │ ├── _colors.scss # → All the colors of the theme │ │ ├── _font-face.scss # → Define font variables here │ │ ├── _font-family.scss # → Define font paths │ │ ├── _font-size.scss # → Define font related sizes │ │ ├── _forms.scss # → Form related variables │ │ └── _spacings.scss # → Margins and paddings │ ├── views/ # → Templates, archives, pages and views go here │ │ ├── _404.scss # → Default 404 styles │ │ ├── _comments.scss # → Comment styles (optional) │ │ ├── _front-page.scss # → Front page styles (empty by default) │ │ └── _search.scss # → Default search result styles ├── screenshot.png # → Theme screenshot for WP admin ├── search.php # → Default search view ├── sidebar.php # → Default sidebar (optional) ├── single.php # → Default single article or CPT view ├── style.css # → Theme meta information ├── svg/ # → Your theme SVG graphics and icons └── template-parts/ # → WordPress template parts. Modules go under this folder. ├── header/ # → Header modules │ ├── branding.php # → Site branding │ ├── navigation.php # → Site navigation └── hero.php # → Default hero 示例2 Twenty Seventeen Theme ...

2022-01-13 · 5 min · Duke Yin

wp_remote_get 时出现 curl error 60: ssl certificate problem: certificate has expired 错误

可能1 Let's Encrypt CA证书在2021年9月过期,可能会导致此错误,解决方法: CentOS7 服务器命令行运行: yum update ca-certificates 可能2 WordPress的自带CA证书过期,可以从如下地址下载: https://github.com/WordPress/WordPress/blob/master/wp-includes/certificates/ca-bundle.crt 之后替换到站点目录下的: /wp-cinludes/certificates/ca-bundle.crt 问题即可解决。

2021-10-12 · 1 min · Duke Yin