構建 CI/CD 工作流——使用 GitHub Actions 自動部署 WordPress 主題
已發表: 2022-11-17介紹
在現代 Web 開發中,通常需要執行多個步驟來構建代碼並將其部署到生產環境中。 對於 WordPress 主題或插件,這可能意味著安裝 Composer 和/或 Node.js 依賴項、編譯 CSS、轉譯 JavaScript 並將文件上傳到您的服務器。
在本文中,我們將探討如何使用 GitHub Actions 簡化 WordPress 部署過程。 我們將創建一個 GitHub Actions 工作流程,以自動構建 WordPress 主題並將其部署到您的 Pressidium WordPress 站點。
如果您只是點擊了工作流程,請滾動到這篇文章的底部並立即開始。 但是,我們鼓勵您閱讀整篇文章,我們在其中詳細解釋了一切是如何工作的!
先決條件
- 對 Git 有基本的了解(創建存儲庫、提交和推送代碼、創建分支等)
- 熟悉 GitHub 的界面
Web 開發中的“部署”是什麼?
Web 開發中的部署是將更改推送到遠程環境,使網站或應用程序可供使用的過程。
有時我們使用術語“部署”來指代一組活動——包括構建、測試和傳輸文件——而其他時候我們將它用作文件傳輸的同義詞。 在本文中,我們始終區分構建和部署。
有很多方法可以將您網站的文件推送到託管服務提供商。 在我們的例子中,我們將使用安全文件傳輸協議 (SFTP),顧名思義,它是一種通過安全通道(例如 SSH)傳輸文件的網絡協議。
什麼是 GitHub 操作?
GitHub Actions 是一個持續集成和持續交付 (CI/CD) 平台,可讓您自動化構建和部署管道。
在接下來的段落中,我們將探討如何創建 GitHub Actions 工作流程,以利用支持暫存環境的託管服務提供商來構建和部署 WordPress 主題。
暫存是用於測試的預生產環境,它幾乎是生產環境的精確複製品。 它試圖盡可能地反映實際的生產環境,因此可以在將更改應用到生產環境之前對其進行測試。
如果您已經在使用 Pressidium,則所有計劃都免費提供暫存環境。 閱讀這篇知識庫文章了解更多信息。
什麼是 GitHub Actions 工作流程?
工作流是由一個或多個事件觸發並運行一個或多個作業的自動化過程。 每個作業包含一個或多個步驟。 最後,每個步驟都可以運行腳本或 GitHub 操作。 一個存儲庫可以有多個工作流,執行不同的任務。
使用 GitHub Actions 工作流有很多好處。
- 你花更少的時間做手工、勞動密集型、重複性的工作; 更多時間增值
- 通過實施特定的部署過程,更容易在不同環境中保持一致
- 它與您的 GitHub 存儲庫集成,允許您跟踪更改、訪問部署日誌等。
- 它是可重用的,這意味著您可以在所有存儲庫中使用相同的工作流程
入門
讓我們通過在 GitHub 存儲庫的.github/workflows/
目錄中創建一個新的 YAML 文件來開始您的第一個工作流程。 我們將從一個簡單的工作流開始,自動部署到生產環境,因此我們將此文件命名為deploy.yml
。
# .github/workflows/deploy.yml name: deploy on: push: branches: # Pushing to the `main` branch # will trigger our workflow - main
我們使用on
關鍵字來定義哪些事件可以觸發工作流。 在此示例中,工作流將在向main
分支進行推送時運行。
當某些文件發生變化時,我們可能根本不需要部署,比如README.md
。 我們可以使用on.push.paths-ignore
來排除文件路徑模式。
name: deploy on: push: branches: - main paths-ignore: - 'bin/**' - 'README.m
創建你的第一份工作
一個工作流由一個或多個作業組成。 在此示例中,您將使用單個deploy
作業將文件上傳到您網站的生產環境。
name: deploy on: [...] jobs: deploy: runs-on: ubuntu-latest steps: [...]
每個作業都在運行器環境中運行,由runs-on
指定。 在上面的 YAML 塊中,我們使用ubuntu-latest
,這是一個 Ubuntu Linux 虛擬機 (VM),由 GitHub 託管,預裝了運行器應用程序和其他工具。
您可以使用 GitHub 託管的運行器或託管您自己的運行器並自定義用於運行作業的環境。 但是,後者超出了本文的範圍。
檢查您的 Git 存儲庫
在您對代碼執行任何有意義的操作之前,您必須檢查您的存儲庫,以便您的工作流可以訪問它。 您可以為此使用結帳操作。
jobs: deploy: runs-on: ubuntu-latest steps: - name: Checkout # Checkout our repository under `${GITHUB_WORKSPACE}`, # so our workflow can access it uses: actions/checkout@v3 with: # Fetch the entire Git history fetch-depth: 0
我們將fetch-depth
指定為0
,這將導致獲取整個 Git 歷史記錄。 我們需要它來僅上傳在後續運行中已更改的文件。
創建 SFTP 用戶
要將文件上傳到託管服務提供商,您需要 SFTP 連接詳細信息(即主機、網絡端口和路徑)和 SFTP 用戶。
大多數時候,您可以找到這些詳細信息並通過託管服務提供商的儀表板創建 SFTP 用戶。 一些網絡託管服務商還會通過電子郵件向您發送這些詳細信息。
如果您已經在使用 Pressidium,請按照以下步驟操作:
- 登錄到您的 Pressidium 儀表板
- 從儀表板側邊欄中選擇網站菜單選項
- 點擊您網站的名稱
- 通過單擊導航欄上的鏈接導航到SFTP選項卡
- 記下您的SFTP 連接詳細信息
- 創建一個新的SFTP 用戶
要創建新的 SFTP 用戶:
- 點擊新建
- 選擇環境(生產或登台)
- 提供用戶名和密碼(建議使用強密碼、混合大小寫拉丁字符、數字和特殊字符)
- 記下您輸入的用戶名和密碼
- 點擊創建創建用戶
在第二步,您應該選擇要部署到的環境。 對於此示例,我們將為每個環境創建一個用戶。
有關通過 SFTP 訪問 Pressidium WordPress 站點的更多信息,請參閱此知識庫文章。
存儲敏感信息
您可以直接在 GitHub Actions 工作流程中輸入 SFTP 連接詳細信息和 SFTP 用戶憑據。 但是,將敏感信息存儲在您的存儲庫中並不是一個好主意。
GitHub 提供加密的秘密作為在您的組織、存儲庫或存儲庫環境中存儲敏感信息的一種方式。
為存儲庫創建加密的秘密:
- 登錄您的 GitHub 帳戶
- 導航到存儲庫的主頁
- 在您的存儲庫名稱下,單擊設置
- 選擇Secrets並單擊Actions ,在邊欄的 Security 部分下
- 單擊新建存儲庫密碼按鈕
- 輸入機密名稱及其值
- 單擊添加秘密
你應該得到一個類似於這個的秘密列表:
-
SFTP_HOST
SFTP 服務器的主機名 SFTP_PORT
SFTP 服務器的端口SFTP_USER
用於身份驗證的用戶名SFTP_PASS
用於身份驗證的密碼
通過 SFTP 上傳文件
要通過 SFTP 上傳文件,您可以使用—您猜對了—另一個 GitHub 操作。
有多個 SFTP 客戶端和 GitHub Actions 可供選擇。 我們使用了自己的lftp-mirror-action ,它在底層使用lftp
。 一個支持SFTP的文件傳輸工具,可以並行傳輸多個文件。
- name: Deploy via SFTP uses: pressidium/lftp-mirror-action@v1 with: host: ${{ secrets.SFTP_HOST }} port: ${{ secrets.SFTP_PORT }} user: ${{ secrets.SFTP_USER }} pass: ${{ secrets.SFTP_PASS }} remoteDir: '/demo-www/wp-content/themes/my-theme' options: '--verbose'
配置lftp-mirror-action的輸入非常簡單:
- 您的 SFTP 連接詳細信息和 SFTP 用戶憑據可以通過
secrets
上下文訪問(例如${{ secrets.SFTP_HOST }}
) -
remoteDir
是主題目錄的路徑 '--verbose'
選項將啟用詳細輸出,這將記錄所有文件傳輸(對故障排除很有用)
在 Pressidium 上,路徑格式如下:
-
YOUR_INSTALLATION_NAME-www/
作為生產環境的根路徑 YOUR_INSTALLATION_NAME-dev-www/
作為暫存環境的根路徑
其中YOUR_INSTALLATION_NAME
是您的安裝名稱。 請注意,帳戶所有者有一個 SFTP 帳戶,顯示為“主”帳戶,可以訪問所有網站,因此它們的路徑將與上述路徑不同。 建議避免使用此帳戶,而是為您要訪問的每個網站創建一個單獨的帳戶。
或者,您可以在您的存儲庫中創建一個.lftp_ignore
文件,包括您希望從部署中排除的任何文件模式。
這是一個可能看起來像的示例:
## Directories to ignore .vscode/** .env.** .git/ .github/ ## Files to ignore .gitignore package.json package-lock.json composer.json composer.lock
把它們放在一起
name: deploy on: push: branches: - main paths-ignore: - 'bin/**' - 'README.md' jobs: deploy: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v3 with: fetch-depth: 0 - name: Deploy via SFTP uses: pressidium/lftp-mirror-action@v1 with: host: ${{ secrets.SFTP_HOST }} port: ${{ secrets.SFTP_PORT }} user: ${{ secrets.SFTP_USER }} pass: ${{ secrets.SFTP_PASS }} remoteDir: '/demo-www/wp-content/themes/my-theme' options: '--verbose'
而已! 您的工作流程現在可以自動部署您的 WordPress 主題。
構建和部署您的 WordPress 主題
到目前為止,我們通過只關注部署文件而忽略了可能需要安裝的任何依賴項、構建可能需要運行的腳本等等來使事情變得簡單。
作為示例設置,我們將使用具有兩個分支的 GitHub 存儲庫:
- 穩定的、生產就緒的
main
分支,將部署到生產環境 - 未經測試的
preview
分支,作為功能的集成分支,將部署到暫存環境
是時候引入build
作業並將我們的工作流程重命名為build-deploy
,因為它將負責構建和部署我們的代碼。
name: build-deploy on: push: branches: - main paths-ignore: - 'bin/**' - 'README.md' jobs: build: runs-on: ubuntu-latest steps: [...] deploy: [...]
檢查您的 Git 存儲庫
每個作業都在運行器圖像的新實例中運行,因此您必須在build
作業中再次檢查您的 GitHub 存儲庫。
build: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v3
您不必在構建作業中獲取整個 Git 歷史記錄,因此您可以堅持使用操作輸入的默認值。
安裝依賴項
一些主題使用第三方包和庫。 如果您的主題需要任何 PHP 和/或 JavaScript 包,您可能需要使用包管理器,例如 Composer、npm 或 yarn。
為了這個示例,我們假設您需要安裝 Composer 和 Node.js 依賴項。 對我們來說幸運的是,有現成的操作。
steps: - name: Checkout uses: actions/checkout@v3 - name: Install Composer dependencies uses: php-actions/composer@v6 - name: Install Node.js LTS uses: actions/setup-node@v3 with: node-version: 'lts/*' cache: 'yarn' - name: Install Node.js dependencies run: yarn install
composer操作將默認運行composer install
,因此您不必配置其任何輸入參數。
對於設置節點操作,我們為node-version
和cache
輸入設置自定義值以指定我們想要:
- 獲得 Node.js 的長期支持(或 LTS)版本
- 緩存通過 yarn 包管理器獲取的任何依賴項
然後,下一步將運行yarn install
來安裝 Node.js 依賴項。 請記住,一個步驟可以運行腳本或 GitHub 操作。
請注意,緩存可以顯著加快您的工作流程。 每次工作流運行時都下載依賴項會導致運行時間更長。 您可以使用cache操作緩存作業的依賴項(這也是setup-node
操作在後台執行的操作),從而加快重新創建文件所需的時間。
運行構建過程
再一次,我們假設您需要執行一個“構建”過程——您可能需要運行一個預處理器來編譯您的樣式表、轉換您的 ES6+ 腳本等。這通常意味著您已經在您的文件中定義了一個build
腳本package.json
文件。
因此,您將需要另一個步驟來運行該構建過程。
- name: Build theme run: yarn run build
如果您需要main
分支和preview
分支運行不同的腳本(例如, main
分支build
, preview
staging
),您可以這樣做:
- name: Build theme run: | if [[ "${{ github.base_ref }}" == "main" || "${{ github.ref }}" == "refs/heads/main" ]]; then yarn run build else yarn run staging fi
最後,由於每個作業都在運行器圖像的新實例中運行,因此工作流程中的作業是完全隔離的。 這意味著,您需要一種方法來臨時存儲剛剛構建的文件,以便deploy
作業可以訪問它們。 輸入工件。
神器
工件允許您在作業完成後保留數據,因此您可以在工作流中的作業之間共享數據。
讓我們為您的build
作業引入一個額外的步驟,以使用Upload-Artifact操作將構建步驟中生成的數據保留 1 天。 我們假設 Composer 在vendor/
目錄中安裝它的依賴項,並且我們的build
腳本將文件導出到dist/
目錄中。
- name: Upload artifact uses: actions/upload-artifact@v3 with: name: my-theme-build path: | dist/ vendor/ retention-days: 1
根據存儲庫的大小和推送的頻率,您可能需要查看 GitHub 的使用限制、計費和管理。
在撰寫本文時,默認情況下,GitHub 將構建日誌和工件存儲 90 天,並在“GitHub 免費”計劃中提供 500 MB 的存儲空間。
按順序運行作業
工作流由一個或多個作業組成,默認情況下它們並行運行。 在我們的例子中,我們必須先構建我們的主題,然後才能部署它。 要按順序運行build
和deploy
作業,您必須使用jobs.<job_id>.needs
關鍵字定義依賴項。
deploy: runs-on: ubuntu-latest needs: build
在下面的示例中,我們聲明build
作業必須在deploy
作業運行之前成功完成。
name: build-deploy on: [...] jobs: build: runs-on: ubuntu-latest steps: [...] deploy: runs-on: ubuntu-latest needs: build steps: [...]
下載工件
在上傳構建步驟中構建的任何數據之前,您必須先下載它們。 讓我們重新審視deploy
作業並引入一個額外的步驟。
- name: Download artifact uses: actions/download-artifact@v3 with: name: my-theme-build path: .
您可以使用類似於Upload-Artifact的Download -Arti fact操作。 確保為這兩個操作指定相同的名稱——在本例中為my-theme-build
。
把它們放在一起
name: build-deploy on: push: branches: - main paths-ignore: - 'bin/**' - 'README.md' jobs: build: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v3 - name: Install Composer dependencies uses: php-actions/composer@v6 - name: Install Node.js LTS uses: actions/setup-node@v3 with: node-version: 'lts/*' cache: 'yarn' - name: Install Node.js dependencies run: yarn install - name: Build theme run: | if [[ "${{ github.base_ref }}" == "main" || "${{ github.ref }}" == "refs/heads/main" ]]; then yarn run build else yarn run staging fi - name: Upload artifact uses: actions/upload-artifact@v3 with: name: my-theme-build path: | dist/ vendor/ retention-days: 1 deploy: runs-on: ubuntu-latest needs: build steps: - name: Checkout uses: actions/checkout@v3 with: fetch-depth: 0 - name: Download artifact uses: actions/download-artifact@v3 with: name: my-theme-build path: . - name: Deploy via SFTP uses: pressidium/lftp-mirror-action@v1 with: host: ${{ secrets.SFTP_HOST }} port: ${{ secrets.SFTP_PORT }} user: ${{ secrets.SFTP_USER }} pass: ${{ secrets.SFTP_PASS }} remoteDir: '/demo-www/wp-content/themes/my-theme' options: '--verbose'
現在你有了一個 GitHub Actions 工作流程,當你推送到main
分支時,它可以自動構建代碼並將其部署到生產環境! 但是,在本文開頭,我們描述了一個能夠部署到生產環境和暫存環境的工作流,具體取決於您要推送到的分支。 如果您仍然願意,請繼續閱讀!
將主題部署到多個環境
部署到多個環境可能需要稍微更改您的工作流程。 例如,通常建議為每個環境設置單獨的 SFTP 用戶,並將其視為最佳實踐。 在 Pressidium 中,SFTP 用戶對於網站的生產環境和登台環境是不同的。
因此,讓我們為每個用戶的用戶名/密碼創建不同的秘密。 這意味著,我們更新的加密秘密列表應該如下所示:
-
SFTP_HOST
-
SFTP_PORT
-
SFTP_PROD_USER
-
SFTP_PROD_PASS
-
SFTP_STAG_USER
-
SFTP_STAG_PASS
您可能還必須更新主機和網絡端口。 不過,在這種情況下,無需更改它們,因為它們對於兩種環境都是相同的。
設置環境變量
環境變量是一個變量,由名稱/值對組成,是進程運行環境的一部分。
在 GitHub Actions 工作流程中,您可以使用env
關鍵字來設置範圍為以下的自定義環境變量:
- 整個工作流程,通過在工作流程的頂層使用
env
- 工作流中的作業,通過在該作業級別使用
env
- 作業中的特定步驟,通過在該步驟級別使用
env
您還可以將環境變量附加到$GITHUB_ENV
,這使得該變量可用於工作流作業中的任何後續步驟。
如您所見,有多種方法可以構建您的工作流。 因此,請隨意使用對您來說最有意義的那個。
在我們的例子中,我們在作業的一個步驟中設置環境變量以臨時存儲值並從稍後在我們的工作流中運行的另一個步驟訪問它們。 我們將在將事件push
送到特定分支的步驟中將環境變量附加到$GITHUB_ENV
以展示如何有條件地設置自定義變量。
- name: Set environment variables (main) if: github.ref == 'refs/heads/main' run: | echo "SFTP_USER=${{ secrets.SFTP_PROD_USER }}" >> $GITHUB_ENV echo "SFTP_PASS=${{ secrets.SFTP_PROD_PASS }}" >> $GITHUB_ENV echo "DEPLOY_PATH=/demo-www/wp-content/themes/my-theme" >> $GITHUB_ENV - name: Set environment variables (preview) if: github.ref == 'refs/heads/preview' run: | echo "SFTP_USER=${{ secrets.SFTP_STAG_USER }}" >> $GITHUB_ENV echo "SFTP_PASS=${{ secrets.SFTP_STAG_PASS }}" >> $GITHUB_ENV echo "DEPLOY_PATH=/demo-dev-www/wp-content/themes/my-theme" >> $GITHUB_ENV
我們使用if
關鍵字將每個步驟限製到特定分支。 這樣, Set environment variables (main)將僅在將更改推送到main
分支時運行。
每個環境的$DEPLOY_PATH
也可能不同。
例如,在 Pressidium 上:
- 生產環境的路徑遵循
/<WEBSITE_NAME>-www/
格式 - 暫存環境的路徑遵循
/<WEBSITE_NAME>-dev-www/
格式
設置輸出
我們想使用我們剛剛設置的環境變量作為 GitHub Action 的輸入,它將通過 SFTP 傳輸文件。
不幸的是,目前似乎無法將環境變量引用為 GitHub 操作的輸入。 您可以通過創建一個額外的步驟來解決這個問題,該步驟將輸出您稍後需要用作輸入的值。
- name: Set outputs # Workaround to reference environment variables as inputs # using step outputs, since we can't pass environment # variables as inputs at the moment. id: sftp_details run: | echo "user=${SFTP_USER}" >> $GITHUB_OUTPUT echo "pass=${SFTP_PASS}" >> $GITHUB_OUTPUT echo "deploy_path=${DEPLOY_PATH}" >> $GITHUB_OUTPUT
您現在擁有sftp_details
步驟的user
、 pass
和deploy_path
輸出,您可以使用它們將這些值引用為下一步的輸入。
上傳文件到不同的環境
通過 SFTP 上傳文件與以前幾乎相同,但您將使用上一步的輸出,而不是引用secrets
上下文和硬編碼remoteDir
。
- name: Deploy via SFTP uses: pressidium/lftp-mirror-action@v1 with: host: ${{ secrets.SFTP_HOST }} port: ${{ secrets.SFTP_PORT }} user: ${{ steps.sftp_details.outputs.user }} pass: ${{ steps.sftp_details.outputs.pass }} remoteDir: ${{ steps.sftp_details.outputs.deploy_path }} options: '--verbose'
使用${{ steps.<step_id>.outputs.<output_name> }}
訪問步驟的輸出。 例如, ${{ steps.sftp_details.outputs.user }}
訪問sftp_details
步驟的user
輸出。
呼,終於! 您的工作流程現在可以構建您的 WordPress 主題並將其部署到您的生產和暫存環境。
整合完整的工作流程
name: build-deploy on: push: branches: # Pushing to any of the following # branches will trigger our workflow - main - preview paths-ignore: # When all the path names match patterns in `paths-ignore` # the workflow will not run. We don't want to do anything # if we have changed *only* (some of) these files - 'bin/**' - 'README.md' jobs: build: runs-on: ubuntu-latest steps: - name: Checkout # Checkout our repository under `${GITHUB_WORKSPACE}`, # so our workflow can access it uses: actions/checkout@v3 - name: Install Composer dependencies # This will run `composer install` # since that's its default command uses: php-actions/composer@v6 - name: Install Node.js LTS # We use the LTS version of Node.js # and cache packages installed via yarn uses: actions/setup-node@v3 with: node-version: 'lts/*' cache: 'yarn' - name: Install Node.js dependencies run: yarn install - name: Build theme # Run the `build` script for production, # and the `staging` script for staging run: | if [[ "${{ github.base_ref }}" == "main" || "${{ github.ref }}" == "refs/heads/main" ]]; then yarn run build else yarn run staging fi - name: Upload artifact # Persist data produced during the build steps # with a retention period of 1 day uses: actions/upload-artifact@v3 with: name: my-theme-build path: | dist/ vendor/ retention-days: 1 deploy: runs-on: ubuntu-latest needs: build steps: - name: Checkout uses: actions/checkout@v3 with: # Fetch the entire Git history fetch-depth: 0 - name: Download artifact uses: actions/download-artifact@v3 with: name: my-theme-build path: . - name: Set environment variables (main) if: github.ref == 'refs/heads/main' run: | echo "SFTP_USER=${{ secrets.SFTP_PROD_USER }}" >> $GITHUB_ENV echo "SFTP_PASS=${{ secrets.SFTP_PROD_PASS }}" >> $GITHUB_ENV echo "DEPLOY_PATH=/demo-www/wp-content/themes/my-theme" >> $GITHUB_ENV - name: Set environment variables (preview) if: github.ref == 'refs/heads/preview' run: | echo "SFTP_USER=${{ secrets.SFTP_STAG_USER }}" >> $GITHUB_ENV echo "SFTP_PASS=${{ secrets.SFTP_STAG_PASS }}" >> $GITHUB_ENV echo "DEPLOY_PATH=/demo-dev-www/wp-content/themes/my-theme" >> $GITHUB_ENV - name: Set outputs # Workaround to reference environment variables as inputs # using step outputs, since we can't pass environment # variables as inputs at the moment. id: sftp_details run: | echo "user=${SFTP_USER}" >> $GITHUB_OUTPUT echo "pass=${SFTP_PASS}" >> $GITHUB_OUTPUT echo "deploy_path=${DEPLOY_PATH}" >> $GITHUB_OUTPUT - name: Deploy via SFTP uses: pressidium/lftp-mirror-action@v1 with: host: ${{ secrets.SFTP_HOST }} port: ${{ secrets.SFTP_PORT }} user: ${{ steps.sftp_details.outputs.user }} pass: ${{ steps.sftp_details.outputs.pass }} remoteDir: ${{ steps.sftp_details.outputs.deploy_path }} options: '--verbose'
您還可以在此 GitHub 存儲庫上找到示例 WordPress 主題和 GitHub Actions 工作流程。
結論
你有它! GitHub Actions 是一個強大的工具,可以輕鬆地自動構建和部署您的 WordPress 主題和插件。
我們僅僅觸及了您可以使用 GitHub Actions 實現的目標的皮毛。 您的後續步驟可能是自動運行您可能擁有的任何測試、打開問題或在部署完成時在 Slack 上通知,等等。
查看 GitHub Marketplace,在撰寫本文時,您可以在其中找到超過 15,000 個可在 GitHub Actions 工作流程中使用的操作。
那你還在等什麼?
- 在 GitHub 上查看此存儲庫的工作流程
- 在 Git 存儲庫中的
.github/workflows/
下創建一個新的 YAML 文件 - 享受自動化構建和部署
部署愉快!