توسعه، آزمایش و استقرار برنامه های افزودنی خود را برای همه CI های محبوب از یک پایگاه کد واحد

💡 تصویر ویژگی یک خط لوله معمولی CI/CD را نشان می دهد که بخشی از آن توسط OpenAI DALL-E ترسیم شده است، اما در این مقاله، ما می خواهیم چیزی مفید را توسعه دهیم.
فهرست مطالب
این یک آموزش نسبتاً کوتاه در مورد چگونگی توسعه، آزمایش و استقرار پسوندهای CI برای GitHub Actions، Azure Pipelines و CircleCI از یک monorepo است و بر اساس تجربه ایجاد افزونههای Qodana CI است.
از قالب های رسمی شروع کنید
بیایید پشته فناوری را برای برنامه های افزودنی CI خود انتخاب کنیم.
باشه انتخاب نمیکنم من فقط به شما می گویم که چرا از TypeScript و node.js برای برنامه های افزودنی استفاده کردم.
مزایای استفاده از اقدامات مبتنی بر JS:
- انعطاف پذیرتر از رویکردهای مبتنی بر bash/Dockerfile
- نوشتن تست ها نسبتا ساده است
منفی
پس بیایید یک اقدام مبتنی بر TypeScript بنویسیم!
اقدامات GitHub
خواندن اسناد اقدامات GitHub راحتتر از Azure بود، بنابراین توصیه میکنم شروع به نوشتن و آزمایش برنامههای افزودنی خود در GitHub با استفاده از اقدامات قالب/تایپ اسکریپت-اکشن رسمی کنید. الگوی ذکر شده نقطه شروع خوبی را فراهم می کند. من مراحل را در اینجا تکرار نمی کنم. با آن بازی کنید، چیزهای ساده بنویسید و سپس برای مراحل بعدی به اینجا برگردید.
خطوط لوله لاجورد
GitHub Actions بر روی زیرساخت Azure ساخته شده است، بنابراین انتقال اکشن GitHub شما به Azure Pipelines باید نسبتا آسان باشد.
بنابراین،
- “عمل” تبدیل به “وظیفه” می شود
- کمی متفاوت بسته بندی شده، توزیع شده و به روشی دیگر نصب شده است
و تعریف تکلیف task.json
همان عمل یک است action.yml
.
برای مثال داشتن موارد زیر action.yml
:
name: 'Your name here'
description: 'Provide a description here'
author: 'Your name or organization here'
inputs:
milliseconds: # change this
required: true
description: 'input description here'
default: 'default value if applicable'
runs:
using: 'node16'
main: 'dist/index.js'
“به راحتی” به وظیفه Azure زیر ترجمه می شود:
{
"$schema": "https://raw.githubusercontent.com/Microsoft/azure-pipelines-task-lib/master/tasks.schema.json",
"id": "822d6cb9-d4d1-431b-9513-e7db7d718a49",
"name": "YourTaskNameHere",
"friendlyName": "Your name here",
"description": "Provide a description here",
"helpMarkDown": "Provide a longer description here",
"author": "Your name or organization here",
"version": {
"Major": 1,
"Minor": 0,
"Patch": 0
},
"instanceNameFormat": "YourTaskNameHere",
"inputs": [
{
"name": "milliseconds",
"type": "string",
"label": "label name here",
"defaultValue": "default value if applicable",
"required": true,
"helpMarkDown": "input description here"
}
],
"execution": {
"Node10": {
"target": "index.js"
}
}
}
از یک مثال ساده، می توان متوجه شد که چرا پیشنهاد کردم با GitHub Actions شروع کنید. اما بیایید ادامه دهیم.
برای شروع کار جدید Azure Pipelines براق خود، پیشنهاد می کنم فقط دایرکتوری اکشن را کپی کنید و سپس مراحل را از اسناد رسمی Azure پیاده سازی کنید – این کار بسیار ساده است.
- ايجاد كردن
vss-extension.json
- ايجاد كردن
task.json
و آن را در خود قرار دهیدdist
دایرکتوری (در واقع بهتر است آن را پس از نام وظیفه نامگذاری کنید) - اگر از هر روشی استفاده کردید از
@actions/core
یا@actions/github
در اقدام خود، باید آنها را با روش های مربوطه جایگزین کنیدazure-pipelines-task-lib
(به عنوان مثالcore.getInput
->tl.getInput
)
API از azure-pipelines-task-lib
شبیه است به @actions/core
و دیگر @actions/*
کتابخانه ها به عنوان مثال، ما یک روش برای به دست آوردن پارامترهای ورودی داریم:
export function getInputs(): Inputs {
return {
milliseconds: core.getInput('milliseconds'),
}
}
و همینطور برای Azure Pipelines:
export function getInputs(): Inputs {
return {
milliseconds: tl.getInput('milliseconds'),
}
}
برای موارد واقعی تر، در صورت تمایل به کاوش در ابزارهای پایگاه کد Qodana GitHub Actions و ابزارهای وظیفه Azure Pipelines ما بپردازید.
monorepo را ایجاد کنید
ما قصد داریم از فضاهای کاری npm برای مدیریت monorepo استفاده کنیم.
کد عملکرد و وظیفه خود را در زیر شاخه ها قرار دهید (مثلاً github
) از monorepo تازه ایجاد شده شما. و سپس یک را ایجاد کنید package.json
فایل در دایرکتوری ریشه
{
"name": "@org/ci",
"version": "1.0.0",
"description": "Common code for CI extensions",
"license": "Apache-2.0",
"workspaces": [
"github",
"azure"
],
"devDependencies": {
"typescript": "latest",
"eslint": "latest",
"eslint-plugin-github": "latest",
"eslint-plugin-jest": "latest",
"prettier": "latest",
"ts-node": "latest"
}
}
بنابراین ساختار monorepo به شکل زیر است:
...
├── action.yaml
├── github/
├── azure/
└── package.json
پس از اجرای تنظیمات فضای کاری، می توانید وظایف و اقدامات را از دایرکتوری ریشه اجرا کنید. به عنوان مثال، برای اجرای build
وظیفه از github
دایرکتوری، می توانید از دستور زیر استفاده کنید:
npm run -w github build
کد را بین اقدامات و وظایف به اشتراک بگذارید
با ارزش ترین بخش استفاده از رویکرد monorepo از اینجا شروع می شود: می توانید کد را بین اقدامات و وظایف خود به اشتراک بگذارید.
قرار است مراحل زیر را انجام دهیم:
- ایجاد یک
common
دایرکتوری در ریشه monorepo، یک پروژه فرعی برای کد مشترک - به روز رسانی
tsconfig.json
پیکربندی های کامپایلر از همه زیرمجموعه ها برای ساخت پروژه مناسب
در ابتدا بیایید پایه را ایجاد کنیم tsconfig
– tsconfig.base.json
با تنظیمات پایه ای که قرار است در همه پروژه های فرعی استفاده شود:
{
"compilerOptions": {
"target": "es6",
"module": "commonjs",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"composite": true
},
"exclude": ["node_modules", "**/*.test.ts", "*/lib/**"]
}
سپس یک ساده ایجاد کنید tsconfig.json
در ریشه پروژه:
{
"references": [
{ "path": "common" },
{ "path": "azure" },
{ "path": "github" }
],
"files": []
}
سپس common/tsconfig.json
:
{
"extends": "../tsconfig.base.json",
"compilerOptions": {
"outDir": "./lib",
"rootDir": "."
},
"files": ["include your files here or use typical include/exclude patterns"]
}
و در نهایت، به روز رسانی tsconfig.json
فایل های موجود در پروژه های فرعی (آنها اساساً یکسان هستند، به عنوان مثال github/tsconfig.json
):
{
"extends": "../tsconfig.base.json",
"compilerOptions": {
"outDir": "./lib",
"rootDir": "./src"
},
"references": [
{ "path": "../common" }
]
}
اکنون می توانید از کد اشتراک گذاری شده استفاده کنید common
دایرکتوری در اقدامات و وظایف شما. به عنوان مثال، ما یک qodana.ts
فایل در common
دایرکتوری که حاوی تابع است getQodanaUrl
که URL را به ابزار Qodana CLI برمی گرداند. و ما از آن هم در اعمال و هم در وظایف استفاده می کنیم.
بسازید و منتشر کنید
شما در حال حاضر گردشهای کاری GitHub را از قالب پیکربندی کردهاید تا اقدامات شما را در نسخههای مخزن خود منتشر کند.
برای نسخههای خودکار، از GH CLI استفاده میکنیم، و یک اسکریپت ساده داریم که یک تغییرات در نسخههای مخزن منتشر میکند:
#!/usr/bin/env bash
previous_tag=0
for current_tag in $(git tag --sort=-creatordate)
do
if [ "$previous_tag" != 0 ];then
printf "## Changelog\n"
git log ${current_tag}...${previous_tag} --pretty=format:'* %h %s' --reverse | grep -v Merge
printf "\n"
break
fi
previous_tag=${current_tag}
done
و گردش کار GitHub که آن را اجرا می کند:
name: 'Release'
on:
push:
tags:
- '*'
permissions:
contents: write
jobs:
github:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- run: |
./changelog.sh > changelog.md
gh release create ${GITHUB_REF##*/} -F changelog.md
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
برای انتشار وظایف Azure Pipelines، می توانید از رویکرد رسمی Azure استفاده کنید. با این حال، همچنین می توانید همین کار را در زیرساخت اقدامات GitHub انجام دهید زیرا ابزار ناشر آنها را می توان در هر جایی نصب کرد. بنابراین، در مورد ما، با یک کار گردش کار ساده GitHub حل می شود:
azure:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set Node.js 12.x
uses: actions/setup-node@v3.6.0
with:
node-version: 12.x
- name: Install dependencies
run: npm ci && cd vsts/QodanaScan && npm ci && npm i -g tfx-cli
- name: Package and publish
run: |
cd vsts && npm run azure
mv JetBrains.qodana-*.vsix qodana.vsix
tfx extension publish --publisher JetBrains --vsix qodana.vsix -t $AZURE_TOKEN
env:
AZURE_TOKEN: ${{ secrets.AZURE_TOKEN }}
با این تنظیم، هر انتشار به طور خودکار در هر فشار برچسب اتفاق می افتد.
git tag -a v1.0.0 -m "v1.0.0" && git push origin v1.0.0
CircleCI
آه، بله، این مقاله به گوی CircleCI نیز اشاره کرده است… راه اندازی CircleCI ساده است اما از پسوندهای TypeScript پشتیبانی نمی کند، بنابراین باید کد خود را در یک تصویر داکر یا یک باینری بسته بندی کنید و آن را در آنجا اجرا کنید. تنها دلیلی که در این پست گنجانده شده است این است که ما گوی خود را با رویکرد monorepo می سازیم که به خوبی کار می کند.
فقط قالب رسمی orb را پیاده سازی کنید و آن را در monorepo خود قرار دهید، بنابراین ساختار به شکل زیر است:
...
├── action.yaml
├── github/
├── azure/
├── src/ # orb source code here
└── package.json
و تعهد را فراموش نکنید .circleci/
دایرکتوری به مخزن خود برای ایجاد CircleCI lint، آزمایش و انتشار orb خود.
اگر این پست ده واکنش در اینجا داشته باشد، قسمت دوم را درباره انتشار و آزمایش خطوط لوله Azure و گوی های CircleCI اضافه خواهم کرد.