Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5c86a13559 | ||
|
|
0c2474ba20 | ||
|
|
b4387b0616
|
||
|
|
7f0c50801d
|
||
|
|
3893281fa1 | ||
|
|
22a9351de7
|
||
|
|
257c3edd85
|
||
|
|
a45659b3cc
|
||
|
|
86d353ec2d
|
||
|
|
71f06a3d68
|
||
|
|
8ce34c75f3 | ||
|
|
688c3a4b97
|
||
|
|
cff22c88dd | ||
|
|
47c70471e1 | ||
|
|
24f3311006 | ||
|
|
9a175925b6 | ||
|
|
716cc5f6f1 | ||
|
|
b3638f4d63 | ||
|
|
c6487dc258 | ||
|
|
cc7f09fa22 | ||
|
|
968f41d68d | ||
|
|
c1a17a262a | ||
|
|
3444265473 | ||
|
|
fcf6895feb | ||
|
|
5bd12dab15 | ||
|
|
7472b2c761 | ||
|
|
9ee672504f | ||
|
|
ff5a50bad8 | ||
|
|
68dcfc303c |
No files matched your search
@@ -2,12 +2,21 @@
|
|||||||
#/ public-key encryption for .env files /
|
#/ public-key encryption for .env files /
|
||||||
#/ [how it works](https://dotenvx.com/encryption) /
|
#/ [how it works](https://dotenvx.com/encryption) /
|
||||||
#/----------------------------------------------------------/
|
#/----------------------------------------------------------/
|
||||||
|
DOTENV_PUBLIC_KEY_DEV="02a9d0f6522086b04ac7763e008a6ad0273c58258715e613c977fd6c82a2030d92"
|
||||||
|
|
||||||
|
# .env.dev
|
||||||
|
#/-------------------[DOTENV_PUBLIC_KEY]--------------------/
|
||||||
|
#/ public-key encryption for .env files /
|
||||||
|
#/ [how it works](https://dotenvx.com/encryption) /
|
||||||
|
#/----------------------------------------------------------/
|
||||||
DOTENV_PUBLIC_KEY="02a9d0f6522086b04ac7763e008a6ad0273c58258715e613c977fd6c82a2030d92"
|
DOTENV_PUBLIC_KEY="02a9d0f6522086b04ac7763e008a6ad0273c58258715e613c977fd6c82a2030d92"
|
||||||
|
|
||||||
# .env
|
# .env
|
||||||
COM_ERMNVLDMR_STATIC_S3_BUCKET="encrypted:BL1vJLB9uPSvsUvrJah4UegRU8uPdFjE7sya+Fae3rwOmVzWsK5+TP4z4YzigTAuwit4FANvANvhRV46se+ZgprYplU8Cw1tZ5mHKO4rWAjif2sJCnsGXUKp8GZ2J7PrMH35MY0YrXX4NVqe18b2NEv2B9K7"
|
COM_ERMNVLDMR_STATIC_S3_BUCKET="encrypted:BE65d5I9m1jrHGVNKDmfGL3Cjb7LjhB4tVWyNzSPU1Zu5Y00+R8NXgqSBrzBnXVj3vVinibjihVt3fStegyiqI52GtSycX1NlFSVJlRFWadUJ6SVK+SYfB7sFKSJ2jKGfwRaXKMzaKCdPWY+ni685oPXU9Rp"
|
||||||
COM_ERMNVLDMR_STATIC_S3_REGION="encrypted:BAj3iuo7tWWNR2V4yQ+LHnFCB4JcZp7TTfUtvv+2FPntNhwc/fV95IeFWz6S0z6aPRkDG+UQzPXNwdMz7y8ZbTHbduDDrgydHu1fST1NfQd2s1Bbpf+yJTG7dPBSc5RSNKZkkpB4v55qg/UC"
|
COM_ERMNVLDMR_STATIC_S3_REGION="encrypted:BPQ2+ms76A+PLFUeKL1Cnz8bdOcsJou03e8AyGwzdhozpcAwhP5yWXSqhTK8ZccAvmfjJcM4NK+x2a2r4g0ALd/UaQDa9xy2eZ6QnXwkoHXu2ce+F86/HuFnzX0qWqYTWi4q+N4="
|
||||||
COM_ERMNVLDMR_STATIC_S3_ENDPOINT_URL="encrypted:BNkQrgsrxtz544vuJbgwWUh5cPjHG5wbmHNcxTUWrzbFJJsdncaAitviCvIrS7Q41w+FiWkssv3D05Tu8Inn2P62E6G3PU4gNxO2oLdmGEdrzUqB/xvxOvLvos42j54QOZf7lOqMPKH6SL2/rheCAo10gSCicCqkfh4xsCAbYpyL"
|
COM_ERMNVLDMR_STATIC_S3_ENDPOINT_URL="encrypted:BCcK2ih1QrABMImpUj31KIQYlbp9zhnafzrXINAwvyCaCjbOst6UGnhhi5M3LtQ+Fhgpx52ZKGjmke1oVxnvU6BBGz/lAbSD5euhHNbJ6EIoSqc25XpcmgucIQGx1cfiJxsL4sDR95FyR3fNaS9KGr005DwQaIRKGg86gALUCPhaLekq/Sd6Nn+TDoqmigLJPozdxp33AFpmWF+EwayYae2u"
|
||||||
COM_ERMNVLDMR_STATIC_AWS_ACCESS_KEY_ID="encrypted:BCsp8p4bp3cB+9grxHo634isRUaFGU3MOc1lr8ClSFRYLjqjqukyrbJCTZWV2Xdo8iQ33EylmbzUltbwzTWMQcjJSvIskesVLyV93q60o/Mu9L9jg/apwHuBgHv4zVuHstJ0zkHWgapbNTIlWD3RCm0ujeX/H1gBH3U="
|
COM_ERMNVLDMR_STATIC_AWS_ACCESS_KEY_ID="encrypted:BPaBvzNo1eH3Z2ro+NFq4zLi4krZQT48h20r0etBfVFLDNS01gh5Uosy70Ip29rC8sa1JoP4Q8isJ2Xz0pr5Vxxa62vVFOJ9wJ6LkXbYF2bUm+UNyjfsIztJsMyiVZfPEEPEEKcniXZ3faqePwgLwCZSTa/Qry6znNmMV5FshSsP"
|
||||||
COM_ERMNVLDMR_STATIC_AWS_SECRET_ACCESS_KEY="encrypted:BM7aPliOyiPrqFPZMfqpn534Nu+Y0Nbh/YRoxv2KY6XAi2dNO0LSEf97DqSUQYdsnu9iibZmVNktF2K/D6mtHr9+gumF6KsmaLH65KE7c9ly7NdFQHL9I26wxRq1Sr3Zgrfs954J6oURSlBRKqJFdcTsBltuuupGuqJHyLS9+DE0jD+bl0Qg0lA="
|
COM_ERMNVLDMR_STATIC_AWS_SECRET_ACCESS_KEY="encrypted:BFiOxOo/TNvSIMOjyeOswLcl+9AVdqp4axW+I46c1CL0ckSucQS+7CLpO8fNfakmW2bSibqru+xfWUbQT7FDH1YB3CPXUc0qPm1PsG0FiLixDefQuDrC/JHuA0Z3/dOAkn/e94BBuPtyJXxcLRP1v517MijPa0MuNqhI9BS3jFHKjWivqc9AVPs2ybglo14b/nEO1GqlM0TYflPoDhHoWjM="
|
||||||
SOPS_AGE_KEY="encrypted:BOJ7q79Tws4DMxpFuSymgv//IC4f+j713Bd7mNlUCEaUYVSfJMayMVPzks0FcsYo12XvlbH6gQ+tCf3t9yj/LcKKJzl3wtxlSVjvCRr0hasEBohcoxkLnFZ73DFQGzWcVC5Jf5IMK7qdYdNVzW0dVY/sn/NlTgl+A3YB6/08XYPhljl9993ky76zQqWDJQ66bKJ7YxWvst2TUNoT0lJEL0M4pg9ztRsuGqNZ"
|
SOPS_AGE_KEY="encrypted:BKiJVxKYhiadu0kNCw8wVLYdaEWZreAVu2PaujxhvcXeCowCGjivEuQD/uhduAy/CwwDWyQkgQJ2FJMEKA47e7QDjS9TMdPCXO19/teR7LThgqTf6AbSM3sebln5zalgyplay4A/7cVytPXuOvVkaYyoh9CgzTVsPJKXRq5yMaDEx/9/91Yo8zUMF3z1vq3/preI5baK4/1xXewR3OwfZqnNGyd7LXkdqyT5"
|
||||||
|
COM_ERMNVLDMR_DEV_ROOT_CA_KEY="encrypted:BP+GhCwutIMF2hSxIs92VNSoEAvfdhYRFSi5MUpFfCs+pNxJkZ7tFOAadMqSlPiLBcm9+A3yIn/04/oEtRNjXk/jlZQ2G21mt30sd89NARjJO+94ui6XbllW65E5/T+d8fDmRhz4c4OcNoKk70aXcdJqd1CJT7IlYQn++zQvB2el9cp9e7E22rvGtvum40iISEt/pVU84uHyQg6ZeCn+1czM+nLhPiWOAgveTz3EAgExlJW2de1ilDIuBCFXJy5+KvnCj3WNwRTAbIYgCwFnZMOUE5jYlhP6OZ2DQ3sWv7noG/Xaa/P+EomP9dwcamlAU32tRruyA8ZSp/ah9E8hFfmBqgKfSbRlWq3qGkq/F935DZfU/C+PjRcepS/eLZQ0mfD23B21VX2CjOhEkp5V+9I5L8XkXDjDg56JDRGvF/umpdqF/KpmtimqcgB0yDVY1Z3yT1U5IZ6Yf4WlqzhchdJXRWfo0bqK8Tk0b442/6AQgRP3n6DIrCjcpmr4jx+RJiejOr3xv3QtHGafDdkF2gO7DrYztdd6XpRjij0orBUiyYECgPsLHuwd+/2jXnxLVTavVTQ0Ddz0LLNjaYxqr8KK/B+0MeS/iuLXmACs8XCKwQmV8hPYQ0C/JXGiL4GOH0V70r6ghBxCDDMpJjPasCbiCBxSAMLkQ7ZmLbO0WVPPUTMAsZ8aKUy2MLe466zizXN640B4H6bkI7x/KC29sroEJWpUufD7f+t2tnVx/KLeAxAC6afuUCGi4ibFiwLHZjfimYKaYpuMcSZHQ64iONixyfUDIRNIOWQSiX1V5EBJgBDE0JVDnExmQYAIG5isYQEorC/7z6IJeZHc4NuiKDWuvd+jwwj8tN8PVAcACJKpQHpyUU20kvp4dYgBEeiQZpBfXWrnmOJZ0HgDHbvVxPW+SHTL/uoi/Tl9xdKe+z3Q/MoT8iYXggMPcFQIqVemQUTw9Tu0oNsSj3xueR9awJc2Le9aYbKTg54MAtcBnfKXN+3cYQkNVbqC5RfiAe2D3gfbT1OgApTUNz8n8v1dgAzTa+EB0i+w8nTsb3N/N4yAXMNSKdGeUl2rFRuQO7qlWorKc3pE+nBC2ex0sOMEUFYUXcyULaxsKM3ddakCAv9/jesnkrZl2gX7YDp8iqiFzh7l8jMAFHtFCMp3CSXlBAOpfQlGLY80qTSi1e8GrnV9Ow9t0DdS1wP7J6ES9DiNuEep5atHD+0MC6u0Dw0GtmsNnNRp77my/KI8ILhF4VBVBFQ5BiJDfdpAA3RNlANo2gK5ZCKPw4tXCYUknjYdwkqvUaIQCJcr2n+WkE2eCUCqjXTFr/KMvRByY6Fb1vAwcGoCWjP2g0Tliz3hcyh/72+umn05NO3cJSAfDEjfcYBUQZ/LCcy86G0EsHXP3NabgeHNXf/Z/VG7zWqQAPX0KaVrF9XC6I2FLkg1aNGWZfJGv4uohdIny7rWU7FWPaxy9GMk6x7xBh/Hk/5/rrGHCNGs+SegLglDs2+v4P56316k4kg//dmVl/vh3h0KC2P/1xiJZ10I91k7HqZLb2qdXToa4yOHB5Euu49UV/Qtv+cZU03fuT81sEv3YT819OdmwUZgkq0PT/Lrck+pbNDaUOakpgkGAbXy6SCvjM87jYN9Ia7druulWWO0pPi4T8daQ26ZQmZp57gdkpuh/He4kC5m1aWpT2s5STSbapChd9tFNjPhjCG1DZb7h0X8jg1VkxqutDDu17jOXrhElT1ejvYqYy9lIG1b1r7Jmjxo7LgGQuPMX6CIo/BLTsuNJyC5SfSCxEm56LvJgoNk2Vaeq6mLDOaKm2PNwPuYPnJw9xWBM0EetJBnsYMutPDMXhrB7x/8DKy5/hCsKICTfhlsboUHmbSfsikvGPYx7YOaOo8xFh4yAQ73T8hFX7kn2DBfRzGkJm8SQJRPj0Hjsf5mEFUt/OrieK/Jw10HKD6hDoEFmUDv5svC3nUY0FX0fTyi0jRAri+burrCQ0HXk/qj4Xs+WLiJgfQbprV2TwTIlzOdLb/jD8PeiElNzBxmOonRj76QKcbkOnPkCWCMFKapOJskxe0ASJVjYt142D0ndTa6F7oFu72ue5U+hyoToKeb7ONZilhF0+yL7akNfFKURUa/X+cEoewuSM7r8whWwZyG+M2cwGUTRMJiAC9wK7yE8MqdrEuQtILnCA0yRTPOh1Z9ifUY0asL1Tw9cbdGRW8svHH/oVHkWe3P+yepTNrn7xQlX/O1/p4FXRm0gSE3Fdnbli8VZdwVn2SET3WkPH9rJT2F7/hovfhx+lQzBQq9ZBpNLrWRdhXzCpiaC04o7q/eef+8dZwU62A1pd8uZ+0dI5T7lOVXoo03uF863YSOKX8ad2CiYUJ8gMvMA8FSWnsUbxiDaiXPj8kni5TLsvrkH/CKY/okG5SdRCF/XCcRcXP5dxdsS90tIWdd0xi/2wbalmn3CPQ2eVeDI3dP/jCRBkfiNtD70flhxVngZMZW+Rr1c0Cpo//fMCiV5ksDIBGin5AfOPmvSnPYWV5zcU3QEfl2F5fLXgDCbpaYjaOYjyRt9ZTqabSf1Ar4L9yQFBr4N9cNg4jKskvbha4BDmUL8J7xz/F/OXHFnEDV2YkMcpBfGM2XhKDevceOQcjrPkF5/e5LdwQeYhqgzzm6ur42OwHB2HBU7ulXn/LCk2eYCFa2D1f+2F3ExbwAvnDMhymdQdUniF/NzOfG/1L3yplFsqi270T/2gT1LdOQ/Fgp3FA81k/sMLbICcF/qCp/nS3x+iMZn9B+WLjUQvJy2PehXNcpXEvXWM/e1X4PWDUhwQi7+wjJwERX2W5SB1XjQa7n/osZqpOUG2ShssPNpS3mecaV+MTpRPVYTPFiDTIgkG7F/DSND0c2PDWsBLFus0h4jG70L94uDxVNiMJb/xq/7d2+7FMNPh9UJSK75XcKDhrRYJo3iU7mfl1U89vJB179ulGrdMpWd8v5DHWEDrn3NRBa0KWVYKpqeQ0195XXH1YlZjzK7615K/5ooOGUL42PlX2Hw1zxOJubsIl6LZt8V6wa6zJgywuVLsZb+kpjtHTHmVZyhY8IUnAn6Uj8erYXapvZ8rlhUpjvVuosn8gB9JM6vNct5dVn4e8Wbt6KnRcogHYUJT32QRSWsHCaZNEqwbX+dYaLx1FQZ5daYbXSWwiHhtAJRuYutbmWwWCRTVzyNNMh3sMAI1EcmMoOIX0DEhXYNe7daErR6vMyizQ+h5YKUYK4nUu270M0x/YKRHlxwK8WkEqWv8vfhZqzV0YGud1Hwd5JwWhIEZQ7cc1uPeYJJ5kAaIFqCffmwecS2gzVvOgDkNC5eENXSk7SzDpVgm8IcfZV47L17ni75tyJCS/kreODjap6VdpDNTyS1YJaaO2TMX/s4kWiEZ22Ma4CEv2eQq1uGazGamli+ZwExAtehw=="
|
||||||
|
COM_ERMNVLDMR_STATIC_PUBLIC_URL="encrypted:BEZbNy1WbNKhgUWmKO648nvuVNyMNXrMnq64WkjsScTOcE/HFtMX3nQktbIvEYiTSNHvoceUeW10E9i4n+C5ZEHKIBi9VUk3nuqVIcwAr6xTfqKjM1cJlRNKFQzwhHbBTYcImLoxFvM56KU4L/9Ei/XuQ/QRz0KTabhvGMM="
|
||||||
@@ -176,7 +176,7 @@ jobs:
|
|||||||
|
|
||||||
PROMPT="You are operating via GitHub Actions in non-interactive headless mode on Issue #${ISSUE_NUMBER}.\n\nIssue Context:\n${ISSUE_DATA}\n\nLatest instruction:\n${COMMENT_BODY}\n\nPlease generate/update a detailed technical implementation plan adhering to project GEMINI.md guidelines."
|
PROMPT="You are operating via GitHub Actions in non-interactive headless mode on Issue #${ISSUE_NUMBER}.\n\nIssue Context:\n${ISSUE_DATA}\n\nLatest instruction:\n${COMMENT_BODY}\n\nPlease generate/update a detailed technical implementation plan adhering to project GEMINI.md guidelines."
|
||||||
|
|
||||||
PLAN_OUTPUT=$(agy $CONTINUE_FLAG --mode plan --print-timeout 20m -p "$PROMPT" || echo "Agent encountered an error generating the plan.")
|
PLAN_OUTPUT=$(agy $CONTINUE_FLAG --mode plan --dangerously-skip-permissions --print-timeout 20m -p "$PROMPT" || echo "Agent encountered an error generating the plan.")
|
||||||
|
|
||||||
DISCLOSURE="\n\n---\n*Disclosure: I'm an AI assistant helping deytenit; I'm not deytenit.*"
|
DISCLOSURE="\n\n---\n*Disclosure: I'm an AI assistant helping deytenit; I'm not deytenit.*"
|
||||||
gh issue comment "$ISSUE_NUMBER" --body "${PLAN_OUTPUT}${DISCLOSURE}"
|
gh issue comment "$ISSUE_NUMBER" --body "${PLAN_OUTPUT}${DISCLOSURE}"
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
[git.ermnvldmr.com]:22222,[45.150.33.239]:22222 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBXcvf3Lds3AKfGHGh00IWR9tSRbBBqrV/CC6JBGmcrD
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
name: ci - next/build-golden-image
|
||||||
|
'on':
|
||||||
|
workflow_dispatch: null
|
||||||
|
concurrency:
|
||||||
|
group: ci-golden-image
|
||||||
|
cancel-in-progress: false
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
jobs:
|
||||||
|
validate-scripts:
|
||||||
|
name: Validate - Provisioner Scripts
|
||||||
|
runs-on: apex-debian13
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Validate Shell Script Syntax
|
||||||
|
run: bash -n ci/packer/scripts/*.sh
|
||||||
|
build-image:
|
||||||
|
name: Build - Golden Image
|
||||||
|
needs: validate-scripts
|
||||||
|
runs-on: apex-debian13
|
||||||
|
outputs:
|
||||||
|
image_name: ${{ steps.vars.outputs.image_name }}
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Calculate Image Name
|
||||||
|
id: vars
|
||||||
|
run: 'SHORT_SHA="$(echo ${{ github.sha }} | cut -c1-7)"
|
||||||
|
|
||||||
|
IMAGE_NAME="com-ermnvldmr-debian-12-k3s-amd64-${SHORT_SHA}.qcow2"
|
||||||
|
|
||||||
|
echo "image_name=${IMAGE_NAME}" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
|
'
|
||||||
|
- name: Install Build Tools
|
||||||
|
run: 'sudo apt-get update
|
||||||
|
|
||||||
|
sudo apt-get install -y qemu-utils
|
||||||
|
|
||||||
|
'
|
||||||
|
- name: Build Debian K3s Golden Image
|
||||||
|
run: bash ci/scripts/build-golden-image.sh
|
||||||
|
- name: Prepare and Upload Image Artifact
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: golden-image
|
||||||
|
path: output-qemu/com-ermnvldmr-debian-12-k3s-amd64.qcow2
|
||||||
|
retention-days: 30
|
||||||
|
upload-s3:
|
||||||
|
name: Upload - S3 Storage
|
||||||
|
needs: build-image
|
||||||
|
runs-on: apex-debian13
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Download Image Artifact
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: golden-image
|
||||||
|
path: output-qemu
|
||||||
|
- name: Upload to Static S3 (/dev/images/)
|
||||||
|
run: bash ci/scripts/upload-golden-image.sh "${IMAGE_NAME}"
|
||||||
|
env:
|
||||||
|
AWS_ACCESS_KEY_ID: ${{ secrets.STATIC_AWS_ACCESS_KEY_ID || secrets.COM_ERMNVLDMR_STATIC_AWS_ACCESS_KEY_ID }}
|
||||||
|
AWS_SECRET_ACCESS_KEY: ${{ secrets.STATIC_AWS_SECRET_ACCESS_KEY || secrets.COM_ERMNVLDMR_STATIC_AWS_SECRET_ACCESS_KEY }}
|
||||||
|
AWS_DEFAULT_REGION: ${{ secrets.STATIC_AWS_REGION || secrets.COM_ERMNVLDMR_STATIC_S3_REGION || 'auto' }}
|
||||||
|
S3_ENDPOINT: ${{ secrets.STATIC_S3_ENDPOINT_URL || secrets.COM_ERMNVLDMR_STATIC_S3_ENDPOINT_URL }}
|
||||||
|
S3_BUCKET: ${{ secrets.STATIC_S3_BUCKET || secrets.COM_ERMNVLDMR_STATIC_S3_BUCKET }}
|
||||||
|
IMAGE_NAME: ${{ needs.build-image.outputs.image_name }}
|
||||||
@@ -0,0 +1,332 @@
|
|||||||
|
name: packages/kits - next/required
|
||||||
|
'on':
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- next
|
||||||
|
paths:
|
||||||
|
- packages/kits/**
|
||||||
|
- packages/ui/**
|
||||||
|
- packages/stl/**
|
||||||
|
- packages/i18n/**
|
||||||
|
- .gitea/workflows/packages-kits-next-required.yml
|
||||||
|
- pnpm-lock.yaml
|
||||||
|
- ci/scripts/**
|
||||||
|
concurrency:
|
||||||
|
group: ci-next-kits-${{ github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
actions: read
|
||||||
|
jobs:
|
||||||
|
setup-stage:
|
||||||
|
name: Setup - Stage
|
||||||
|
runs-on: apex-debian13
|
||||||
|
outputs: {}
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Pack dependency cache
|
||||||
|
run: python3 ci/scripts/cache.py pack
|
||||||
|
- uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: ${{ steps.dependency-cache.outputs.key }}
|
||||||
|
path: .ci/pnpm-store.tar
|
||||||
|
retention-days: 7
|
||||||
|
build-configs:
|
||||||
|
name: Build - Configs & UI
|
||||||
|
needs: setup-stage
|
||||||
|
runs-on: apex-debian13
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Build Rsbuild config
|
||||||
|
run: pnpm --filter @ermnvldmr/rsbuild-config build
|
||||||
|
- name: Build Storybook config
|
||||||
|
run: pnpm --filter @ermnvldmr/storybook-config build
|
||||||
|
- name: Build i18n
|
||||||
|
run: pnpm --filter @ermnvldmr/i18n build
|
||||||
|
- name: Build UI
|
||||||
|
run: pnpm --filter @ermnvldmr/ui build
|
||||||
|
- name: Upload Rsbuild Config
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rsbuild-config-dist-${{ github.run_id }}
|
||||||
|
path: packages/rsbuild-config/dist
|
||||||
|
retention-days: 30
|
||||||
|
- name: Upload Storybook Config
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: storybook-config-dist-${{ github.run_id }}
|
||||||
|
path: packages/storybook-config/dist
|
||||||
|
retention-days: 30
|
||||||
|
- name: Upload i18n dist
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: i18n-dist-${{ github.run_id }}
|
||||||
|
path: packages/i18n/dist
|
||||||
|
retention-days: 30
|
||||||
|
- name: Upload UI dist
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: ui-dist-${{ github.run_id }}
|
||||||
|
path: packages/ui/dist
|
||||||
|
retention-days: 30
|
||||||
|
lint-kits:
|
||||||
|
name: Lint - Kits
|
||||||
|
needs: build-configs
|
||||||
|
runs-on: apex-debian13
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Download Rsbuild Config
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rsbuild-config-dist-${{ github.run_id }}
|
||||||
|
path: packages/rsbuild-config/dist
|
||||||
|
- name: Download Storybook Config
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: storybook-config-dist-${{ github.run_id }}
|
||||||
|
path: packages/storybook-config/dist
|
||||||
|
- name: Download i18n dist
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: i18n-dist-${{ github.run_id }}
|
||||||
|
path: packages/i18n/dist
|
||||||
|
- name: Download UI dist
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: ui-dist-${{ github.run_id }}
|
||||||
|
path: packages/ui/dist
|
||||||
|
- name: Lint Kits package
|
||||||
|
run: pnpm --filter @ermnvldmr/kits lint
|
||||||
|
typecheck-kits:
|
||||||
|
name: Typecheck - Kits
|
||||||
|
needs: build-configs
|
||||||
|
runs-on: apex-debian13
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Download Rsbuild Config
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rsbuild-config-dist-${{ github.run_id }}
|
||||||
|
path: packages/rsbuild-config/dist
|
||||||
|
- name: Download Storybook Config
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: storybook-config-dist-${{ github.run_id }}
|
||||||
|
path: packages/storybook-config/dist
|
||||||
|
- name: Download i18n dist
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: i18n-dist-${{ github.run_id }}
|
||||||
|
path: packages/i18n/dist
|
||||||
|
- name: Download UI dist
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: ui-dist-${{ github.run_id }}
|
||||||
|
path: packages/ui/dist
|
||||||
|
- name: Typecheck Kits package
|
||||||
|
run: pnpm --filter @ermnvldmr/kits typecheck
|
||||||
|
test-kits:
|
||||||
|
name: Test - Unit
|
||||||
|
needs: build-configs
|
||||||
|
runs-on: apex-debian13
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Download Rsbuild Config
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rsbuild-config-dist-${{ github.run_id }}
|
||||||
|
path: packages/rsbuild-config/dist
|
||||||
|
- name: Download Storybook Config
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: storybook-config-dist-${{ github.run_id }}
|
||||||
|
path: packages/storybook-config/dist
|
||||||
|
- name: Download i18n dist
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: i18n-dist-${{ github.run_id }}
|
||||||
|
path: packages/i18n/dist
|
||||||
|
- name: Download UI dist
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: ui-dist-${{ github.run_id }}
|
||||||
|
path: packages/ui/dist
|
||||||
|
- name: Test Kits package
|
||||||
|
run: pnpm --filter @ermnvldmr/kits test:coverage
|
||||||
|
build-storybook:
|
||||||
|
name: Build - Storybook
|
||||||
|
needs: build-configs
|
||||||
|
runs-on: apex-debian13
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Download Rsbuild Config
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rsbuild-config-dist-${{ github.run_id }}
|
||||||
|
path: packages/rsbuild-config/dist
|
||||||
|
- name: Download Storybook Config
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: storybook-config-dist-${{ github.run_id }}
|
||||||
|
path: packages/storybook-config/dist
|
||||||
|
- name: Download i18n dist
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: i18n-dist-${{ github.run_id }}
|
||||||
|
path: packages/i18n/dist
|
||||||
|
- name: Download UI dist
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: ui-dist-${{ github.run_id }}
|
||||||
|
path: packages/ui/dist
|
||||||
|
- name: Build Kits Storybook
|
||||||
|
run: pnpm --filter @ermnvldmr/kits build-storybook
|
||||||
|
- name: Upload Storybook build
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: kits-storybook-static-${{ github.run_id }}
|
||||||
|
path: packages/kits/storybook-static/
|
||||||
|
retention-days: 30
|
||||||
|
test-storybook:
|
||||||
|
name: Test - Storybook
|
||||||
|
needs: build-storybook
|
||||||
|
runs-on: apex-debian13
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Download Rsbuild Config
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rsbuild-config-dist-${{ github.run_id }}
|
||||||
|
path: packages/rsbuild-config/dist
|
||||||
|
- name: Download Storybook Config
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: storybook-config-dist-${{ github.run_id }}
|
||||||
|
path: packages/storybook-config/dist
|
||||||
|
- name: Download i18n dist
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: i18n-dist-${{ github.run_id }}
|
||||||
|
path: packages/i18n/dist
|
||||||
|
- name: Download UI dist
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: ui-dist-${{ github.run_id }}
|
||||||
|
path: packages/ui/dist
|
||||||
|
- name: Install Playwright browsers
|
||||||
|
run: pnpm --filter @ermnvldmr/kits exec playwright install --with-deps chromium
|
||||||
|
- name: Download Storybook build
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: kits-storybook-static-${{ github.run_id }}
|
||||||
|
path: packages/kits/storybook-static/
|
||||||
|
- name: Test Storybook
|
||||||
|
run: pnpm --filter @ermnvldmr/kits test:storybook:ci
|
||||||
|
build-kits:
|
||||||
|
name: Build - Kits
|
||||||
|
needs: build-configs
|
||||||
|
runs-on: apex-debian13
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Download Rsbuild Config
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rsbuild-config-dist-${{ github.run_id }}
|
||||||
|
path: packages/rsbuild-config/dist
|
||||||
|
- name: Download Storybook Config
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: storybook-config-dist-${{ github.run_id }}
|
||||||
|
path: packages/storybook-config/dist
|
||||||
|
- name: Download i18n dist
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: i18n-dist-${{ github.run_id }}
|
||||||
|
path: packages/i18n/dist
|
||||||
|
- name: Download UI dist
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: ui-dist-${{ github.run_id }}
|
||||||
|
path: packages/ui/dist
|
||||||
|
- name: Build Kits package
|
||||||
|
run: pnpm --filter @ermnvldmr/kits build
|
||||||
@@ -0,0 +1,332 @@
|
|||||||
|
name: packages/kits - pr/required
|
||||||
|
'on':
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- next
|
||||||
|
paths:
|
||||||
|
- packages/kits/**
|
||||||
|
- packages/ui/**
|
||||||
|
- packages/stl/**
|
||||||
|
- packages/i18n/**
|
||||||
|
- .gitea/workflows/packages-kits-pr-required.yml
|
||||||
|
- pnpm-lock.yaml
|
||||||
|
- ci/scripts/**
|
||||||
|
concurrency:
|
||||||
|
group: ci-pr-kits-${{ github.head_ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
actions: read
|
||||||
|
jobs:
|
||||||
|
setup-stage:
|
||||||
|
name: Setup - Stage
|
||||||
|
runs-on: apex-debian13
|
||||||
|
outputs: {}
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Pack dependency cache
|
||||||
|
run: python3 ci/scripts/cache.py pack
|
||||||
|
- uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: ${{ steps.dependency-cache.outputs.key }}
|
||||||
|
path: .ci/pnpm-store.tar
|
||||||
|
retention-days: 7
|
||||||
|
build-configs:
|
||||||
|
name: Build - Configs & UI
|
||||||
|
needs: setup-stage
|
||||||
|
runs-on: apex-debian13
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Build Rsbuild config
|
||||||
|
run: pnpm --filter @ermnvldmr/rsbuild-config build
|
||||||
|
- name: Build Storybook config
|
||||||
|
run: pnpm --filter @ermnvldmr/storybook-config build
|
||||||
|
- name: Build i18n
|
||||||
|
run: pnpm --filter @ermnvldmr/i18n build
|
||||||
|
- name: Build UI
|
||||||
|
run: pnpm --filter @ermnvldmr/ui build
|
||||||
|
- name: Upload Rsbuild Config
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rsbuild-config-dist-${{ github.run_id }}
|
||||||
|
path: packages/rsbuild-config/dist
|
||||||
|
retention-days: 30
|
||||||
|
- name: Upload Storybook Config
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: storybook-config-dist-${{ github.run_id }}
|
||||||
|
path: packages/storybook-config/dist
|
||||||
|
retention-days: 30
|
||||||
|
- name: Upload i18n dist
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: i18n-dist-${{ github.run_id }}
|
||||||
|
path: packages/i18n/dist
|
||||||
|
retention-days: 30
|
||||||
|
- name: Upload UI dist
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: ui-dist-${{ github.run_id }}
|
||||||
|
path: packages/ui/dist
|
||||||
|
retention-days: 30
|
||||||
|
lint-kits:
|
||||||
|
name: Lint - Kits
|
||||||
|
needs: build-configs
|
||||||
|
runs-on: apex-debian13
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Download Rsbuild Config
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rsbuild-config-dist-${{ github.run_id }}
|
||||||
|
path: packages/rsbuild-config/dist
|
||||||
|
- name: Download Storybook Config
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: storybook-config-dist-${{ github.run_id }}
|
||||||
|
path: packages/storybook-config/dist
|
||||||
|
- name: Download i18n dist
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: i18n-dist-${{ github.run_id }}
|
||||||
|
path: packages/i18n/dist
|
||||||
|
- name: Download UI dist
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: ui-dist-${{ github.run_id }}
|
||||||
|
path: packages/ui/dist
|
||||||
|
- name: Lint Kits package
|
||||||
|
run: pnpm --filter @ermnvldmr/kits lint
|
||||||
|
typecheck-kits:
|
||||||
|
name: Typecheck - Kits
|
||||||
|
needs: build-configs
|
||||||
|
runs-on: apex-debian13
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Download Rsbuild Config
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rsbuild-config-dist-${{ github.run_id }}
|
||||||
|
path: packages/rsbuild-config/dist
|
||||||
|
- name: Download Storybook Config
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: storybook-config-dist-${{ github.run_id }}
|
||||||
|
path: packages/storybook-config/dist
|
||||||
|
- name: Download i18n dist
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: i18n-dist-${{ github.run_id }}
|
||||||
|
path: packages/i18n/dist
|
||||||
|
- name: Download UI dist
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: ui-dist-${{ github.run_id }}
|
||||||
|
path: packages/ui/dist
|
||||||
|
- name: Typecheck Kits package
|
||||||
|
run: pnpm --filter @ermnvldmr/kits typecheck
|
||||||
|
test-kits:
|
||||||
|
name: Test - Unit
|
||||||
|
needs: build-configs
|
||||||
|
runs-on: apex-debian13
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Download Rsbuild Config
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rsbuild-config-dist-${{ github.run_id }}
|
||||||
|
path: packages/rsbuild-config/dist
|
||||||
|
- name: Download Storybook Config
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: storybook-config-dist-${{ github.run_id }}
|
||||||
|
path: packages/storybook-config/dist
|
||||||
|
- name: Download i18n dist
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: i18n-dist-${{ github.run_id }}
|
||||||
|
path: packages/i18n/dist
|
||||||
|
- name: Download UI dist
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: ui-dist-${{ github.run_id }}
|
||||||
|
path: packages/ui/dist
|
||||||
|
- name: Test Kits package
|
||||||
|
run: pnpm --filter @ermnvldmr/kits test:coverage
|
||||||
|
build-storybook:
|
||||||
|
name: Build - Storybook
|
||||||
|
needs: build-configs
|
||||||
|
runs-on: apex-debian13
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Download Rsbuild Config
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rsbuild-config-dist-${{ github.run_id }}
|
||||||
|
path: packages/rsbuild-config/dist
|
||||||
|
- name: Download Storybook Config
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: storybook-config-dist-${{ github.run_id }}
|
||||||
|
path: packages/storybook-config/dist
|
||||||
|
- name: Download i18n dist
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: i18n-dist-${{ github.run_id }}
|
||||||
|
path: packages/i18n/dist
|
||||||
|
- name: Download UI dist
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: ui-dist-${{ github.run_id }}
|
||||||
|
path: packages/ui/dist
|
||||||
|
- name: Build Kits Storybook
|
||||||
|
run: pnpm --filter @ermnvldmr/kits build-storybook
|
||||||
|
- name: Upload Storybook build
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: kits-storybook-static-${{ github.run_id }}
|
||||||
|
path: packages/kits/storybook-static/
|
||||||
|
retention-days: 30
|
||||||
|
test-storybook:
|
||||||
|
name: Test - Storybook
|
||||||
|
needs: build-storybook
|
||||||
|
runs-on: apex-debian13
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Download Rsbuild Config
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rsbuild-config-dist-${{ github.run_id }}
|
||||||
|
path: packages/rsbuild-config/dist
|
||||||
|
- name: Download Storybook Config
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: storybook-config-dist-${{ github.run_id }}
|
||||||
|
path: packages/storybook-config/dist
|
||||||
|
- name: Download i18n dist
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: i18n-dist-${{ github.run_id }}
|
||||||
|
path: packages/i18n/dist
|
||||||
|
- name: Download UI dist
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: ui-dist-${{ github.run_id }}
|
||||||
|
path: packages/ui/dist
|
||||||
|
- name: Install Playwright browsers
|
||||||
|
run: pnpm --filter @ermnvldmr/kits exec playwright install --with-deps chromium
|
||||||
|
- name: Download Storybook build
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: kits-storybook-static-${{ github.run_id }}
|
||||||
|
path: packages/kits/storybook-static/
|
||||||
|
- name: Test Storybook
|
||||||
|
run: pnpm --filter @ermnvldmr/kits test:storybook:ci
|
||||||
|
build-kits:
|
||||||
|
name: Build - Kits
|
||||||
|
needs: build-configs
|
||||||
|
runs-on: apex-debian13
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Download Rsbuild Config
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rsbuild-config-dist-${{ github.run_id }}
|
||||||
|
path: packages/rsbuild-config/dist
|
||||||
|
- name: Download Storybook Config
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: storybook-config-dist-${{ github.run_id }}
|
||||||
|
path: packages/storybook-config/dist
|
||||||
|
- name: Download i18n dist
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: i18n-dist-${{ github.run_id }}
|
||||||
|
path: packages/i18n/dist
|
||||||
|
- name: Download UI dist
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: ui-dist-${{ github.run_id }}
|
||||||
|
path: packages/ui/dist
|
||||||
|
- name: Build Kits package
|
||||||
|
run: pnpm --filter @ermnvldmr/kits build
|
||||||
@@ -0,0 +1,133 @@
|
|||||||
|
name: packages/ssg - next/required
|
||||||
|
'on':
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- next
|
||||||
|
paths:
|
||||||
|
- packages/ssg/**
|
||||||
|
- .gitea/workflows/packages-ssg-next-required.yml
|
||||||
|
- pnpm-lock.yaml
|
||||||
|
- ci/scripts/**
|
||||||
|
concurrency:
|
||||||
|
group: ci-ssg-${{ github.ref_name }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
actions: read
|
||||||
|
jobs:
|
||||||
|
setup-stage:
|
||||||
|
name: Setup - Stage
|
||||||
|
runs-on: apex-debian13
|
||||||
|
outputs: {}
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Pack dependency cache
|
||||||
|
run: python3 ci/scripts/cache.py pack
|
||||||
|
- uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: ${{ steps.dependency-cache.outputs.key }}
|
||||||
|
path: .ci/pnpm-store.tar
|
||||||
|
retention-days: 7
|
||||||
|
build-configs:
|
||||||
|
name: Build - Configs
|
||||||
|
needs: setup-stage
|
||||||
|
runs-on: apex-debian13
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Build Rsbuild config
|
||||||
|
run: pnpm --filter @ermnvldmr/rsbuild-config build
|
||||||
|
- name: Upload Config Artifacts
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rsbuild-config-dist
|
||||||
|
path: packages/rsbuild-config/dist
|
||||||
|
retention-days: 30
|
||||||
|
lint-ssg:
|
||||||
|
name: Lint - SSG
|
||||||
|
needs: build-configs
|
||||||
|
runs-on: apex-debian13
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Download Config Artifacts
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rsbuild-config-dist
|
||||||
|
path: packages/rsbuild-config/dist
|
||||||
|
- name: Lint SSG package
|
||||||
|
run: pnpm --filter @ermnvldmr/ssg lint
|
||||||
|
typecheck-ssg:
|
||||||
|
name: Typecheck - SSG
|
||||||
|
needs: build-configs
|
||||||
|
runs-on: apex-debian13
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Download Config Artifacts
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rsbuild-config-dist
|
||||||
|
path: packages/rsbuild-config/dist
|
||||||
|
- name: Typecheck SSG package
|
||||||
|
run: pnpm --filter @ermnvldmr/ssg typecheck
|
||||||
|
build-ssg:
|
||||||
|
name: Build - SSG
|
||||||
|
needs: build-configs
|
||||||
|
runs-on: apex-debian13
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Download Config Artifacts
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rsbuild-config-dist
|
||||||
|
path: packages/rsbuild-config/dist
|
||||||
|
- name: Build SSG package
|
||||||
|
run: pnpm --filter @ermnvldmr/ssg build
|
||||||
@@ -0,0 +1,133 @@
|
|||||||
|
name: packages/ssg - pr/required
|
||||||
|
'on':
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- next
|
||||||
|
paths:
|
||||||
|
- packages/ssg/**
|
||||||
|
- .gitea/workflows/packages-ssg-pr-required.yml
|
||||||
|
- pnpm-lock.yaml
|
||||||
|
- ci/scripts/**
|
||||||
|
concurrency:
|
||||||
|
group: ci-pr-ssg-${{ github.head_ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
actions: read
|
||||||
|
jobs:
|
||||||
|
setup-stage:
|
||||||
|
name: Setup - Stage
|
||||||
|
runs-on: apex-debian13
|
||||||
|
outputs: {}
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Pack dependency cache
|
||||||
|
run: python3 ci/scripts/cache.py pack
|
||||||
|
- uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: ${{ steps.dependency-cache.outputs.key }}
|
||||||
|
path: .ci/pnpm-store.tar
|
||||||
|
retention-days: 7
|
||||||
|
build-configs:
|
||||||
|
name: Build - Configs
|
||||||
|
needs: setup-stage
|
||||||
|
runs-on: apex-debian13
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Build Rsbuild config
|
||||||
|
run: pnpm --filter @ermnvldmr/rsbuild-config build
|
||||||
|
- name: Upload Config Artifacts
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rsbuild-config-dist-${{ github.run_id }}
|
||||||
|
path: packages/rsbuild-config/dist
|
||||||
|
retention-days: 30
|
||||||
|
lint-ssg:
|
||||||
|
name: Lint - SSG
|
||||||
|
needs: build-configs
|
||||||
|
runs-on: apex-debian13
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Download Config Artifacts
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rsbuild-config-dist-${{ github.run_id }}
|
||||||
|
path: packages/rsbuild-config/dist
|
||||||
|
- name: Lint SSG package
|
||||||
|
run: pnpm --filter @ermnvldmr/ssg lint
|
||||||
|
typecheck-ssg:
|
||||||
|
name: Typecheck - SSG
|
||||||
|
needs: build-configs
|
||||||
|
runs-on: apex-debian13
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Download Config Artifacts
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rsbuild-config-dist-${{ github.run_id }}
|
||||||
|
path: packages/rsbuild-config/dist
|
||||||
|
- name: Typecheck SSG package
|
||||||
|
run: pnpm --filter @ermnvldmr/ssg typecheck
|
||||||
|
build-ssg:
|
||||||
|
name: Build - SSG
|
||||||
|
needs: build-configs
|
||||||
|
runs-on: apex-debian13
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Download Config Artifacts
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rsbuild-config-dist-${{ github.run_id }}
|
||||||
|
path: packages/rsbuild-config/dist
|
||||||
|
- name: Build SSG package
|
||||||
|
run: pnpm --filter @ermnvldmr/ssg build
|
||||||
@@ -0,0 +1,156 @@
|
|||||||
|
name: packages/stl - next/required
|
||||||
|
'on':
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- next
|
||||||
|
paths:
|
||||||
|
- packages/stl/**
|
||||||
|
- .gitea/workflows/packages-stl-next-required.yml
|
||||||
|
- pnpm-lock.yaml
|
||||||
|
- ci/scripts/**
|
||||||
|
concurrency:
|
||||||
|
group: ci-stl-${{ github.ref_name }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
actions: read
|
||||||
|
jobs:
|
||||||
|
setup-stage:
|
||||||
|
name: Setup - Stage
|
||||||
|
runs-on: apex-debian13
|
||||||
|
outputs: {}
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Pack dependency cache
|
||||||
|
run: python3 ci/scripts/cache.py pack
|
||||||
|
- uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: ${{ steps.dependency-cache.outputs.key }}
|
||||||
|
path: .ci/pnpm-store.tar
|
||||||
|
retention-days: 7
|
||||||
|
build-configs:
|
||||||
|
name: Build - Configs
|
||||||
|
needs: setup-stage
|
||||||
|
runs-on: apex-debian13
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Build Rsbuild config
|
||||||
|
run: pnpm --filter @ermnvldmr/rsbuild-config build
|
||||||
|
- name: Upload Config Artifacts
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rsbuild-config-dist
|
||||||
|
path: packages/rsbuild-config/dist
|
||||||
|
retention-days: 30
|
||||||
|
lint-stl:
|
||||||
|
name: Lint - STL
|
||||||
|
needs: build-configs
|
||||||
|
runs-on: apex-debian13
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Download Config Artifacts
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rsbuild-config-dist
|
||||||
|
path: packages/rsbuild-config/dist
|
||||||
|
- name: Lint STL package
|
||||||
|
run: pnpm --filter @ermnvldmr/stl lint
|
||||||
|
typecheck-stl:
|
||||||
|
name: Typecheck - STL
|
||||||
|
needs: build-configs
|
||||||
|
runs-on: apex-debian13
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Download Config Artifacts
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rsbuild-config-dist
|
||||||
|
path: packages/rsbuild-config/dist
|
||||||
|
- name: Typecheck STL package
|
||||||
|
run: pnpm --filter @ermnvldmr/stl typecheck
|
||||||
|
test-stl:
|
||||||
|
name: Test - STL
|
||||||
|
needs: build-configs
|
||||||
|
runs-on: apex-debian13
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Download Config Artifacts
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rsbuild-config-dist
|
||||||
|
path: packages/rsbuild-config/dist
|
||||||
|
- name: Test STL package
|
||||||
|
run: pnpm --filter @ermnvldmr/stl test:coverage
|
||||||
|
build-stl:
|
||||||
|
name: Build - STL
|
||||||
|
needs: build-configs
|
||||||
|
runs-on: apex-debian13
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Download Config Artifacts
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rsbuild-config-dist
|
||||||
|
path: packages/rsbuild-config/dist
|
||||||
|
- name: Build STL package
|
||||||
|
run: pnpm --filter @ermnvldmr/stl build
|
||||||
@@ -0,0 +1,157 @@
|
|||||||
|
name: packages/stl - pr/required
|
||||||
|
'on':
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- next
|
||||||
|
paths:
|
||||||
|
- packages/stl/**
|
||||||
|
- .gitea/workflows/packages-stl-pr-required.yml
|
||||||
|
- pnpm-lock.yaml
|
||||||
|
- ci/scripts/**
|
||||||
|
workflow_dispatch: {}
|
||||||
|
concurrency:
|
||||||
|
group: ci-pr-stl-${{ github.head_ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
actions: read
|
||||||
|
jobs:
|
||||||
|
setup-stage:
|
||||||
|
name: Setup - Stage
|
||||||
|
runs-on: apex-debian13
|
||||||
|
outputs: {}
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Pack dependency cache
|
||||||
|
run: python3 ci/scripts/cache.py pack
|
||||||
|
- uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: ${{ steps.dependency-cache.outputs.key }}
|
||||||
|
path: .ci/pnpm-store.tar
|
||||||
|
retention-days: 7
|
||||||
|
build-configs:
|
||||||
|
name: Build - Configs
|
||||||
|
needs: setup-stage
|
||||||
|
runs-on: apex-debian13
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Build Rsbuild config
|
||||||
|
run: pnpm --filter @ermnvldmr/rsbuild-config build
|
||||||
|
- name: Upload Config Artifacts
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rsbuild-config-dist-${{ github.run_id }}
|
||||||
|
path: packages/rsbuild-config/dist
|
||||||
|
retention-days: 30
|
||||||
|
lint-stl:
|
||||||
|
name: Lint - STL
|
||||||
|
needs: build-configs
|
||||||
|
runs-on: apex-debian13
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Download Config Artifacts
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rsbuild-config-dist-${{ github.run_id }}
|
||||||
|
path: packages/rsbuild-config/dist
|
||||||
|
- name: Lint STL package
|
||||||
|
run: pnpm --filter @ermnvldmr/stl lint
|
||||||
|
typecheck-stl:
|
||||||
|
name: Typecheck - STL
|
||||||
|
needs: build-configs
|
||||||
|
runs-on: apex-debian13
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Download Config Artifacts
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rsbuild-config-dist-${{ github.run_id }}
|
||||||
|
path: packages/rsbuild-config/dist
|
||||||
|
- name: Typecheck STL package
|
||||||
|
run: pnpm --filter @ermnvldmr/stl typecheck
|
||||||
|
test-stl:
|
||||||
|
name: Test - STL
|
||||||
|
needs: build-configs
|
||||||
|
runs-on: apex-debian13
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Download Config Artifacts
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rsbuild-config-dist-${{ github.run_id }}
|
||||||
|
path: packages/rsbuild-config/dist
|
||||||
|
- name: Test STL package
|
||||||
|
run: pnpm --filter @ermnvldmr/stl test:coverage
|
||||||
|
build-stl:
|
||||||
|
name: Build - STL
|
||||||
|
needs: build-configs
|
||||||
|
runs-on: apex-debian13
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Download Config Artifacts
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rsbuild-config-dist-${{ github.run_id }}
|
||||||
|
path: packages/rsbuild-config/dist
|
||||||
|
- name: Build STL package
|
||||||
|
run: pnpm --filter @ermnvldmr/stl build
|
||||||
@@ -0,0 +1,284 @@
|
|||||||
|
name: packages/ui - next/required
|
||||||
|
'on':
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- next
|
||||||
|
paths:
|
||||||
|
- packages/ui/**
|
||||||
|
- packages/stl/**
|
||||||
|
- packages/i18n/**
|
||||||
|
- .gitea/workflows/packages-ui-next-required.yml
|
||||||
|
- pnpm-lock.yaml
|
||||||
|
- ci/scripts/**
|
||||||
|
concurrency:
|
||||||
|
group: ci-ui-${{ github.ref_name }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
actions: read
|
||||||
|
jobs:
|
||||||
|
setup-stage:
|
||||||
|
name: Setup - Stage
|
||||||
|
runs-on: apex-debian13
|
||||||
|
outputs: {}
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Pack dependency cache
|
||||||
|
run: python3 ci/scripts/cache.py pack
|
||||||
|
- uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: ${{ steps.dependency-cache.outputs.key }}
|
||||||
|
path: .ci/pnpm-store.tar
|
||||||
|
retention-days: 7
|
||||||
|
build-configs:
|
||||||
|
name: Build - Configs
|
||||||
|
needs: setup-stage
|
||||||
|
runs-on: apex-debian13
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Build Rsbuild config
|
||||||
|
run: pnpm --filter @ermnvldmr/rsbuild-config build
|
||||||
|
- name: Build Storybook config
|
||||||
|
run: pnpm --filter @ermnvldmr/storybook-config build
|
||||||
|
- name: Build i18n
|
||||||
|
run: pnpm --filter @ermnvldmr/i18n build
|
||||||
|
- name: Upload Rsbuild Config
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rsbuild-config-dist
|
||||||
|
path: packages/rsbuild-config/dist
|
||||||
|
retention-days: 30
|
||||||
|
- name: Upload Storybook Config
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: storybook-config-dist
|
||||||
|
path: packages/storybook-config/dist
|
||||||
|
retention-days: 30
|
||||||
|
- name: Upload i18n dist
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: i18n-dist
|
||||||
|
path: packages/i18n/dist
|
||||||
|
retention-days: 30
|
||||||
|
lint-ui:
|
||||||
|
name: Lint - UI
|
||||||
|
needs: build-configs
|
||||||
|
runs-on: apex-debian13
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Download Rsbuild Config
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rsbuild-config-dist
|
||||||
|
path: packages/rsbuild-config/dist
|
||||||
|
- name: Download Storybook Config
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: storybook-config-dist
|
||||||
|
path: packages/storybook-config/dist
|
||||||
|
- name: Download i18n dist
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: i18n-dist
|
||||||
|
path: packages/i18n/dist
|
||||||
|
- name: Lint UI package
|
||||||
|
run: pnpm --filter @ermnvldmr/ui lint
|
||||||
|
typecheck-ui:
|
||||||
|
name: Typecheck - UI
|
||||||
|
needs: build-configs
|
||||||
|
runs-on: apex-debian13
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Download Rsbuild Config
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rsbuild-config-dist
|
||||||
|
path: packages/rsbuild-config/dist
|
||||||
|
- name: Download Storybook Config
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: storybook-config-dist
|
||||||
|
path: packages/storybook-config/dist
|
||||||
|
- name: Download i18n dist
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: i18n-dist
|
||||||
|
path: packages/i18n/dist
|
||||||
|
- name: Typecheck UI package
|
||||||
|
run: pnpm --filter @ermnvldmr/ui typecheck
|
||||||
|
test-ui:
|
||||||
|
name: Test - Unit
|
||||||
|
needs: build-configs
|
||||||
|
runs-on: apex-debian13
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Download Rsbuild Config
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rsbuild-config-dist
|
||||||
|
path: packages/rsbuild-config/dist
|
||||||
|
- name: Download Storybook Config
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: storybook-config-dist
|
||||||
|
path: packages/storybook-config/dist
|
||||||
|
- name: Download i18n dist
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: i18n-dist
|
||||||
|
path: packages/i18n/dist
|
||||||
|
- name: Test UI package
|
||||||
|
run: pnpm --filter @ermnvldmr/ui test:coverage
|
||||||
|
build-storybook:
|
||||||
|
name: Build - Storybook
|
||||||
|
needs: build-configs
|
||||||
|
runs-on: apex-debian13
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Download Rsbuild Config
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rsbuild-config-dist
|
||||||
|
path: packages/rsbuild-config/dist
|
||||||
|
- name: Download Storybook Config
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: storybook-config-dist
|
||||||
|
path: packages/storybook-config/dist
|
||||||
|
- name: Download i18n dist
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: i18n-dist
|
||||||
|
path: packages/i18n/dist
|
||||||
|
- name: Build UI Storybook
|
||||||
|
run: pnpm --filter @ermnvldmr/ui build-storybook
|
||||||
|
test-storybook:
|
||||||
|
name: Test - Storybook
|
||||||
|
needs: build-storybook
|
||||||
|
runs-on: apex-debian13
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Download Rsbuild Config
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rsbuild-config-dist
|
||||||
|
path: packages/rsbuild-config/dist
|
||||||
|
- name: Download Storybook Config
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: storybook-config-dist
|
||||||
|
path: packages/storybook-config/dist
|
||||||
|
- name: Download i18n dist
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: i18n-dist
|
||||||
|
path: packages/i18n/dist
|
||||||
|
- name: Install Playwright browsers
|
||||||
|
run: pnpm --filter @ermnvldmr/ui exec playwright install --with-deps chromium
|
||||||
|
- name: Build UI Storybook
|
||||||
|
run: pnpm --filter @ermnvldmr/ui build-storybook
|
||||||
|
- name: Test Storybook
|
||||||
|
run: pnpm --filter @ermnvldmr/ui test:storybook:ci
|
||||||
|
build-ui:
|
||||||
|
name: Build - UI
|
||||||
|
needs: build-configs
|
||||||
|
runs-on: apex-debian13
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Download Rsbuild Config
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rsbuild-config-dist
|
||||||
|
path: packages/rsbuild-config/dist
|
||||||
|
- name: Download Storybook Config
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: storybook-config-dist
|
||||||
|
path: packages/storybook-config/dist
|
||||||
|
- name: Download i18n dist
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: i18n-dist
|
||||||
|
path: packages/i18n/dist
|
||||||
|
- name: Build UI package
|
||||||
|
run: pnpm --filter @ermnvldmr/ui build
|
||||||
@@ -0,0 +1,293 @@
|
|||||||
|
name: packages/ui - pr/required
|
||||||
|
'on':
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- next
|
||||||
|
paths:
|
||||||
|
- packages/ui/**
|
||||||
|
- packages/stl/**
|
||||||
|
- packages/i18n/**
|
||||||
|
- .gitea/workflows/packages-ui-pr-required.yml
|
||||||
|
- pnpm-lock.yaml
|
||||||
|
- ci/scripts/**
|
||||||
|
concurrency:
|
||||||
|
group: ci-pr-ui-${{ github.head_ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
actions: read
|
||||||
|
jobs:
|
||||||
|
setup-stage:
|
||||||
|
name: Setup - Stage
|
||||||
|
runs-on: apex-debian13
|
||||||
|
outputs: {}
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Pack dependency cache
|
||||||
|
run: python3 ci/scripts/cache.py pack
|
||||||
|
- uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: ${{ steps.dependency-cache.outputs.key }}
|
||||||
|
path: .ci/pnpm-store.tar
|
||||||
|
retention-days: 7
|
||||||
|
build-configs:
|
||||||
|
name: Build - Configs
|
||||||
|
needs: setup-stage
|
||||||
|
runs-on: apex-debian13
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Build Rsbuild config
|
||||||
|
run: pnpm --filter @ermnvldmr/rsbuild-config build
|
||||||
|
- name: Build Storybook config
|
||||||
|
run: pnpm --filter @ermnvldmr/storybook-config build
|
||||||
|
- name: Build i18n
|
||||||
|
run: pnpm --filter @ermnvldmr/i18n build
|
||||||
|
- name: Upload Rsbuild Config
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rsbuild-config-dist-${{ github.run_id }}
|
||||||
|
path: packages/rsbuild-config/dist
|
||||||
|
retention-days: 30
|
||||||
|
- name: Upload Storybook Config
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: storybook-config-dist-${{ github.run_id }}
|
||||||
|
path: packages/storybook-config/dist
|
||||||
|
retention-days: 30
|
||||||
|
- name: Upload i18n dist
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: i18n-dist-${{ github.run_id }}
|
||||||
|
path: packages/i18n/dist
|
||||||
|
retention-days: 30
|
||||||
|
lint-ui:
|
||||||
|
name: Lint - UI
|
||||||
|
needs: build-configs
|
||||||
|
runs-on: apex-debian13
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Download Rsbuild Config
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rsbuild-config-dist-${{ github.run_id }}
|
||||||
|
path: packages/rsbuild-config/dist
|
||||||
|
- name: Download Storybook Config
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: storybook-config-dist-${{ github.run_id }}
|
||||||
|
path: packages/storybook-config/dist
|
||||||
|
- name: Download i18n dist
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: i18n-dist-${{ github.run_id }}
|
||||||
|
path: packages/i18n/dist
|
||||||
|
- name: Lint UI package
|
||||||
|
run: pnpm --filter @ermnvldmr/ui lint
|
||||||
|
typecheck-ui:
|
||||||
|
name: Typecheck - UI
|
||||||
|
needs: build-configs
|
||||||
|
runs-on: apex-debian13
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Download Rsbuild Config
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rsbuild-config-dist-${{ github.run_id }}
|
||||||
|
path: packages/rsbuild-config/dist
|
||||||
|
- name: Download Storybook Config
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: storybook-config-dist-${{ github.run_id }}
|
||||||
|
path: packages/storybook-config/dist
|
||||||
|
- name: Download i18n dist
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: i18n-dist-${{ github.run_id }}
|
||||||
|
path: packages/i18n/dist
|
||||||
|
- name: Typecheck UI package
|
||||||
|
run: pnpm --filter @ermnvldmr/ui typecheck
|
||||||
|
test-ui:
|
||||||
|
name: Test - Unit
|
||||||
|
needs: build-configs
|
||||||
|
runs-on: apex-debian13
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Download Rsbuild Config
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rsbuild-config-dist-${{ github.run_id }}
|
||||||
|
path: packages/rsbuild-config/dist
|
||||||
|
- name: Download Storybook Config
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: storybook-config-dist-${{ github.run_id }}
|
||||||
|
path: packages/storybook-config/dist
|
||||||
|
- name: Download i18n dist
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: i18n-dist-${{ github.run_id }}
|
||||||
|
path: packages/i18n/dist
|
||||||
|
- name: Test UI package
|
||||||
|
run: pnpm --filter @ermnvldmr/ui test:coverage
|
||||||
|
build-storybook:
|
||||||
|
name: Build - Storybook
|
||||||
|
needs: build-configs
|
||||||
|
runs-on: apex-debian13
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Download Rsbuild Config
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rsbuild-config-dist-${{ github.run_id }}
|
||||||
|
path: packages/rsbuild-config/dist
|
||||||
|
- name: Download Storybook Config
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: storybook-config-dist-${{ github.run_id }}
|
||||||
|
path: packages/storybook-config/dist
|
||||||
|
- name: Download i18n dist
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: i18n-dist-${{ github.run_id }}
|
||||||
|
path: packages/i18n/dist
|
||||||
|
- name: Build UI Storybook
|
||||||
|
run: pnpm --filter @ermnvldmr/ui build-storybook
|
||||||
|
- name: Upload Storybook build
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: ui-storybook-static-${{ github.run_id }}
|
||||||
|
path: packages/ui/storybook-static/
|
||||||
|
retention-days: 30
|
||||||
|
test-storybook:
|
||||||
|
name: Test - Storybook
|
||||||
|
needs: build-storybook
|
||||||
|
runs-on: apex-debian13
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Download Rsbuild Config
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rsbuild-config-dist-${{ github.run_id }}
|
||||||
|
path: packages/rsbuild-config/dist
|
||||||
|
- name: Download Storybook Config
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: storybook-config-dist-${{ github.run_id }}
|
||||||
|
path: packages/storybook-config/dist
|
||||||
|
- name: Download i18n dist
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: i18n-dist-${{ github.run_id }}
|
||||||
|
path: packages/i18n/dist
|
||||||
|
- name: Install Playwright browsers
|
||||||
|
run: pnpm --filter @ermnvldmr/ui exec playwright install --with-deps chromium
|
||||||
|
- name: Download Storybook build
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: ui-storybook-static-${{ github.run_id }}
|
||||||
|
path: packages/ui/storybook-static/
|
||||||
|
- name: Test Storybook
|
||||||
|
run: pnpm --filter @ermnvldmr/ui test:storybook:ci
|
||||||
|
build-ui:
|
||||||
|
name: Build - UI
|
||||||
|
needs: build-configs
|
||||||
|
runs-on: apex-debian13
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Download Rsbuild Config
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rsbuild-config-dist-${{ github.run_id }}
|
||||||
|
path: packages/rsbuild-config/dist
|
||||||
|
- name: Download Storybook Config
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: storybook-config-dist-${{ github.run_id }}
|
||||||
|
path: packages/storybook-config/dist
|
||||||
|
- name: Download i18n dist
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: i18n-dist-${{ github.run_id }}
|
||||||
|
path: packages/i18n/dist
|
||||||
|
- name: Build UI package
|
||||||
|
run: pnpm --filter @ermnvldmr/ui build
|
||||||
@@ -0,0 +1,144 @@
|
|||||||
|
name: services/docs - next/required
|
||||||
|
'on':
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- next
|
||||||
|
paths:
|
||||||
|
- services/docs/**
|
||||||
|
- .gitea/workflows/services-docs-next-required.yml
|
||||||
|
- ci/docker/docs/**
|
||||||
|
- ci/config/nginx/**
|
||||||
|
- ci/scripts/**
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: ci-docs-${{ github.ref_name }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
actions: read
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
setup-hugo:
|
||||||
|
name: Setup - Hugo
|
||||||
|
runs-on: apex-debian13
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
submodules: recursive
|
||||||
|
- name: Setup Hugo
|
||||||
|
run: hugo version | grep extended
|
||||||
|
|
||||||
|
build-hugo:
|
||||||
|
name: Build - Hugo Site
|
||||||
|
needs: setup-hugo
|
||||||
|
runs-on: apex-debian13
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
submodules: recursive
|
||||||
|
- name: Setup Hugo
|
||||||
|
run: hugo version | grep extended
|
||||||
|
- name: Build Hugo site
|
||||||
|
working-directory: services/docs
|
||||||
|
run: hugo --gc --minify
|
||||||
|
|
||||||
|
release-docker:
|
||||||
|
name: Release - Docker Image
|
||||||
|
needs: build-hugo
|
||||||
|
runs-on: apex-debian13
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
packages: write
|
||||||
|
outputs:
|
||||||
|
short_sha: ${{ steps.vars.outputs.short_sha }}
|
||||||
|
version: ${{ steps.vars.outputs.version }}
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
submodules: recursive
|
||||||
|
fetch-depth: 0
|
||||||
|
- name: Log in to Gitea Container Registry
|
||||||
|
run: python3 ci/scripts/docker.py login
|
||||||
|
env:
|
||||||
|
REGISTRY: git.ermnvldmr.com
|
||||||
|
REGISTRY_USER: ${{ github.repository_owner }}
|
||||||
|
REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN }}
|
||||||
|
- name: Compute version and metadata
|
||||||
|
id: vars
|
||||||
|
run: |
|
||||||
|
SHORT_SHA="sha-$(echo ${{ github.sha }} | cut -c1-7)"
|
||||||
|
VERSION=$(bash ci/scripts/calver-release.sh docs)
|
||||||
|
echo "short_sha=$SHORT_SHA" >> $GITHUB_OUTPUT
|
||||||
|
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
||||||
|
- name: Create and push release tag
|
||||||
|
if: github.event_name == 'push' && github.ref == 'refs/heads/next'
|
||||||
|
run: bash ci/scripts/calver-release.sh tag docs "${{ github.sha }}" "${{ steps.vars.outputs.version }}"
|
||||||
|
env:
|
||||||
|
GIT_WRITE_KEY: ${{ secrets.DOCS_DEPLOY_KEY }}
|
||||||
|
- name: Extract Docker metadata
|
||||||
|
id: meta
|
||||||
|
run: python3 ci/scripts/docker.py metadata
|
||||||
|
env:
|
||||||
|
IMAGES: git.ermnvldmr.com/${{ github.repository }}/docs
|
||||||
|
TAG_RULES: |
|
||||||
|
type=raw,value=latest
|
||||||
|
type=raw,value=${{ steps.vars.outputs.version }}
|
||||||
|
type=sha,format=short
|
||||||
|
SOURCE_SHA: ${{ github.sha }}
|
||||||
|
- name: Build and push Docker image
|
||||||
|
run: python3 ci/scripts/docker.py build
|
||||||
|
env:
|
||||||
|
TAGS: ${{ steps.meta.outputs.tags }}
|
||||||
|
LABELS: ${{ steps.meta.outputs.labels }}
|
||||||
|
BUILD_ARGS: |
|
||||||
|
COMMIT_SHA=${{ steps.vars.outputs.short_sha }}
|
||||||
|
VERSION=${{ steps.vars.outputs.version }}
|
||||||
|
DOCKERFILE: ci/docker/docs/Dockerfile
|
||||||
|
PLATFORMS: ''
|
||||||
|
PUSH: 'true'
|
||||||
|
CONTEXT: .
|
||||||
|
SOURCE_SHA: ${{ github.sha }}
|
||||||
|
RUN_ID: ${{ github.run_id }}
|
||||||
|
|
||||||
|
deploy:
|
||||||
|
name: Deploy - Kubernetes (GitOps)
|
||||||
|
needs: release-docker
|
||||||
|
runs-on: apex-debian13
|
||||||
|
if: github.event_name == 'push' && github.ref == 'refs/heads/next'
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
ref: next
|
||||||
|
- name: Setup Kustomize
|
||||||
|
run: test "$(kustomize version)" = v5.3.0
|
||||||
|
- name: Deploy via GitOps
|
||||||
|
run: |
|
||||||
|
DOCS_TAG="${{ needs.release-docker.outputs.version }}"
|
||||||
|
bash ci/scripts/deploy-gitops.sh docs "${DOCS_TAG}"
|
||||||
|
env:
|
||||||
|
GIT_WRITE_KEY: ${{ secrets.DOCS_DEPLOY_KEY }}
|
||||||
|
|
||||||
|
verify-rollout:
|
||||||
|
name: Verify - Production Rollout
|
||||||
|
needs:
|
||||||
|
- release-docker
|
||||||
|
- deploy
|
||||||
|
runs-on: apex-debian13
|
||||||
|
if: github.event_name == 'push' && github.ref == 'refs/heads/next'
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
ref: next
|
||||||
|
- name: Await production rollout
|
||||||
|
run: |
|
||||||
|
DOCS_TAG="${{ needs.release-docker.outputs.version }}"
|
||||||
|
bash ci/scripts/await-rollout.sh docs "${DOCS_TAG}"
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
name: services/docs - pr/required
|
||||||
|
'on':
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- next
|
||||||
|
paths:
|
||||||
|
- services/docs/**
|
||||||
|
- .gitea/workflows/services-docs-pr-required.yml
|
||||||
|
- ci/scripts/**
|
||||||
|
concurrency:
|
||||||
|
group: ci-pr-docs-${{ github.head_ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
actions: read
|
||||||
|
jobs:
|
||||||
|
setup-hugo:
|
||||||
|
name: Setup - Hugo
|
||||||
|
runs-on: apex-debian13
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
submodules: recursive
|
||||||
|
- name: Setup Hugo
|
||||||
|
run: hugo version | grep extended
|
||||||
|
build-hugo:
|
||||||
|
name: Build - Hugo Site
|
||||||
|
needs: setup-hugo
|
||||||
|
runs-on: apex-debian13
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
submodules: recursive
|
||||||
|
- name: Setup Hugo
|
||||||
|
run: hugo version | grep extended
|
||||||
|
- name: Build Hugo site
|
||||||
|
working-directory: services/docs
|
||||||
|
run: hugo --gc --minify
|
||||||
@@ -0,0 +1,195 @@
|
|||||||
|
name: services/static - next/required
|
||||||
|
'on':
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- next
|
||||||
|
paths:
|
||||||
|
- services/static/**
|
||||||
|
- packages/ui/**
|
||||||
|
- packages/stl/**
|
||||||
|
- packages/i18n/**
|
||||||
|
- .gitea/workflows/services-static-next-required.yml
|
||||||
|
- ci/scripts/**
|
||||||
|
- pnpm-lock.yaml
|
||||||
|
- ci/scripts/**
|
||||||
|
concurrency:
|
||||||
|
group: ci-static-${{ github.ref_name }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
actions: read
|
||||||
|
jobs:
|
||||||
|
setup-stage:
|
||||||
|
name: Setup - Stage
|
||||||
|
runs-on: apex-debian13
|
||||||
|
outputs: {}
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Pack dependency cache
|
||||||
|
run: python3 ci/scripts/cache.py pack
|
||||||
|
- uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: ${{ steps.dependency-cache.outputs.key }}
|
||||||
|
path: .ci/pnpm-store.tar
|
||||||
|
retention-days: 7
|
||||||
|
build-configs:
|
||||||
|
name: Build - Configs
|
||||||
|
needs: setup-stage
|
||||||
|
runs-on: apex-debian13
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Build Rsbuild config
|
||||||
|
run: pnpm --filter @ermnvldmr/rsbuild-config build
|
||||||
|
- name: Build i18n
|
||||||
|
run: pnpm --filter @ermnvldmr/i18n build
|
||||||
|
- name: Upload Config Artifacts
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rsbuild-config-dist
|
||||||
|
path: packages/rsbuild-config/dist
|
||||||
|
retention-days: 30
|
||||||
|
- name: Upload i18n dist
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: i18n-dist
|
||||||
|
path: packages/i18n/dist
|
||||||
|
retention-days: 30
|
||||||
|
lint-static:
|
||||||
|
name: Lint - Static
|
||||||
|
needs: build-configs
|
||||||
|
runs-on: apex-debian13
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Download Config Artifacts
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rsbuild-config-dist
|
||||||
|
path: packages/rsbuild-config/dist
|
||||||
|
- name: Download i18n dist
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: i18n-dist
|
||||||
|
path: packages/i18n/dist
|
||||||
|
- name: Lint static service
|
||||||
|
run: pnpm --filter @ermnvldmr/static lint
|
||||||
|
typecheck-static:
|
||||||
|
name: Typecheck - Static
|
||||||
|
needs: build-configs
|
||||||
|
runs-on: apex-debian13
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Download Config Artifacts
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rsbuild-config-dist
|
||||||
|
path: packages/rsbuild-config/dist
|
||||||
|
- name: Download i18n dist
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: i18n-dist
|
||||||
|
path: packages/i18n/dist
|
||||||
|
- name: Typecheck static service
|
||||||
|
run: pnpm --filter @ermnvldmr/static typecheck
|
||||||
|
build-static:
|
||||||
|
name: Build - Static Site
|
||||||
|
needs: build-configs
|
||||||
|
runs-on: apex-debian13
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Download Config Artifacts
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rsbuild-config-dist
|
||||||
|
path: packages/rsbuild-config/dist
|
||||||
|
- name: Download i18n dist
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: i18n-dist
|
||||||
|
path: packages/i18n/dist
|
||||||
|
- name: Build static service
|
||||||
|
run: pnpm --filter @ermnvldmr/static build
|
||||||
|
- name: Upload build artifacts
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: static-dist
|
||||||
|
path: services/static/dist/
|
||||||
|
retention-days: 30
|
||||||
|
deploy-s3:
|
||||||
|
name: Deploy - S3
|
||||||
|
needs:
|
||||||
|
- lint-static
|
||||||
|
- typecheck-static
|
||||||
|
- build-static
|
||||||
|
runs-on: apex-debian13
|
||||||
|
if: github.event_name == 'push' && github.ref == 'refs/heads/next'
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Download build artifacts
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: static-dist
|
||||||
|
path: services/static/dist/
|
||||||
|
- name: Deploy to S3
|
||||||
|
env:
|
||||||
|
AWS_ACCESS_KEY_ID: ${{ secrets.STATIC_AWS_ACCESS_KEY_ID }}
|
||||||
|
AWS_SECRET_ACCESS_KEY: ${{ secrets.STATIC_AWS_SECRET_ACCESS_KEY }}
|
||||||
|
AWS_DEFAULT_REGION: ${{ secrets.STATIC_AWS_REGION }}
|
||||||
|
S3_BUCKET: ${{ secrets.STATIC_S3_BUCKET }}
|
||||||
|
AWS_REGION: ${{ secrets.STATIC_AWS_REGION }}
|
||||||
|
S3_ENDPOINT_URL: ${{ secrets.STATIC_S3_ENDPOINT_URL }}
|
||||||
|
run: 'chmod +x ci/scripts/deploy-static.sh
|
||||||
|
|
||||||
|
./ci/scripts/deploy-static.sh
|
||||||
|
|
||||||
|
'
|
||||||
@@ -0,0 +1,166 @@
|
|||||||
|
name: services/static - pr/required
|
||||||
|
'on':
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- next
|
||||||
|
paths:
|
||||||
|
- services/static/**
|
||||||
|
- packages/ui/**
|
||||||
|
- packages/stl/**
|
||||||
|
- packages/i18n/**
|
||||||
|
- .gitea/workflows/services-static-pr-required.yml
|
||||||
|
- ci/scripts/**
|
||||||
|
- pnpm-lock.yaml
|
||||||
|
- ci/scripts/**
|
||||||
|
concurrency:
|
||||||
|
group: ci-pr-static-${{ github.head_ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
actions: read
|
||||||
|
jobs:
|
||||||
|
setup-stage:
|
||||||
|
name: Setup - Stage
|
||||||
|
runs-on: apex-debian13
|
||||||
|
outputs: {}
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Pack dependency cache
|
||||||
|
run: python3 ci/scripts/cache.py pack
|
||||||
|
- uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: ${{ steps.dependency-cache.outputs.key }}
|
||||||
|
path: .ci/pnpm-store.tar
|
||||||
|
retention-days: 7
|
||||||
|
build-configs:
|
||||||
|
name: Build - Configs
|
||||||
|
needs: setup-stage
|
||||||
|
runs-on: apex-debian13
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Build Rsbuild config
|
||||||
|
run: pnpm --filter @ermnvldmr/rsbuild-config build
|
||||||
|
- name: Build i18n
|
||||||
|
run: pnpm --filter @ermnvldmr/i18n build
|
||||||
|
- name: Upload Config Artifacts
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rsbuild-config-dist-${{ github.run_id }}
|
||||||
|
path: packages/rsbuild-config/dist
|
||||||
|
retention-days: 30
|
||||||
|
- name: Upload i18n dist
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: i18n-dist-${{ github.run_id }}
|
||||||
|
path: packages/i18n/dist
|
||||||
|
retention-days: 30
|
||||||
|
lint-static:
|
||||||
|
name: Lint - Static
|
||||||
|
needs: build-configs
|
||||||
|
runs-on: apex-debian13
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Download Config Artifacts
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rsbuild-config-dist-${{ github.run_id }}
|
||||||
|
path: packages/rsbuild-config/dist
|
||||||
|
- name: Download i18n dist
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: i18n-dist-${{ github.run_id }}
|
||||||
|
path: packages/i18n/dist
|
||||||
|
- name: Lint static service
|
||||||
|
run: pnpm --filter @ermnvldmr/static lint
|
||||||
|
typecheck-static:
|
||||||
|
name: Typecheck - Static
|
||||||
|
needs: build-configs
|
||||||
|
runs-on: apex-debian13
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Download Config Artifacts
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rsbuild-config-dist-${{ github.run_id }}
|
||||||
|
path: packages/rsbuild-config/dist
|
||||||
|
- name: Download i18n dist
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: i18n-dist-${{ github.run_id }}
|
||||||
|
path: packages/i18n/dist
|
||||||
|
- name: Typecheck static service
|
||||||
|
run: pnpm --filter @ermnvldmr/static typecheck
|
||||||
|
build-static:
|
||||||
|
name: Build - Static Site
|
||||||
|
needs: build-configs
|
||||||
|
runs-on: apex-debian13
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Download Config Artifacts
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rsbuild-config-dist-${{ github.run_id }}
|
||||||
|
path: packages/rsbuild-config/dist
|
||||||
|
- name: Download i18n dist
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: i18n-dist-${{ github.run_id }}
|
||||||
|
path: packages/i18n/dist
|
||||||
|
- name: Build static service
|
||||||
|
run: pnpm --filter @ermnvldmr/static build
|
||||||
|
- name: Upload build artifacts
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: static-dist-${{ github.run_id }}
|
||||||
|
path: services/static/dist/
|
||||||
|
retention-days: 30
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
name: services/www - manual deploy
|
||||||
|
'on':
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
tested_sha:
|
||||||
|
description: Full tested source commit (leave blank for latest)
|
||||||
|
required: false
|
||||||
|
type: string
|
||||||
|
default: ''
|
||||||
|
tested_digest:
|
||||||
|
description: OCI sha256 digest from the successful build (leave blank for latest)
|
||||||
|
required: false
|
||||||
|
type: string
|
||||||
|
default: ''
|
||||||
|
build_run_id:
|
||||||
|
description: Successful WWW build run ID (leave blank for latest)
|
||||||
|
required: false
|
||||||
|
type: string
|
||||||
|
default: ''
|
||||||
|
release_tag:
|
||||||
|
description: Previously approved release tag (leave blank for latest)
|
||||||
|
required: false
|
||||||
|
type: string
|
||||||
|
default: ''
|
||||||
|
release_run_id:
|
||||||
|
description: Approved release run ID (leave blank for latest)
|
||||||
|
required: false
|
||||||
|
type: string
|
||||||
|
default: ''
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
actions: read
|
||||||
|
jobs:
|
||||||
|
deploy:
|
||||||
|
name: Deploy - Kubernetes (GitOps)
|
||||||
|
runs-on: apex-debian13
|
||||||
|
if: github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/next' && github.actor == 'deytenit'
|
||||||
|
outputs:
|
||||||
|
short_sha: ${{ steps.provenance.outputs.short_sha }}
|
||||||
|
tested_digest: ${{ steps.provenance.outputs.tested_digest }}
|
||||||
|
release_tag: ${{ steps.provenance.outputs.release_tag }}
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
ref: next
|
||||||
|
- name: Authenticate local registry
|
||||||
|
run: python3 ci/scripts/docker.py login
|
||||||
|
env:
|
||||||
|
REGISTRY: git.ermnvldmr.com
|
||||||
|
REGISTRY_USER: ${{ github.repository_owner }}
|
||||||
|
REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN }}
|
||||||
|
- name: Verify successful build and approved release
|
||||||
|
id: provenance
|
||||||
|
run: python3 ci/scripts/provenance.py
|
||||||
|
env:
|
||||||
|
IS_DEPLOY: 'true'
|
||||||
|
TESTED_SHA: ${{ inputs.tested_sha }}
|
||||||
|
TESTED_DIGEST: ${{ inputs.tested_digest }}
|
||||||
|
BUILD_RUN_ID: ${{ inputs.build_run_id }}
|
||||||
|
RELEASE_RUN_ID: ${{ inputs.release_run_id }}
|
||||||
|
RELEASE_TAG: ${{ inputs.release_tag }}
|
||||||
|
PROVENANCE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Setup Kustomize
|
||||||
|
run: test "$(kustomize version)" = v5.3.0
|
||||||
|
- name: Deploy via GitOps
|
||||||
|
run: |
|
||||||
|
RELEASE_TAG="${{ steps.provenance.outputs.release_tag }}"
|
||||||
|
TESTED_DIGEST="${{ steps.provenance.outputs.tested_digest }}"
|
||||||
|
TESTED_SHA="${{ steps.provenance.outputs.tested_sha }}"
|
||||||
|
|
||||||
|
echo "Deploying www digest $TESTED_DIGEST ($RELEASE_TAG)..."
|
||||||
|
bash ci/scripts/deploy-gitops.sh www "$TESTED_DIGEST"
|
||||||
|
env:
|
||||||
|
GIT_WRITE_KEY: ${{ secrets.WWW_DEPLOY_KEY }}
|
||||||
|
|
||||||
|
verify-rollout:
|
||||||
|
name: Verify - Production Rollout
|
||||||
|
needs: deploy
|
||||||
|
runs-on: apex-debian13
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
ref: next
|
||||||
|
- name: Await production rollout
|
||||||
|
run: |
|
||||||
|
bash ci/scripts/await-rollout.sh www "${{ needs.deploy.outputs.short_sha }}"
|
||||||
@@ -0,0 +1,377 @@
|
|||||||
|
name: services/www - next/required
|
||||||
|
'on':
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- next
|
||||||
|
paths:
|
||||||
|
- services/www/**
|
||||||
|
- packages/ui/**
|
||||||
|
- packages/stl/**
|
||||||
|
- packages/i18n/**
|
||||||
|
- .gitea/workflows/services-www-next-required.yml
|
||||||
|
- ci/docker/www/**
|
||||||
|
- ci/config/nginx/**
|
||||||
|
- ci/scripts/**
|
||||||
|
- pnpm-lock.yaml
|
||||||
|
- ci/scripts/**
|
||||||
|
workflow_dispatch: null
|
||||||
|
concurrency:
|
||||||
|
group: ci-www-${{ github.ref_name }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
actions: read
|
||||||
|
jobs:
|
||||||
|
setup-stage:
|
||||||
|
name: Setup - Stage
|
||||||
|
runs-on: apex-debian13
|
||||||
|
outputs: {}
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Pack dependency cache
|
||||||
|
run: python3 ci/scripts/cache.py pack
|
||||||
|
- uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: ${{ steps.dependency-cache.outputs.key }}
|
||||||
|
path: .ci/pnpm-store.tar
|
||||||
|
retention-days: 7
|
||||||
|
build-configs:
|
||||||
|
name: Build - Configs
|
||||||
|
needs: setup-stage
|
||||||
|
runs-on: apex-debian13
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Build Rsbuild config
|
||||||
|
run: pnpm --filter @ermnvldmr/rsbuild-config build
|
||||||
|
- name: Build Storybook config
|
||||||
|
run: pnpm --filter @ermnvldmr/storybook-config build
|
||||||
|
- name: Upload Rsbuild Config
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rsbuild-config-dist
|
||||||
|
path: packages/rsbuild-config/dist
|
||||||
|
retention-days: 30
|
||||||
|
- name: Upload Storybook Config
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: storybook-config-dist
|
||||||
|
path: packages/storybook-config/dist
|
||||||
|
retention-days: 30
|
||||||
|
- name: Build i18n package
|
||||||
|
run: pnpm --filter @ermnvldmr/i18n build
|
||||||
|
- name: Upload i18n dist
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: i18n-dist
|
||||||
|
path: packages/i18n/dist
|
||||||
|
retention-days: 30
|
||||||
|
lint-www:
|
||||||
|
name: Lint - WWW
|
||||||
|
needs: build-configs
|
||||||
|
runs-on: apex-debian13
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Download Rsbuild Config
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rsbuild-config-dist
|
||||||
|
path: packages/rsbuild-config/dist
|
||||||
|
- name: Download i18n dist
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: i18n-dist
|
||||||
|
path: packages/i18n/dist
|
||||||
|
- name: Download Storybook Config
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: storybook-config-dist
|
||||||
|
path: packages/storybook-config/dist
|
||||||
|
- name: Lint WWW service
|
||||||
|
run: pnpm --filter @ermnvldmr/www lint
|
||||||
|
typecheck-www:
|
||||||
|
name: Typecheck - WWW
|
||||||
|
needs: build-configs
|
||||||
|
runs-on: apex-debian13
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Download Rsbuild Config
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rsbuild-config-dist
|
||||||
|
path: packages/rsbuild-config/dist
|
||||||
|
- name: Download i18n dist
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: i18n-dist
|
||||||
|
path: packages/i18n/dist
|
||||||
|
- name: Download Storybook Config
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: storybook-config-dist
|
||||||
|
path: packages/storybook-config/dist
|
||||||
|
- name: Typecheck WWW service
|
||||||
|
run: pnpm --filter @ermnvldmr/www typecheck
|
||||||
|
build-storybook:
|
||||||
|
name: Build - Storybook
|
||||||
|
needs: build-configs
|
||||||
|
runs-on: apex-debian13
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Download Rsbuild Config
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rsbuild-config-dist
|
||||||
|
path: packages/rsbuild-config/dist
|
||||||
|
- name: Download i18n dist
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: i18n-dist
|
||||||
|
path: packages/i18n/dist
|
||||||
|
- name: Download Storybook Config
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: storybook-config-dist
|
||||||
|
path: packages/storybook-config/dist
|
||||||
|
- name: Build WWW Storybook
|
||||||
|
run: pnpm --filter @ermnvldmr/www build-storybook
|
||||||
|
- name: Upload Storybook build
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: storybook-static
|
||||||
|
path: services/www/storybook-static/
|
||||||
|
retention-days: 30
|
||||||
|
test-www:
|
||||||
|
name: Test - Unit
|
||||||
|
needs: build-configs
|
||||||
|
runs-on: apex-debian13
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Download Rsbuild Config
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rsbuild-config-dist
|
||||||
|
path: packages/rsbuild-config/dist
|
||||||
|
- name: Download i18n dist
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: i18n-dist
|
||||||
|
path: packages/i18n/dist
|
||||||
|
- name: Download Storybook Config
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: storybook-config-dist
|
||||||
|
path: packages/storybook-config/dist
|
||||||
|
- name: Test WWW service
|
||||||
|
run: pnpm --filter @ermnvldmr/www test:coverage
|
||||||
|
test-storybook:
|
||||||
|
name: Test - Storybook
|
||||||
|
needs: build-storybook
|
||||||
|
runs-on: apex-debian13
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Download Rsbuild Config
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rsbuild-config-dist
|
||||||
|
path: packages/rsbuild-config/dist
|
||||||
|
- name: Download i18n dist
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: i18n-dist
|
||||||
|
path: packages/i18n/dist
|
||||||
|
- name: Download Storybook Config
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: storybook-config-dist
|
||||||
|
path: packages/storybook-config/dist
|
||||||
|
- name: Install Playwright browsers
|
||||||
|
run: pnpm --filter @ermnvldmr/www exec playwright install --with-deps chromium
|
||||||
|
- name: Download Storybook build
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: storybook-static
|
||||||
|
path: services/www/storybook-static/
|
||||||
|
- name: Serve Storybook and run tests with coverage
|
||||||
|
run: pnpm --filter @ermnvldmr/www test:storybook:ci
|
||||||
|
build-www:
|
||||||
|
name: Build - WWW Service
|
||||||
|
needs: build-configs
|
||||||
|
runs-on: apex-debian13
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Download Rsbuild Config
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rsbuild-config-dist
|
||||||
|
path: packages/rsbuild-config/dist
|
||||||
|
- name: Download i18n dist
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: i18n-dist
|
||||||
|
path: packages/i18n/dist
|
||||||
|
- name: Download Storybook Config
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: storybook-config-dist
|
||||||
|
path: packages/storybook-config/dist
|
||||||
|
- name: Build WWW service (all locales)
|
||||||
|
run: pnpm --filter @ermnvldmr/www build:all
|
||||||
|
env:
|
||||||
|
RSDOCTOR: 'true'
|
||||||
|
- name: Upload Rsdoctor report
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rsdoctor-report
|
||||||
|
path: services/www/rsdoctor/
|
||||||
|
retention-days: 30
|
||||||
|
build-docker:
|
||||||
|
name: Build - Docker Image
|
||||||
|
needs:
|
||||||
|
- lint-www
|
||||||
|
- typecheck-www
|
||||||
|
- test-www
|
||||||
|
- test-storybook
|
||||||
|
- build-www
|
||||||
|
runs-on: apex-debian13
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
packages: write
|
||||||
|
outputs:
|
||||||
|
short_sha: ${{ steps.vars.outputs.short_sha }}
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Calculate Short SHA
|
||||||
|
id: vars
|
||||||
|
run: |
|
||||||
|
SHORT_SHA="sha-$(echo ${{ github.sha }} | cut -c1-7)"
|
||||||
|
echo "short_sha=$SHORT_SHA" >> $GITHUB_OUTPUT
|
||||||
|
- name: Log in to Gitea Container Registry
|
||||||
|
run: python3 ci/scripts/docker.py login
|
||||||
|
env:
|
||||||
|
REGISTRY: git.ermnvldmr.com
|
||||||
|
REGISTRY_USER: ${{ github.repository_owner }}
|
||||||
|
REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN }}
|
||||||
|
- name: Extract Docker metadata
|
||||||
|
id: meta
|
||||||
|
run: python3 ci/scripts/docker.py metadata
|
||||||
|
env:
|
||||||
|
IMAGES: git.ermnvldmr.com/${{ github.repository }}/www
|
||||||
|
TAG_RULES: |
|
||||||
|
type=sha,format=short
|
||||||
|
SOURCE_SHA: ${{ github.sha }}
|
||||||
|
- name: Build and push Docker image
|
||||||
|
run: python3 ci/scripts/docker.py build
|
||||||
|
env:
|
||||||
|
TAGS: ${{ steps.meta.outputs.tags }}
|
||||||
|
LABELS: ${{ steps.meta.outputs.labels }}
|
||||||
|
BUILD_ARGS: |
|
||||||
|
COMMIT_SHA=${{ steps.vars.outputs.short_sha }}
|
||||||
|
VERSION=${{ steps.vars.outputs.short_sha }}
|
||||||
|
DOCKERFILE: ci/docker/www/Dockerfile
|
||||||
|
PLATFORMS: ''
|
||||||
|
PUSH: 'true'
|
||||||
|
CONTEXT: .
|
||||||
|
SOURCE_SHA: ${{ github.sha }}
|
||||||
|
RUN_ID: ${{ github.run_id }}
|
||||||
|
id: image
|
||||||
|
- name: Record tested digest provenance
|
||||||
|
env:
|
||||||
|
IMAGE_DIGEST: ${{ steps.image.outputs.digest }}
|
||||||
|
run: |
|
||||||
|
mkdir -p .ci
|
||||||
|
python3 - <<'PROVENANCE'
|
||||||
|
import json, os
|
||||||
|
from pathlib import Path
|
||||||
|
Path('.ci/www-provenance.json').write_text(json.dumps({
|
||||||
|
'sha': os.environ['GITHUB_SHA'],
|
||||||
|
'digest': os.environ['IMAGE_DIGEST'],
|
||||||
|
'run_id': os.environ['GITHUB_RUN_ID'],
|
||||||
|
'repository': os.environ['GITHUB_REPOSITORY']
|
||||||
|
}))
|
||||||
|
PROVENANCE
|
||||||
|
- uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: www-provenance
|
||||||
|
path: .ci/www-provenance.json
|
||||||
|
retention-days: 30
|
||||||
@@ -0,0 +1,302 @@
|
|||||||
|
name: services/www - pr/required
|
||||||
|
'on':
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- next
|
||||||
|
paths:
|
||||||
|
- services/www/**
|
||||||
|
- packages/ui/**
|
||||||
|
- packages/stl/**
|
||||||
|
- packages/i18n/**
|
||||||
|
- .gitea/workflows/services-www-pr-required.yml
|
||||||
|
- pnpm-lock.yaml
|
||||||
|
- ci/scripts/**
|
||||||
|
concurrency:
|
||||||
|
group: ci-pr-www-${{ github.head_ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
actions: read
|
||||||
|
jobs:
|
||||||
|
setup-stage:
|
||||||
|
name: Setup - Stage
|
||||||
|
runs-on: apex-debian13
|
||||||
|
outputs: {}
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Pack dependency cache
|
||||||
|
run: python3 ci/scripts/cache.py pack
|
||||||
|
- uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: ${{ steps.dependency-cache.outputs.key }}
|
||||||
|
path: .ci/pnpm-store.tar
|
||||||
|
retention-days: 7
|
||||||
|
build-configs:
|
||||||
|
name: Build - Configs
|
||||||
|
needs: setup-stage
|
||||||
|
runs-on: apex-debian13
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Build Rsbuild config
|
||||||
|
run: pnpm --filter @ermnvldmr/rsbuild-config build
|
||||||
|
- name: Build Storybook config
|
||||||
|
run: pnpm --filter @ermnvldmr/storybook-config build
|
||||||
|
- name: Upload Rsbuild Config
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rsbuild-config-dist-${{ github.run_id }}
|
||||||
|
path: packages/rsbuild-config/dist
|
||||||
|
retention-days: 30
|
||||||
|
- name: Upload Storybook Config
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: storybook-config-dist-${{ github.run_id }}
|
||||||
|
path: packages/storybook-config/dist
|
||||||
|
retention-days: 30
|
||||||
|
- name: Build i18n package
|
||||||
|
run: pnpm --filter @ermnvldmr/i18n build
|
||||||
|
- name: Upload i18n dist
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: i18n-dist-${{ github.run_id }}
|
||||||
|
path: packages/i18n/dist
|
||||||
|
retention-days: 30
|
||||||
|
lint-www:
|
||||||
|
name: Lint - WWW
|
||||||
|
needs: build-configs
|
||||||
|
runs-on: apex-debian13
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Download Rsbuild Config
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rsbuild-config-dist-${{ github.run_id }}
|
||||||
|
path: packages/rsbuild-config/dist
|
||||||
|
- name: Download i18n dist
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: i18n-dist-${{ github.run_id }}
|
||||||
|
path: packages/i18n/dist
|
||||||
|
- name: Download Storybook Config
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: storybook-config-dist-${{ github.run_id }}
|
||||||
|
path: packages/storybook-config/dist
|
||||||
|
- name: Lint WWW service
|
||||||
|
run: pnpm --filter @ermnvldmr/www lint
|
||||||
|
typecheck-www:
|
||||||
|
name: Typecheck - WWW
|
||||||
|
needs: build-configs
|
||||||
|
runs-on: apex-debian13
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Download Rsbuild Config
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rsbuild-config-dist-${{ github.run_id }}
|
||||||
|
path: packages/rsbuild-config/dist
|
||||||
|
- name: Download i18n dist
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: i18n-dist-${{ github.run_id }}
|
||||||
|
path: packages/i18n/dist
|
||||||
|
- name: Download Storybook Config
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: storybook-config-dist-${{ github.run_id }}
|
||||||
|
path: packages/storybook-config/dist
|
||||||
|
- name: Typecheck WWW service
|
||||||
|
run: pnpm --filter @ermnvldmr/www typecheck
|
||||||
|
build-storybook:
|
||||||
|
name: Build - Storybook
|
||||||
|
needs: build-configs
|
||||||
|
runs-on: apex-debian13
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Download Rsbuild Config
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rsbuild-config-dist-${{ github.run_id }}
|
||||||
|
path: packages/rsbuild-config/dist
|
||||||
|
- name: Download i18n dist
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: i18n-dist-${{ github.run_id }}
|
||||||
|
path: packages/i18n/dist
|
||||||
|
- name: Download Storybook Config
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: storybook-config-dist-${{ github.run_id }}
|
||||||
|
path: packages/storybook-config/dist
|
||||||
|
- name: Build WWW Storybook
|
||||||
|
run: pnpm --filter @ermnvldmr/www build-storybook
|
||||||
|
- name: Upload Storybook build
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: www-storybook-static-${{ github.run_id }}
|
||||||
|
path: services/www/storybook-static/
|
||||||
|
retention-days: 30
|
||||||
|
test-www:
|
||||||
|
name: Test - Unit
|
||||||
|
needs: build-configs
|
||||||
|
runs-on: apex-debian13
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Download Rsbuild Config
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rsbuild-config-dist-${{ github.run_id }}
|
||||||
|
path: packages/rsbuild-config/dist
|
||||||
|
- name: Download i18n dist
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: i18n-dist-${{ github.run_id }}
|
||||||
|
path: packages/i18n/dist
|
||||||
|
- name: Download Storybook Config
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: storybook-config-dist-${{ github.run_id }}
|
||||||
|
path: packages/storybook-config/dist
|
||||||
|
- name: Test WWW service
|
||||||
|
run: pnpm --filter @ermnvldmr/www test:coverage
|
||||||
|
test-storybook:
|
||||||
|
name: Test - Storybook
|
||||||
|
needs: build-storybook
|
||||||
|
runs-on: apex-debian13
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Download Rsbuild Config
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rsbuild-config-dist-${{ github.run_id }}
|
||||||
|
path: packages/rsbuild-config/dist
|
||||||
|
- name: Download i18n dist
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: i18n-dist-${{ github.run_id }}
|
||||||
|
path: packages/i18n/dist
|
||||||
|
- name: Download Storybook Config
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: storybook-config-dist-${{ github.run_id }}
|
||||||
|
path: packages/storybook-config/dist
|
||||||
|
- name: Install Playwright browsers
|
||||||
|
run: pnpm --filter @ermnvldmr/www exec playwright install --with-deps chromium
|
||||||
|
- name: Download Storybook build
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: www-storybook-static-${{ github.run_id }}
|
||||||
|
path: services/www/storybook-static/
|
||||||
|
- name: Serve Storybook and run tests with coverage
|
||||||
|
run: pnpm --filter @ermnvldmr/www test:storybook:ci
|
||||||
|
build-www:
|
||||||
|
name: Build - WWW Service
|
||||||
|
needs: build-configs
|
||||||
|
runs-on: apex-debian13
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup environment
|
||||||
|
run: bash ci/scripts/setup-env.sh 9.12.3 20
|
||||||
|
- name: Restore repository dependency cache
|
||||||
|
id: dependency-cache
|
||||||
|
run: python3 ci/scripts/cache.py restore
|
||||||
|
env:
|
||||||
|
CACHE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
- name: Download Rsbuild Config
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rsbuild-config-dist-${{ github.run_id }}
|
||||||
|
path: packages/rsbuild-config/dist
|
||||||
|
- name: Download i18n dist
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: i18n-dist-${{ github.run_id }}
|
||||||
|
path: packages/i18n/dist
|
||||||
|
- name: Download Storybook Config
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: storybook-config-dist-${{ github.run_id }}
|
||||||
|
path: packages/storybook-config/dist
|
||||||
|
- name: Build WWW service (all locales)
|
||||||
|
run: pnpm --filter @ermnvldmr/www build:all
|
||||||
|
env:
|
||||||
|
RSDOCTOR: 'true'
|
||||||
|
- name: Upload Rsdoctor report
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rsdoctor-report-${{ github.run_id }}
|
||||||
|
path: services/www/rsdoctor/
|
||||||
|
retention-days: 30
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
name: services/www - manual release
|
||||||
|
'on':
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
tested_sha:
|
||||||
|
description: Full tested source commit (leave blank for latest)
|
||||||
|
required: false
|
||||||
|
type: string
|
||||||
|
default: ''
|
||||||
|
tested_digest:
|
||||||
|
description: OCI sha256 digest (leave blank for latest)
|
||||||
|
required: false
|
||||||
|
type: string
|
||||||
|
default: ''
|
||||||
|
build_run_id:
|
||||||
|
description: Successful WWW build run ID (leave blank for latest)
|
||||||
|
required: false
|
||||||
|
type: string
|
||||||
|
default: ''
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
packages: write
|
||||||
|
actions: read
|
||||||
|
jobs:
|
||||||
|
release:
|
||||||
|
name: Release - Tag and Promote
|
||||||
|
runs-on: apex-debian13
|
||||||
|
if: github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/next' && github.actor == 'deytenit'
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
- name: Authenticate local registry
|
||||||
|
run: python3 ci/scripts/docker.py login
|
||||||
|
env:
|
||||||
|
REGISTRY: git.ermnvldmr.com
|
||||||
|
REGISTRY_USER: ${{ github.repository_owner }}
|
||||||
|
REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN }}
|
||||||
|
- name: Verify successful build and immutable digest
|
||||||
|
id: provenance
|
||||||
|
run: python3 ci/scripts/provenance.py
|
||||||
|
env:
|
||||||
|
TESTED_SHA: ${{ inputs.tested_sha }}
|
||||||
|
TESTED_DIGEST: ${{ inputs.tested_digest }}
|
||||||
|
BUILD_RUN_ID: ${{ inputs.build_run_id }}
|
||||||
|
PROVENANCE_TOKEN: ${{ github.token }}
|
||||||
|
- name: Promote tested digest and create release tag
|
||||||
|
env:
|
||||||
|
TESTED_SHA: ${{ steps.provenance.outputs.tested_sha }}
|
||||||
|
TESTED_DIGEST: ${{ steps.provenance.outputs.tested_digest }}
|
||||||
|
BUILD_RUN_ID: ${{ steps.provenance.outputs.build_run_id }}
|
||||||
|
PROVENANCE_TOKEN: ${{ github.token }}
|
||||||
|
GIT_WRITE_KEY: ${{ secrets.WWW_DEPLOY_KEY }}
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
VERSION=$(bash ci/scripts/calver-release.sh www)
|
||||||
|
TAG_NAME="services/www-$VERSION"
|
||||||
|
|
||||||
|
echo "Tagging Git commit $TESTED_SHA with $TAG_NAME..."
|
||||||
|
bash ci/scripts/calver-release.sh tag www "$TESTED_SHA" "$VERSION"
|
||||||
|
|
||||||
|
echo "Promoting Docker image to $VERSION and latest..."
|
||||||
|
docker buildx imagetools create --prefer-index=false \
|
||||||
|
"git.ermnvldmr.com/${{ github.repository }}/www@$TESTED_DIGEST" \
|
||||||
|
--tag "git.ermnvldmr.com/${{ github.repository }}/www:$VERSION" \
|
||||||
|
--tag "git.ermnvldmr.com/${{ github.repository }}/www:latest"
|
||||||
|
|
||||||
|
test "$(docker buildx imagetools inspect "git.ermnvldmr.com/${{ github.repository }}/www:$VERSION" --format '{{.Manifest.Digest}}')" = "$TESTED_DIGEST"
|
||||||
|
|
||||||
|
export VERSION TAG_NAME
|
||||||
|
mkdir -p .ci
|
||||||
|
python3 - <<'RELEASE_PROVENANCE'
|
||||||
|
import json, os
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
Path('.ci/www-release.json').write_text(json.dumps({
|
||||||
|
'sha': os.environ['TESTED_SHA'],
|
||||||
|
'digest': os.environ['TESTED_DIGEST'],
|
||||||
|
'run_id': os.environ['BUILD_RUN_ID'],
|
||||||
|
'repository': os.environ['GITHUB_REPOSITORY'],
|
||||||
|
'release_tag': os.environ['TAG_NAME'],
|
||||||
|
'version': os.environ['VERSION']
|
||||||
|
}))
|
||||||
|
RELEASE_PROVENANCE
|
||||||
|
- uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: www-release-provenance
|
||||||
|
path: .ci/www-release.json
|
||||||
|
retention-days: 30
|
||||||
@@ -1,134 +0,0 @@
|
|||||||
name: ci - next/build-golden-image
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ci-golden-image
|
|
||||||
cancel-in-progress: false
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
validate-scripts:
|
|
||||||
name: Validate - Provisioner Scripts
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Validate Shell Script Syntax
|
|
||||||
run: bash -n ci/packer/scripts/*.sh
|
|
||||||
|
|
||||||
build-image:
|
|
||||||
name: Build - Golden Image
|
|
||||||
needs: validate-scripts
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
outputs:
|
|
||||||
image_name: ${{ steps.vars.outputs.image_name }}
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Calculate Image Name
|
|
||||||
id: vars
|
|
||||||
run: |
|
|
||||||
SHORT_SHA="$(echo ${{ github.sha }} | cut -c1-7)"
|
|
||||||
IMAGE_NAME="com-ermnvldmr-debian-12-k3s-amd64-${SHORT_SHA}.qcow2"
|
|
||||||
echo "image_name=${IMAGE_NAME}" >> "$GITHUB_OUTPUT"
|
|
||||||
|
|
||||||
- name: Install Build Tools
|
|
||||||
run: |
|
|
||||||
sudo apt-get update
|
|
||||||
sudo apt-get install -y qemu-utils
|
|
||||||
|
|
||||||
- name: Build Debian K3s Golden Image
|
|
||||||
run: |
|
|
||||||
mkdir -p output-qemu
|
|
||||||
echo "Downloading official Debian 12 cloud image..."
|
|
||||||
curl -fsSL -o base.qcow2 https://cloud.debian.org/images/cloud/bookworm/latest/debian-12-genericcloud-amd64.qcow2
|
|
||||||
|
|
||||||
echo "Expanding disk image to 10G..."
|
|
||||||
qemu-img resize base.qcow2 10G
|
|
||||||
|
|
||||||
echo "Connecting disk image via NBD..."
|
|
||||||
sudo modprobe nbd max_part=8
|
|
||||||
sudo qemu-nbd --connect=/dev/nbd0 base.qcow2
|
|
||||||
sleep 1
|
|
||||||
sudo partx -u /dev/nbd0 || true
|
|
||||||
|
|
||||||
echo "Mounting disk filesystem..."
|
|
||||||
sudo mkdir -p /mnt/target
|
|
||||||
sudo mount /dev/nbd0p1 /mnt/target
|
|
||||||
|
|
||||||
echo "Mounting host virtual filesystems and configuring DNS..."
|
|
||||||
sudo rm -f /mnt/target/etc/resolv.conf
|
|
||||||
echo "nameserver 1.1.1.1" | sudo tee /mnt/target/etc/resolv.conf
|
|
||||||
echo "nameserver 8.8.8.8" | sudo tee -a /mnt/target/etc/resolv.conf
|
|
||||||
sudo mount --bind /dev /mnt/target/dev
|
|
||||||
sudo mount --bind /dev/pts /mnt/target/dev/pts
|
|
||||||
sudo mount --bind /proc /mnt/target/proc
|
|
||||||
sudo mount --bind /sys /mnt/target/sys
|
|
||||||
|
|
||||||
echo "Copying provisioner scripts..."
|
|
||||||
sudo mkdir -p /mnt/target/tmp/scripts
|
|
||||||
sudo cp ci/packer/scripts/*.sh /mnt/target/tmp/scripts/
|
|
||||||
sudo chmod +x /mnt/target/tmp/scripts/*.sh
|
|
||||||
|
|
||||||
echo "Running provisioner scripts in chroot..."
|
|
||||||
sudo chroot /mnt/target /bin/bash /tmp/scripts/01-base-system.sh
|
|
||||||
sudo chroot /mnt/target /bin/bash /tmp/scripts/02-install-k3s.sh
|
|
||||||
sudo chroot /mnt/target /bin/bash /tmp/scripts/03-cleanup.sh
|
|
||||||
sudo rm -rf /mnt/target/tmp/scripts
|
|
||||||
|
|
||||||
echo "Unmounting filesystems..."
|
|
||||||
sudo umount /mnt/target/sys
|
|
||||||
sudo umount /mnt/target/proc
|
|
||||||
sudo umount /mnt/target/dev/pts
|
|
||||||
sudo umount /mnt/target/dev
|
|
||||||
sudo umount /mnt/target
|
|
||||||
sudo qemu-nbd --disconnect /dev/nbd0
|
|
||||||
|
|
||||||
echo "Compressing and optimizing qcow2 with 2M cluster size..."
|
|
||||||
qemu-img convert -f qcow2 -O qcow2 -o cluster_size=2M -c base.qcow2 output-qemu/com-ermnvldmr-debian-12-k3s-amd64.qcow2
|
|
||||||
echo "Golden image built successfully."
|
|
||||||
|
|
||||||
- name: Prepare and Upload Image Artifact
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: golden-image
|
|
||||||
path: output-qemu/com-ermnvldmr-debian-12-k3s-amd64.qcow2
|
|
||||||
retention-days: 1
|
|
||||||
|
|
||||||
upload-s3:
|
|
||||||
name: Upload - S3 Storage
|
|
||||||
needs: build-image
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Download Image Artifact
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: golden-image
|
|
||||||
path: output-qemu
|
|
||||||
|
|
||||||
- name: Upload to Static S3 (/dev/images/)
|
|
||||||
env:
|
|
||||||
AWS_ACCESS_KEY_ID: ${{ secrets.STATIC_AWS_ACCESS_KEY_ID || secrets.COM_ERMNVLDMR_STATIC_AWS_ACCESS_KEY_ID }}
|
|
||||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.STATIC_AWS_SECRET_ACCESS_KEY || secrets.COM_ERMNVLDMR_STATIC_AWS_SECRET_ACCESS_KEY }}
|
|
||||||
AWS_DEFAULT_REGION: ${{ secrets.STATIC_AWS_REGION || secrets.COM_ERMNVLDMR_STATIC_S3_REGION || 'ru-central1' }}
|
|
||||||
S3_ENDPOINT: ${{ secrets.STATIC_S3_ENDPOINT_URL || secrets.COM_ERMNVLDMR_STATIC_S3_ENDPOINT_URL }}
|
|
||||||
S3_BUCKET: ${{ secrets.STATIC_S3_BUCKET || secrets.COM_ERMNVLDMR_STATIC_S3_BUCKET }}
|
|
||||||
IMAGE_NAME: ${{ needs.build-image.outputs.image_name }}
|
|
||||||
run: |
|
|
||||||
mv output-qemu/com-ermnvldmr-debian-12-k3s-amd64.qcow2 "output-qemu/${IMAGE_NAME}"
|
|
||||||
if [ -n "${S3_BUCKET}" ] && [ -n "${AWS_ACCESS_KEY_ID}" ]; then
|
|
||||||
ENDPOINT_FLAG=""
|
|
||||||
[ -n "${S3_ENDPOINT}" ] && ENDPOINT_FLAG="--endpoint-url=${S3_ENDPOINT}"
|
|
||||||
echo "Cleaning up older images in dev/images/ to free bucket storage..."
|
|
||||||
aws ${ENDPOINT_FLAG} s3 rm "s3://${S3_BUCKET}/dev/images/" --recursive || true
|
|
||||||
aws ${ENDPOINT_FLAG} s3 cp "output-qemu/${IMAGE_NAME}" "s3://${S3_BUCKET}/dev/images/${IMAGE_NAME}"
|
|
||||||
echo "Golden image uploaded to s3://${S3_BUCKET}/dev/images/${IMAGE_NAME}"
|
|
||||||
else
|
|
||||||
echo "S3 storage secrets not provided; skipping remote S3 upload. Image artifact is preserved in GitHub Actions run artifacts."
|
|
||||||
fi
|
|
||||||
@@ -1,361 +0,0 @@
|
|||||||
name: packages/kits - next/required
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [next]
|
|
||||||
paths:
|
|
||||||
- 'packages/kits/**'
|
|
||||||
- 'packages/ui/**'
|
|
||||||
- 'packages/stl/**'
|
|
||||||
- 'packages/i18n/**'
|
|
||||||
- '.github/workflows/packages-kits-next-required.yml'
|
|
||||||
- 'pnpm-lock.yaml'
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ci-next-kits-${{ github.ref }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
actions: read
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
setup-stage:
|
|
||||||
name: Setup - Stage
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
outputs:
|
|
||||||
cache-hit: ${{ steps.cache-pnpm-store.outputs.cache-hit }}
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
|
|
||||||
- name: Setup Node.js with pnpm cache
|
|
||||||
uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
|
|
||||||
- name: Cache pnpm store
|
|
||||||
id: cache-pnpm-store
|
|
||||||
uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: ~/.pnpm-store
|
|
||||||
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
|
|
||||||
build-configs:
|
|
||||||
name: Build - Configs & UI
|
|
||||||
needs: setup-stage
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
- name: Build Rsbuild config
|
|
||||||
run: pnpm --filter @ermnvldmr/rsbuild-config build
|
|
||||||
- name: Build Storybook config
|
|
||||||
run: pnpm --filter @ermnvldmr/storybook-config build
|
|
||||||
- name: Build i18n
|
|
||||||
run: pnpm --filter @ermnvldmr/i18n build
|
|
||||||
- name: Build UI
|
|
||||||
run: pnpm --filter @ermnvldmr/ui build
|
|
||||||
- name: Upload Rsbuild Config
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: rsbuild-config-dist-${{ github.run_id }}
|
|
||||||
path: packages/rsbuild-config/dist
|
|
||||||
retention-days: 1
|
|
||||||
- name: Upload Storybook Config
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: storybook-config-dist-${{ github.run_id }}
|
|
||||||
path: packages/storybook-config/dist
|
|
||||||
retention-days: 1
|
|
||||||
- name: Upload i18n dist
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: i18n-dist-${{ github.run_id }}
|
|
||||||
path: packages/i18n/dist
|
|
||||||
retention-days: 1
|
|
||||||
- name: Upload UI dist
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: ui-dist-${{ github.run_id }}
|
|
||||||
path: packages/ui/dist
|
|
||||||
retention-days: 1
|
|
||||||
|
|
||||||
lint-kits:
|
|
||||||
name: Lint - Kits
|
|
||||||
needs: build-configs
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
- name: Download Rsbuild Config
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: rsbuild-config-dist-${{ github.run_id }}
|
|
||||||
path: packages/rsbuild-config/dist
|
|
||||||
- name: Download Storybook Config
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: storybook-config-dist-${{ github.run_id }}
|
|
||||||
path: packages/storybook-config/dist
|
|
||||||
- name: Download i18n dist
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: i18n-dist-${{ github.run_id }}
|
|
||||||
path: packages/i18n/dist
|
|
||||||
- name: Download UI dist
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: ui-dist-${{ github.run_id }}
|
|
||||||
path: packages/ui/dist
|
|
||||||
- name: Lint Kits package
|
|
||||||
run: pnpm --filter @ermnvldmr/kits lint
|
|
||||||
|
|
||||||
typecheck-kits:
|
|
||||||
name: Typecheck - Kits
|
|
||||||
needs: build-configs
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
- name: Download Rsbuild Config
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: rsbuild-config-dist-${{ github.run_id }}
|
|
||||||
path: packages/rsbuild-config/dist
|
|
||||||
- name: Download Storybook Config
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: storybook-config-dist-${{ github.run_id }}
|
|
||||||
path: packages/storybook-config/dist
|
|
||||||
- name: Download i18n dist
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: i18n-dist-${{ github.run_id }}
|
|
||||||
path: packages/i18n/dist
|
|
||||||
- name: Download UI dist
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: ui-dist-${{ github.run_id }}
|
|
||||||
path: packages/ui/dist
|
|
||||||
- name: Typecheck Kits package
|
|
||||||
run: pnpm --filter @ermnvldmr/kits typecheck
|
|
||||||
|
|
||||||
test-kits:
|
|
||||||
name: Test - Unit
|
|
||||||
needs: build-configs
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
- name: Download Rsbuild Config
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: rsbuild-config-dist-${{ github.run_id }}
|
|
||||||
path: packages/rsbuild-config/dist
|
|
||||||
- name: Download Storybook Config
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: storybook-config-dist-${{ github.run_id }}
|
|
||||||
path: packages/storybook-config/dist
|
|
||||||
- name: Download i18n dist
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: i18n-dist-${{ github.run_id }}
|
|
||||||
path: packages/i18n/dist
|
|
||||||
- name: Download UI dist
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: ui-dist-${{ github.run_id }}
|
|
||||||
path: packages/ui/dist
|
|
||||||
- name: Test Kits package
|
|
||||||
run: pnpm --filter @ermnvldmr/kits test:coverage
|
|
||||||
- name: Upload coverage to Codecov
|
|
||||||
uses: codecov/codecov-action@v4
|
|
||||||
with:
|
|
||||||
files: ./packages/kits/coverage/lcov.info
|
|
||||||
flags: kits
|
|
||||||
env:
|
|
||||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
|
||||||
|
|
||||||
build-storybook:
|
|
||||||
name: Build - Storybook
|
|
||||||
needs: build-configs
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
- name: Download Rsbuild Config
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: rsbuild-config-dist-${{ github.run_id }}
|
|
||||||
path: packages/rsbuild-config/dist
|
|
||||||
- name: Download Storybook Config
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: storybook-config-dist-${{ github.run_id }}
|
|
||||||
path: packages/storybook-config/dist
|
|
||||||
- name: Download i18n dist
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: i18n-dist-${{ github.run_id }}
|
|
||||||
path: packages/i18n/dist
|
|
||||||
- name: Download UI dist
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: ui-dist-${{ github.run_id }}
|
|
||||||
path: packages/ui/dist
|
|
||||||
- name: Build Kits Storybook
|
|
||||||
run: pnpm --filter @ermnvldmr/kits build-storybook
|
|
||||||
- name: Upload Storybook build
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: kits-storybook-static-${{ github.run_id }}
|
|
||||||
path: packages/kits/storybook-static/
|
|
||||||
retention-days: 1
|
|
||||||
|
|
||||||
test-storybook:
|
|
||||||
name: Test - Storybook
|
|
||||||
needs: build-storybook
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
- name: Download Rsbuild Config
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: rsbuild-config-dist-${{ github.run_id }}
|
|
||||||
path: packages/rsbuild-config/dist
|
|
||||||
- name: Download Storybook Config
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: storybook-config-dist-${{ github.run_id }}
|
|
||||||
path: packages/storybook-config/dist
|
|
||||||
- name: Download i18n dist
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: i18n-dist-${{ github.run_id }}
|
|
||||||
path: packages/i18n/dist
|
|
||||||
- name: Download UI dist
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: ui-dist-${{ github.run_id }}
|
|
||||||
path: packages/ui/dist
|
|
||||||
- name: Install Playwright browsers
|
|
||||||
run: pnpm --filter @ermnvldmr/kits exec playwright install --with-deps chromium
|
|
||||||
- name: Download Storybook build
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: kits-storybook-static-${{ github.run_id }}
|
|
||||||
path: packages/kits/storybook-static/
|
|
||||||
- name: Test Storybook
|
|
||||||
run: pnpm --filter @ermnvldmr/kits test:storybook:ci
|
|
||||||
- name: Upload coverage to Codecov
|
|
||||||
uses: codecov/codecov-action@v4
|
|
||||||
with:
|
|
||||||
files: ./packages/kits/coverage/storybook/lcov.info
|
|
||||||
flags: kits-storybook
|
|
||||||
env:
|
|
||||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
|
||||||
|
|
||||||
build-kits:
|
|
||||||
name: Build - Kits
|
|
||||||
needs: build-configs
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
- name: Download Rsbuild Config
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: rsbuild-config-dist-${{ github.run_id }}
|
|
||||||
path: packages/rsbuild-config/dist
|
|
||||||
- name: Download Storybook Config
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: storybook-config-dist-${{ github.run_id }}
|
|
||||||
path: packages/storybook-config/dist
|
|
||||||
- name: Download i18n dist
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: i18n-dist-${{ github.run_id }}
|
|
||||||
path: packages/i18n/dist
|
|
||||||
- name: Download UI dist
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: ui-dist-${{ github.run_id }}
|
|
||||||
path: packages/ui/dist
|
|
||||||
- name: Build Kits package
|
|
||||||
run: pnpm --filter @ermnvldmr/kits build
|
|
||||||
@@ -1,361 +0,0 @@
|
|||||||
name: packages/kits - pr/required
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
branches: [next]
|
|
||||||
paths:
|
|
||||||
- 'packages/kits/**'
|
|
||||||
- 'packages/ui/**'
|
|
||||||
- 'packages/stl/**'
|
|
||||||
- 'packages/i18n/**'
|
|
||||||
- '.github/workflows/packages-kits-pr-required.yml'
|
|
||||||
- 'pnpm-lock.yaml'
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ci-pr-kits-${{ github.head_ref }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
actions: read
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
setup-stage:
|
|
||||||
name: Setup - Stage
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
outputs:
|
|
||||||
cache-hit: ${{ steps.cache-pnpm-store.outputs.cache-hit }}
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
|
|
||||||
- name: Setup Node.js with pnpm cache
|
|
||||||
uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
|
|
||||||
- name: Cache pnpm store
|
|
||||||
id: cache-pnpm-store
|
|
||||||
uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: ~/.pnpm-store
|
|
||||||
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
|
|
||||||
build-configs:
|
|
||||||
name: Build - Configs & UI
|
|
||||||
needs: setup-stage
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
- name: Build Rsbuild config
|
|
||||||
run: pnpm --filter @ermnvldmr/rsbuild-config build
|
|
||||||
- name: Build Storybook config
|
|
||||||
run: pnpm --filter @ermnvldmr/storybook-config build
|
|
||||||
- name: Build i18n
|
|
||||||
run: pnpm --filter @ermnvldmr/i18n build
|
|
||||||
- name: Build UI
|
|
||||||
run: pnpm --filter @ermnvldmr/ui build
|
|
||||||
- name: Upload Rsbuild Config
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: rsbuild-config-dist-${{ github.run_id }}
|
|
||||||
path: packages/rsbuild-config/dist
|
|
||||||
retention-days: 1
|
|
||||||
- name: Upload Storybook Config
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: storybook-config-dist-${{ github.run_id }}
|
|
||||||
path: packages/storybook-config/dist
|
|
||||||
retention-days: 1
|
|
||||||
- name: Upload i18n dist
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: i18n-dist-${{ github.run_id }}
|
|
||||||
path: packages/i18n/dist
|
|
||||||
retention-days: 1
|
|
||||||
- name: Upload UI dist
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: ui-dist-${{ github.run_id }}
|
|
||||||
path: packages/ui/dist
|
|
||||||
retention-days: 1
|
|
||||||
|
|
||||||
lint-kits:
|
|
||||||
name: Lint - Kits
|
|
||||||
needs: build-configs
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
- name: Download Rsbuild Config
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: rsbuild-config-dist-${{ github.run_id }}
|
|
||||||
path: packages/rsbuild-config/dist
|
|
||||||
- name: Download Storybook Config
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: storybook-config-dist-${{ github.run_id }}
|
|
||||||
path: packages/storybook-config/dist
|
|
||||||
- name: Download i18n dist
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: i18n-dist-${{ github.run_id }}
|
|
||||||
path: packages/i18n/dist
|
|
||||||
- name: Download UI dist
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: ui-dist-${{ github.run_id }}
|
|
||||||
path: packages/ui/dist
|
|
||||||
- name: Lint Kits package
|
|
||||||
run: pnpm --filter @ermnvldmr/kits lint
|
|
||||||
|
|
||||||
typecheck-kits:
|
|
||||||
name: Typecheck - Kits
|
|
||||||
needs: build-configs
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
- name: Download Rsbuild Config
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: rsbuild-config-dist-${{ github.run_id }}
|
|
||||||
path: packages/rsbuild-config/dist
|
|
||||||
- name: Download Storybook Config
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: storybook-config-dist-${{ github.run_id }}
|
|
||||||
path: packages/storybook-config/dist
|
|
||||||
- name: Download i18n dist
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: i18n-dist-${{ github.run_id }}
|
|
||||||
path: packages/i18n/dist
|
|
||||||
- name: Download UI dist
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: ui-dist-${{ github.run_id }}
|
|
||||||
path: packages/ui/dist
|
|
||||||
- name: Typecheck Kits package
|
|
||||||
run: pnpm --filter @ermnvldmr/kits typecheck
|
|
||||||
|
|
||||||
test-kits:
|
|
||||||
name: Test - Unit
|
|
||||||
needs: build-configs
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
- name: Download Rsbuild Config
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: rsbuild-config-dist-${{ github.run_id }}
|
|
||||||
path: packages/rsbuild-config/dist
|
|
||||||
- name: Download Storybook Config
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: storybook-config-dist-${{ github.run_id }}
|
|
||||||
path: packages/storybook-config/dist
|
|
||||||
- name: Download i18n dist
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: i18n-dist-${{ github.run_id }}
|
|
||||||
path: packages/i18n/dist
|
|
||||||
- name: Download UI dist
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: ui-dist-${{ github.run_id }}
|
|
||||||
path: packages/ui/dist
|
|
||||||
- name: Test Kits package
|
|
||||||
run: pnpm --filter @ermnvldmr/kits test:coverage
|
|
||||||
- name: Upload coverage to Codecov
|
|
||||||
uses: codecov/codecov-action@v4
|
|
||||||
with:
|
|
||||||
files: ./packages/kits/coverage/lcov.info
|
|
||||||
flags: kits
|
|
||||||
env:
|
|
||||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
|
||||||
|
|
||||||
build-storybook:
|
|
||||||
name: Build - Storybook
|
|
||||||
needs: build-configs
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
- name: Download Rsbuild Config
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: rsbuild-config-dist-${{ github.run_id }}
|
|
||||||
path: packages/rsbuild-config/dist
|
|
||||||
- name: Download Storybook Config
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: storybook-config-dist-${{ github.run_id }}
|
|
||||||
path: packages/storybook-config/dist
|
|
||||||
- name: Download i18n dist
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: i18n-dist-${{ github.run_id }}
|
|
||||||
path: packages/i18n/dist
|
|
||||||
- name: Download UI dist
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: ui-dist-${{ github.run_id }}
|
|
||||||
path: packages/ui/dist
|
|
||||||
- name: Build Kits Storybook
|
|
||||||
run: pnpm --filter @ermnvldmr/kits build-storybook
|
|
||||||
- name: Upload Storybook build
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: kits-storybook-static-${{ github.run_id }}
|
|
||||||
path: packages/kits/storybook-static/
|
|
||||||
retention-days: 1
|
|
||||||
|
|
||||||
test-storybook:
|
|
||||||
name: Test - Storybook
|
|
||||||
needs: build-storybook
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
- name: Download Rsbuild Config
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: rsbuild-config-dist-${{ github.run_id }}
|
|
||||||
path: packages/rsbuild-config/dist
|
|
||||||
- name: Download Storybook Config
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: storybook-config-dist-${{ github.run_id }}
|
|
||||||
path: packages/storybook-config/dist
|
|
||||||
- name: Download i18n dist
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: i18n-dist-${{ github.run_id }}
|
|
||||||
path: packages/i18n/dist
|
|
||||||
- name: Download UI dist
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: ui-dist-${{ github.run_id }}
|
|
||||||
path: packages/ui/dist
|
|
||||||
- name: Install Playwright browsers
|
|
||||||
run: pnpm --filter @ermnvldmr/kits exec playwright install --with-deps chromium
|
|
||||||
- name: Download Storybook build
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: kits-storybook-static-${{ github.run_id }}
|
|
||||||
path: packages/kits/storybook-static/
|
|
||||||
- name: Test Storybook
|
|
||||||
run: pnpm --filter @ermnvldmr/kits test:storybook:ci
|
|
||||||
- name: Upload coverage to Codecov
|
|
||||||
uses: codecov/codecov-action@v4
|
|
||||||
with:
|
|
||||||
files: ./packages/kits/coverage/storybook/lcov.info
|
|
||||||
flags: kits-storybook
|
|
||||||
env:
|
|
||||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
|
||||||
|
|
||||||
build-kits:
|
|
||||||
name: Build - Kits
|
|
||||||
needs: build-configs
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
- name: Download Rsbuild Config
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: rsbuild-config-dist-${{ github.run_id }}
|
|
||||||
path: packages/rsbuild-config/dist
|
|
||||||
- name: Download Storybook Config
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: storybook-config-dist-${{ github.run_id }}
|
|
||||||
path: packages/storybook-config/dist
|
|
||||||
- name: Download i18n dist
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: i18n-dist-${{ github.run_id }}
|
|
||||||
path: packages/i18n/dist
|
|
||||||
- name: Download UI dist
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: ui-dist-${{ github.run_id }}
|
|
||||||
path: packages/ui/dist
|
|
||||||
- name: Build Kits package
|
|
||||||
run: pnpm --filter @ermnvldmr/kits build
|
|
||||||
@@ -1,145 +0,0 @@
|
|||||||
name: packages/ssg - next/required
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [next]
|
|
||||||
paths:
|
|
||||||
- 'packages/ssg/**'
|
|
||||||
- '.github/workflows/packages-ssg-next-required.yml'
|
|
||||||
- 'pnpm-lock.yaml'
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ci-ssg-${{ github.ref_name }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
actions: read
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
setup-stage:
|
|
||||||
name: Setup - Stage
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
outputs:
|
|
||||||
cache-hit: ${{ steps.cache-pnpm-store.outputs.cache-hit }}
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
|
|
||||||
- name: Setup Node.js with pnpm cache
|
|
||||||
uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
|
|
||||||
- name: Cache pnpm store
|
|
||||||
id: cache-pnpm-store
|
|
||||||
uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: ~/.pnpm-store
|
|
||||||
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
|
|
||||||
build-configs:
|
|
||||||
name: Build - Configs
|
|
||||||
needs: setup-stage
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
- name: Build Rsbuild config
|
|
||||||
run: pnpm --filter @ermnvldmr/rsbuild-config build
|
|
||||||
- name: Upload Config Artifacts
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: rsbuild-config-dist
|
|
||||||
path: packages/rsbuild-config/dist
|
|
||||||
retention-days: 1
|
|
||||||
|
|
||||||
lint-ssg:
|
|
||||||
name: Lint - SSG
|
|
||||||
needs: build-configs
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
- name: Download Config Artifacts
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: rsbuild-config-dist
|
|
||||||
path: packages/rsbuild-config/dist
|
|
||||||
- name: Lint SSG package
|
|
||||||
run: pnpm --filter @ermnvldmr/ssg lint
|
|
||||||
|
|
||||||
typecheck-ssg:
|
|
||||||
name: Typecheck - SSG
|
|
||||||
needs: build-configs
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
- name: Download Config Artifacts
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: rsbuild-config-dist
|
|
||||||
path: packages/rsbuild-config/dist
|
|
||||||
- name: Typecheck SSG package
|
|
||||||
run: pnpm --filter @ermnvldmr/ssg typecheck
|
|
||||||
|
|
||||||
build-ssg:
|
|
||||||
name: Build - SSG
|
|
||||||
needs: build-configs
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
- name: Download Config Artifacts
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: rsbuild-config-dist
|
|
||||||
path: packages/rsbuild-config/dist
|
|
||||||
- name: Build SSG package
|
|
||||||
run: pnpm --filter @ermnvldmr/ssg build
|
|
||||||
@@ -1,145 +0,0 @@
|
|||||||
name: packages/ssg - pr/required
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
branches: [next]
|
|
||||||
paths:
|
|
||||||
- 'packages/ssg/**'
|
|
||||||
- '.github/workflows/packages-ssg-pr-required.yml'
|
|
||||||
- 'pnpm-lock.yaml'
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ci-pr-ssg-${{ github.head_ref }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
actions: read
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
setup-stage:
|
|
||||||
name: Setup - Stage
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
outputs:
|
|
||||||
cache-hit: ${{ steps.cache-pnpm-store.outputs.cache-hit }}
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
|
|
||||||
- name: Setup Node.js with pnpm cache
|
|
||||||
uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
|
|
||||||
- name: Cache pnpm store
|
|
||||||
id: cache-pnpm-store
|
|
||||||
uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: ~/.pnpm-store
|
|
||||||
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
|
|
||||||
build-configs:
|
|
||||||
name: Build - Configs
|
|
||||||
needs: setup-stage
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
- name: Build Rsbuild config
|
|
||||||
run: pnpm --filter @ermnvldmr/rsbuild-config build
|
|
||||||
- name: Upload Config Artifacts
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: rsbuild-config-dist-${{ github.run_id }}
|
|
||||||
path: packages/rsbuild-config/dist
|
|
||||||
retention-days: 1
|
|
||||||
|
|
||||||
lint-ssg:
|
|
||||||
name: Lint - SSG
|
|
||||||
needs: build-configs
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
- name: Download Config Artifacts
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: rsbuild-config-dist-${{ github.run_id }}
|
|
||||||
path: packages/rsbuild-config/dist
|
|
||||||
- name: Lint SSG package
|
|
||||||
run: pnpm --filter @ermnvldmr/ssg lint
|
|
||||||
|
|
||||||
typecheck-ssg:
|
|
||||||
name: Typecheck - SSG
|
|
||||||
needs: build-configs
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
- name: Download Config Artifacts
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: rsbuild-config-dist-${{ github.run_id }}
|
|
||||||
path: packages/rsbuild-config/dist
|
|
||||||
- name: Typecheck SSG package
|
|
||||||
run: pnpm --filter @ermnvldmr/ssg typecheck
|
|
||||||
|
|
||||||
build-ssg:
|
|
||||||
name: Build - SSG
|
|
||||||
needs: build-configs
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
- name: Download Config Artifacts
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: rsbuild-config-dist-${{ github.run_id }}
|
|
||||||
path: packages/rsbuild-config/dist
|
|
||||||
- name: Build SSG package
|
|
||||||
run: pnpm --filter @ermnvldmr/ssg build
|
|
||||||
@@ -1,176 +0,0 @@
|
|||||||
name: packages/stl - next/required
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [next]
|
|
||||||
paths:
|
|
||||||
- 'packages/stl/**'
|
|
||||||
- '.github/workflows/packages-stl-next-required.yml'
|
|
||||||
- 'pnpm-lock.yaml'
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ci-stl-${{ github.ref_name }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
actions: read
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
setup-stage:
|
|
||||||
name: Setup - Stage
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
outputs:
|
|
||||||
cache-hit: ${{ steps.cache-pnpm-store.outputs.cache-hit }}
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
|
|
||||||
- name: Setup Node.js with pnpm cache
|
|
||||||
uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
|
|
||||||
- name: Cache pnpm store
|
|
||||||
id: cache-pnpm-store
|
|
||||||
uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: ~/.pnpm-store
|
|
||||||
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
|
|
||||||
build-configs:
|
|
||||||
name: Build - Configs
|
|
||||||
needs: setup-stage
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
- name: Build Rsbuild config
|
|
||||||
run: pnpm --filter @ermnvldmr/rsbuild-config build
|
|
||||||
- name: Upload Config Artifacts
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: rsbuild-config-dist
|
|
||||||
path: packages/rsbuild-config/dist
|
|
||||||
retention-days: 1
|
|
||||||
|
|
||||||
lint-stl:
|
|
||||||
name: Lint - STL
|
|
||||||
needs: build-configs
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
- name: Download Config Artifacts
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: rsbuild-config-dist
|
|
||||||
path: packages/rsbuild-config/dist
|
|
||||||
- name: Lint STL package
|
|
||||||
run: pnpm --filter @ermnvldmr/stl lint
|
|
||||||
|
|
||||||
typecheck-stl:
|
|
||||||
name: Typecheck - STL
|
|
||||||
needs: build-configs
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
- name: Download Config Artifacts
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: rsbuild-config-dist
|
|
||||||
path: packages/rsbuild-config/dist
|
|
||||||
- name: Typecheck STL package
|
|
||||||
run: pnpm --filter @ermnvldmr/stl typecheck
|
|
||||||
|
|
||||||
test-stl:
|
|
||||||
name: Test - STL
|
|
||||||
needs: build-configs
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
- name: Download Config Artifacts
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: rsbuild-config-dist
|
|
||||||
path: packages/rsbuild-config/dist
|
|
||||||
- name: Test STL package
|
|
||||||
run: pnpm --filter @ermnvldmr/stl test:coverage
|
|
||||||
- name: Upload coverage to Codecov
|
|
||||||
uses: codecov/codecov-action@v4
|
|
||||||
with:
|
|
||||||
files: ./packages/stl/coverage/lcov.info
|
|
||||||
flags: stl
|
|
||||||
env:
|
|
||||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
|
||||||
|
|
||||||
build-stl:
|
|
||||||
name: Build - STL
|
|
||||||
needs: build-configs
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
- name: Download Config Artifacts
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: rsbuild-config-dist
|
|
||||||
path: packages/rsbuild-config/dist
|
|
||||||
- name: Build STL package
|
|
||||||
run: pnpm --filter @ermnvldmr/stl build
|
|
||||||
@@ -1,176 +0,0 @@
|
|||||||
name: packages/stl - pr/required
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
branches: [next]
|
|
||||||
paths:
|
|
||||||
- 'packages/stl/**'
|
|
||||||
- '.github/workflows/packages-stl-pr-required.yml'
|
|
||||||
- 'pnpm-lock.yaml'
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ci-pr-stl-${{ github.head_ref }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
actions: read
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
setup-stage:
|
|
||||||
name: Setup - Stage
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
outputs:
|
|
||||||
cache-hit: ${{ steps.cache-pnpm-store.outputs.cache-hit }}
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
|
|
||||||
- name: Setup Node.js with pnpm cache
|
|
||||||
uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
|
|
||||||
- name: Cache pnpm store
|
|
||||||
id: cache-pnpm-store
|
|
||||||
uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: ~/.pnpm-store
|
|
||||||
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
|
|
||||||
build-configs:
|
|
||||||
name: Build - Configs
|
|
||||||
needs: setup-stage
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
- name: Build Rsbuild config
|
|
||||||
run: pnpm --filter @ermnvldmr/rsbuild-config build
|
|
||||||
- name: Upload Config Artifacts
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: rsbuild-config-dist-${{ github.run_id }}
|
|
||||||
path: packages/rsbuild-config/dist
|
|
||||||
retention-days: 1
|
|
||||||
|
|
||||||
lint-stl:
|
|
||||||
name: Lint - STL
|
|
||||||
needs: build-configs
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
- name: Download Config Artifacts
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: rsbuild-config-dist-${{ github.run_id }}
|
|
||||||
path: packages/rsbuild-config/dist
|
|
||||||
- name: Lint STL package
|
|
||||||
run: pnpm --filter @ermnvldmr/stl lint
|
|
||||||
|
|
||||||
typecheck-stl:
|
|
||||||
name: Typecheck - STL
|
|
||||||
needs: build-configs
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
- name: Download Config Artifacts
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: rsbuild-config-dist-${{ github.run_id }}
|
|
||||||
path: packages/rsbuild-config/dist
|
|
||||||
- name: Typecheck STL package
|
|
||||||
run: pnpm --filter @ermnvldmr/stl typecheck
|
|
||||||
|
|
||||||
test-stl:
|
|
||||||
name: Test - STL
|
|
||||||
needs: build-configs
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
- name: Download Config Artifacts
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: rsbuild-config-dist-${{ github.run_id }}
|
|
||||||
path: packages/rsbuild-config/dist
|
|
||||||
- name: Test STL package
|
|
||||||
run: pnpm --filter @ermnvldmr/stl test:coverage
|
|
||||||
- name: Upload coverage to Codecov
|
|
||||||
uses: codecov/codecov-action@v4
|
|
||||||
with:
|
|
||||||
files: ./packages/stl/coverage/lcov.info
|
|
||||||
flags: stl
|
|
||||||
env:
|
|
||||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
|
||||||
|
|
||||||
build-stl:
|
|
||||||
name: Build - STL
|
|
||||||
needs: build-configs
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
- name: Download Config Artifacts
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: rsbuild-config-dist-${{ github.run_id }}
|
|
||||||
path: packages/rsbuild-config/dist
|
|
||||||
- name: Build STL package
|
|
||||||
run: pnpm --filter @ermnvldmr/stl build
|
|
||||||
@@ -1,313 +0,0 @@
|
|||||||
name: packages/ui - next/required
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [next]
|
|
||||||
paths:
|
|
||||||
- 'packages/ui/**'
|
|
||||||
- 'packages/stl/**'
|
|
||||||
- 'packages/i18n/**'
|
|
||||||
- '.github/workflows/packages-ui-next-required.yml'
|
|
||||||
- 'pnpm-lock.yaml'
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ci-ui-${{ github.ref_name }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
actions: read
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
setup-stage:
|
|
||||||
name: Setup - Stage
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
outputs:
|
|
||||||
cache-hit: ${{ steps.cache-pnpm-store.outputs.cache-hit }}
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
|
|
||||||
- name: Setup Node.js with pnpm cache
|
|
||||||
uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
|
|
||||||
- name: Cache pnpm store
|
|
||||||
id: cache-pnpm-store
|
|
||||||
uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: ~/.pnpm-store
|
|
||||||
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
|
|
||||||
build-configs:
|
|
||||||
name: Build - Configs
|
|
||||||
needs: setup-stage
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
- name: Build Rsbuild config
|
|
||||||
run: pnpm --filter @ermnvldmr/rsbuild-config build
|
|
||||||
- name: Build Storybook config
|
|
||||||
run: pnpm --filter @ermnvldmr/storybook-config build
|
|
||||||
- name: Build i18n
|
|
||||||
run: pnpm --filter @ermnvldmr/i18n build
|
|
||||||
- name: Upload Rsbuild Config
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: rsbuild-config-dist
|
|
||||||
path: packages/rsbuild-config/dist
|
|
||||||
retention-days: 1
|
|
||||||
- name: Upload Storybook Config
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: storybook-config-dist
|
|
||||||
path: packages/storybook-config/dist
|
|
||||||
retention-days: 1
|
|
||||||
- name: Upload i18n dist
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: i18n-dist
|
|
||||||
path: packages/i18n/dist
|
|
||||||
retention-days: 1
|
|
||||||
|
|
||||||
lint-ui:
|
|
||||||
name: Lint - UI
|
|
||||||
needs: build-configs
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
- name: Download Rsbuild Config
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: rsbuild-config-dist
|
|
||||||
path: packages/rsbuild-config/dist
|
|
||||||
- name: Download Storybook Config
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: storybook-config-dist
|
|
||||||
path: packages/storybook-config/dist
|
|
||||||
- name: Download i18n dist
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: i18n-dist
|
|
||||||
path: packages/i18n/dist
|
|
||||||
- name: Lint UI package
|
|
||||||
run: pnpm --filter @ermnvldmr/ui lint
|
|
||||||
|
|
||||||
typecheck-ui:
|
|
||||||
name: Typecheck - UI
|
|
||||||
needs: build-configs
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
- name: Download Rsbuild Config
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: rsbuild-config-dist
|
|
||||||
path: packages/rsbuild-config/dist
|
|
||||||
- name: Download Storybook Config
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: storybook-config-dist
|
|
||||||
path: packages/storybook-config/dist
|
|
||||||
- name: Download i18n dist
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: i18n-dist
|
|
||||||
path: packages/i18n/dist
|
|
||||||
- name: Typecheck UI package
|
|
||||||
run: pnpm --filter @ermnvldmr/ui typecheck
|
|
||||||
|
|
||||||
test-ui:
|
|
||||||
name: Test - Unit
|
|
||||||
needs: build-configs
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
- name: Download Rsbuild Config
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: rsbuild-config-dist
|
|
||||||
path: packages/rsbuild-config/dist
|
|
||||||
- name: Download Storybook Config
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: storybook-config-dist
|
|
||||||
path: packages/storybook-config/dist
|
|
||||||
- name: Download i18n dist
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: i18n-dist
|
|
||||||
path: packages/i18n/dist
|
|
||||||
- name: Test UI package
|
|
||||||
run: pnpm --filter @ermnvldmr/ui test:coverage
|
|
||||||
- name: Upload coverage to Codecov
|
|
||||||
uses: codecov/codecov-action@v4
|
|
||||||
with:
|
|
||||||
files: ./packages/ui/coverage/lcov.info
|
|
||||||
flags: ui
|
|
||||||
env:
|
|
||||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
|
||||||
|
|
||||||
build-storybook:
|
|
||||||
name: Build - Storybook
|
|
||||||
needs: build-configs
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
- name: Download Rsbuild Config
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: rsbuild-config-dist
|
|
||||||
path: packages/rsbuild-config/dist
|
|
||||||
- name: Download Storybook Config
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: storybook-config-dist
|
|
||||||
path: packages/storybook-config/dist
|
|
||||||
- name: Download i18n dist
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: i18n-dist
|
|
||||||
path: packages/i18n/dist
|
|
||||||
- name: Build UI Storybook
|
|
||||||
run: pnpm --filter @ermnvldmr/ui build-storybook
|
|
||||||
|
|
||||||
test-storybook:
|
|
||||||
name: Test - Storybook
|
|
||||||
needs: build-storybook
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
- name: Download Rsbuild Config
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: rsbuild-config-dist
|
|
||||||
path: packages/rsbuild-config/dist
|
|
||||||
- name: Download Storybook Config
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: storybook-config-dist
|
|
||||||
path: packages/storybook-config/dist
|
|
||||||
- name: Download i18n dist
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: i18n-dist
|
|
||||||
path: packages/i18n/dist
|
|
||||||
- name: Install Playwright browsers
|
|
||||||
run: pnpm --filter @ermnvldmr/ui exec playwright install --with-deps chromium
|
|
||||||
- name: Build UI Storybook
|
|
||||||
run: pnpm --filter @ermnvldmr/ui build-storybook
|
|
||||||
- name: Test Storybook
|
|
||||||
run: pnpm --filter @ermnvldmr/ui test:storybook:ci
|
|
||||||
- name: Upload coverage to Codecov
|
|
||||||
uses: codecov/codecov-action@v4
|
|
||||||
with:
|
|
||||||
files: ./packages/ui/coverage/storybook/lcov.info
|
|
||||||
flags: ui-storybook
|
|
||||||
env:
|
|
||||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
|
||||||
|
|
||||||
build-ui:
|
|
||||||
name: Build - UI
|
|
||||||
needs: build-configs
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
- name: Download Rsbuild Config
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: rsbuild-config-dist
|
|
||||||
path: packages/rsbuild-config/dist
|
|
||||||
- name: Download Storybook Config
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: storybook-config-dist
|
|
||||||
path: packages/storybook-config/dist
|
|
||||||
- name: Download i18n dist
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: i18n-dist
|
|
||||||
path: packages/i18n/dist
|
|
||||||
- name: Build UI package
|
|
||||||
run: pnpm --filter @ermnvldmr/ui build
|
|
||||||
@@ -1,322 +0,0 @@
|
|||||||
name: packages/ui - pr/required
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
branches: [next]
|
|
||||||
paths:
|
|
||||||
- 'packages/ui/**'
|
|
||||||
- 'packages/stl/**'
|
|
||||||
- 'packages/i18n/**'
|
|
||||||
- '.github/workflows/packages-ui-pr-required.yml'
|
|
||||||
- 'pnpm-lock.yaml'
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ci-pr-ui-${{ github.head_ref }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
actions: read
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
setup-stage:
|
|
||||||
name: Setup - Stage
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
outputs:
|
|
||||||
cache-hit: ${{ steps.cache-pnpm-store.outputs.cache-hit }}
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
|
|
||||||
- name: Setup Node.js with pnpm cache
|
|
||||||
uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
|
|
||||||
- name: Cache pnpm store
|
|
||||||
id: cache-pnpm-store
|
|
||||||
uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: ~/.pnpm-store
|
|
||||||
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
|
|
||||||
build-configs:
|
|
||||||
name: Build - Configs
|
|
||||||
needs: setup-stage
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
- name: Build Rsbuild config
|
|
||||||
run: pnpm --filter @ermnvldmr/rsbuild-config build
|
|
||||||
- name: Build Storybook config
|
|
||||||
run: pnpm --filter @ermnvldmr/storybook-config build
|
|
||||||
- name: Build i18n
|
|
||||||
run: pnpm --filter @ermnvldmr/i18n build
|
|
||||||
- name: Upload Rsbuild Config
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: rsbuild-config-dist-${{ github.run_id }}
|
|
||||||
path: packages/rsbuild-config/dist
|
|
||||||
retention-days: 1
|
|
||||||
- name: Upload Storybook Config
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: storybook-config-dist-${{ github.run_id }}
|
|
||||||
path: packages/storybook-config/dist
|
|
||||||
retention-days: 1
|
|
||||||
- name: Upload i18n dist
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: i18n-dist-${{ github.run_id }}
|
|
||||||
path: packages/i18n/dist
|
|
||||||
retention-days: 1
|
|
||||||
|
|
||||||
lint-ui:
|
|
||||||
name: Lint - UI
|
|
||||||
needs: build-configs
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
- name: Download Rsbuild Config
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: rsbuild-config-dist-${{ github.run_id }}
|
|
||||||
path: packages/rsbuild-config/dist
|
|
||||||
- name: Download Storybook Config
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: storybook-config-dist-${{ github.run_id }}
|
|
||||||
path: packages/storybook-config/dist
|
|
||||||
- name: Download i18n dist
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: i18n-dist-${{ github.run_id }}
|
|
||||||
path: packages/i18n/dist
|
|
||||||
- name: Lint UI package
|
|
||||||
run: pnpm --filter @ermnvldmr/ui lint
|
|
||||||
|
|
||||||
typecheck-ui:
|
|
||||||
name: Typecheck - UI
|
|
||||||
needs: build-configs
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
- name: Download Rsbuild Config
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: rsbuild-config-dist-${{ github.run_id }}
|
|
||||||
path: packages/rsbuild-config/dist
|
|
||||||
- name: Download Storybook Config
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: storybook-config-dist-${{ github.run_id }}
|
|
||||||
path: packages/storybook-config/dist
|
|
||||||
- name: Download i18n dist
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: i18n-dist-${{ github.run_id }}
|
|
||||||
path: packages/i18n/dist
|
|
||||||
- name: Typecheck UI package
|
|
||||||
run: pnpm --filter @ermnvldmr/ui typecheck
|
|
||||||
|
|
||||||
test-ui:
|
|
||||||
name: Test - Unit
|
|
||||||
needs: build-configs
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
- name: Download Rsbuild Config
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: rsbuild-config-dist-${{ github.run_id }}
|
|
||||||
path: packages/rsbuild-config/dist
|
|
||||||
- name: Download Storybook Config
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: storybook-config-dist-${{ github.run_id }}
|
|
||||||
path: packages/storybook-config/dist
|
|
||||||
- name: Download i18n dist
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: i18n-dist-${{ github.run_id }}
|
|
||||||
path: packages/i18n/dist
|
|
||||||
- name: Test UI package
|
|
||||||
run: pnpm --filter @ermnvldmr/ui test:coverage
|
|
||||||
- name: Upload coverage to Codecov
|
|
||||||
uses: codecov/codecov-action@v4
|
|
||||||
with:
|
|
||||||
files: ./packages/ui/coverage/lcov.info
|
|
||||||
flags: ui
|
|
||||||
env:
|
|
||||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
|
||||||
|
|
||||||
build-storybook:
|
|
||||||
name: Build - Storybook
|
|
||||||
needs: build-configs
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
- name: Download Rsbuild Config
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: rsbuild-config-dist-${{ github.run_id }}
|
|
||||||
path: packages/rsbuild-config/dist
|
|
||||||
- name: Download Storybook Config
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: storybook-config-dist-${{ github.run_id }}
|
|
||||||
path: packages/storybook-config/dist
|
|
||||||
- name: Download i18n dist
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: i18n-dist-${{ github.run_id }}
|
|
||||||
path: packages/i18n/dist
|
|
||||||
- name: Build UI Storybook
|
|
||||||
run: pnpm --filter @ermnvldmr/ui build-storybook
|
|
||||||
- name: Upload Storybook build
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: ui-storybook-static-${{ github.run_id }}
|
|
||||||
path: packages/ui/storybook-static/
|
|
||||||
retention-days: 1
|
|
||||||
|
|
||||||
test-storybook:
|
|
||||||
name: Test - Storybook
|
|
||||||
needs: build-storybook
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
- name: Download Rsbuild Config
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: rsbuild-config-dist-${{ github.run_id }}
|
|
||||||
path: packages/rsbuild-config/dist
|
|
||||||
- name: Download Storybook Config
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: storybook-config-dist-${{ github.run_id }}
|
|
||||||
path: packages/storybook-config/dist
|
|
||||||
- name: Download i18n dist
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: i18n-dist-${{ github.run_id }}
|
|
||||||
path: packages/i18n/dist
|
|
||||||
- name: Install Playwright browsers
|
|
||||||
run: pnpm --filter @ermnvldmr/ui exec playwright install --with-deps chromium
|
|
||||||
- name: Download Storybook build
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: ui-storybook-static-${{ github.run_id }}
|
|
||||||
path: packages/ui/storybook-static/
|
|
||||||
- name: Test Storybook
|
|
||||||
run: pnpm --filter @ermnvldmr/ui test:storybook:ci
|
|
||||||
- name: Upload coverage to Codecov
|
|
||||||
uses: codecov/codecov-action@v4
|
|
||||||
with:
|
|
||||||
files: ./packages/ui/coverage/storybook/lcov.info
|
|
||||||
flags: ui-storybook
|
|
||||||
env:
|
|
||||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
|
||||||
|
|
||||||
build-ui:
|
|
||||||
name: Build - UI
|
|
||||||
needs: build-configs
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
- name: Download Rsbuild Config
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: rsbuild-config-dist-${{ github.run_id }}
|
|
||||||
path: packages/rsbuild-config/dist
|
|
||||||
- name: Download Storybook Config
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: storybook-config-dist-${{ github.run_id }}
|
|
||||||
path: packages/storybook-config/dist
|
|
||||||
- name: Download i18n dist
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: i18n-dist-${{ github.run_id }}
|
|
||||||
path: packages/i18n/dist
|
|
||||||
- name: Build UI package
|
|
||||||
run: pnpm --filter @ermnvldmr/ui build
|
|
||||||
@@ -1,166 +0,0 @@
|
|||||||
name: services/docs - next/required
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [next]
|
|
||||||
paths:
|
|
||||||
- 'services/docs/**'
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ci-docs-${{ github.ref_name }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
actions: read
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
setup-hugo:
|
|
||||||
name: Setup - Hugo
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
submodules: recursive
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Setup Hugo
|
|
||||||
uses: peaceiris/actions-hugo@v2
|
|
||||||
with:
|
|
||||||
hugo-version: 'latest'
|
|
||||||
extended: true
|
|
||||||
|
|
||||||
build-hugo:
|
|
||||||
name: Build - Hugo Site
|
|
||||||
needs: setup-hugo
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
submodules: recursive
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Setup Hugo
|
|
||||||
uses: peaceiris/actions-hugo@v2
|
|
||||||
with:
|
|
||||||
hugo-version: 'latest'
|
|
||||||
extended: true
|
|
||||||
|
|
||||||
- name: Build Hugo site
|
|
||||||
working-directory: services/docs
|
|
||||||
run: hugo --gc --minify
|
|
||||||
|
|
||||||
release-docker:
|
|
||||||
name: Release - Docker Image
|
|
||||||
needs: build-hugo
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
packages: write
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
submodules: recursive
|
|
||||||
|
|
||||||
- name: Log in to GitHub Container Registry
|
|
||||||
uses: docker/login-action@v3
|
|
||||||
with:
|
|
||||||
registry: ghcr.io
|
|
||||||
username: ${{ github.actor }}
|
|
||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
- name: Extract Docker metadata
|
|
||||||
id: meta
|
|
||||||
uses: docker/metadata-action@v5
|
|
||||||
with:
|
|
||||||
images: ghcr.io/${{ github.repository }}/docs
|
|
||||||
tags: |
|
|
||||||
type=raw,value=latest
|
|
||||||
type=sha,format=short
|
|
||||||
|
|
||||||
- name: Compute short SHA
|
|
||||||
id: vars
|
|
||||||
run: echo "short_sha=sha-$(echo ${{ github.sha }} | cut -c1-7)" >> $GITHUB_OUTPUT
|
|
||||||
|
|
||||||
- name: Build and push Docker image
|
|
||||||
uses: docker/build-push-action@v5
|
|
||||||
with:
|
|
||||||
context: .
|
|
||||||
file: ci/docker/docs/Dockerfile
|
|
||||||
push: true
|
|
||||||
tags: ${{ steps.meta.outputs.tags }}
|
|
||||||
labels: ${{ steps.meta.outputs.labels }}
|
|
||||||
build-args: |
|
|
||||||
COMMIT_SHA=${{ steps.vars.outputs.short_sha }}
|
|
||||||
VERSION=${{ steps.vars.outputs.short_sha }}
|
|
||||||
|
|
||||||
deploy:
|
|
||||||
name: Deploy - Kubernetes (GitOps)
|
|
||||||
needs: release-docker
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
if: github.event_name == 'push' && github.ref == 'refs/heads/next'
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
ref: next
|
|
||||||
token: ${{ secrets.GITOPS_TOKEN || secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
- name: Setup Kustomize
|
|
||||||
uses: imranismail/setup-kustomize@v2
|
|
||||||
with:
|
|
||||||
kustomize-version: "5.3.0"
|
|
||||||
|
|
||||||
- name: Deploy via GitOps
|
|
||||||
run: |
|
|
||||||
DOCS_TAG="sha-$(echo ${{ github.sha }} | cut -c1-7)"
|
|
||||||
bash ci/scripts/deploy-gitops.sh docs "${DOCS_TAG}"
|
|
||||||
|
|
||||||
verify-rollout:
|
|
||||||
name: Verify - Production Rollout
|
|
||||||
needs: deploy
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
if: github.event_name == 'push' && github.ref == 'refs/heads/next'
|
|
||||||
steps:
|
|
||||||
- name: Await production rollout
|
|
||||||
run: |
|
|
||||||
TARGET_COMMIT="sha-$(echo ${{ github.sha }} | cut -c1-7)"
|
|
||||||
ENDPOINT="https://docs.ermnvldmr.com/version.json"
|
|
||||||
|
|
||||||
echo "========================================================"
|
|
||||||
echo "Verifying production deployment on $ENDPOINT"
|
|
||||||
echo "Expected commit: $TARGET_COMMIT"
|
|
||||||
echo "========================================================"
|
|
||||||
|
|
||||||
MAX_ATTEMPTS=45
|
|
||||||
ATTEMPT=1
|
|
||||||
|
|
||||||
while [ $ATTEMPT -le $MAX_ATTEMPTS ]; do
|
|
||||||
echo "Attempt $ATTEMPT/$MAX_ATTEMPTS: Polling $ENDPOINT..."
|
|
||||||
|
|
||||||
RESPONSE=$(curl -sfL --max-time 10 -H "User-Agent: GitHub-Actions-Rollout-Verifier" "$ENDPOINT" 2>/dev/null || true)
|
|
||||||
|
|
||||||
if [ -n "$RESPONSE" ]; then
|
|
||||||
LIVE_COMMIT=$(echo "$RESPONSE" | jq -r '.commit // empty')
|
|
||||||
|
|
||||||
echo " Live commit: ${LIVE_COMMIT:-<none>}"
|
|
||||||
|
|
||||||
if [ "$LIVE_COMMIT" = "$TARGET_COMMIT" ]; then
|
|
||||||
echo "✅ Success! Production docs has successfully rolled out $TARGET_COMMIT."
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo " Endpoint did not return valid JSON or timed out."
|
|
||||||
fi
|
|
||||||
|
|
||||||
ATTEMPT=$((ATTEMPT + 1))
|
|
||||||
sleep 10
|
|
||||||
done
|
|
||||||
|
|
||||||
echo "❌ Deployment verification timed out after 7.5 minutes."
|
|
||||||
exit 1
|
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
name: services/docs - pr/required
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
branches: [next]
|
|
||||||
paths:
|
|
||||||
- 'services/docs/**'
|
|
||||||
- '.github/workflows/services-docs-pr-required.yml'
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ci-pr-docs-${{ github.head_ref }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
actions: read
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
setup-hugo:
|
|
||||||
name: Setup - Hugo
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
submodules: recursive
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Setup Hugo
|
|
||||||
uses: peaceiris/actions-hugo@v2
|
|
||||||
with:
|
|
||||||
hugo-version: 'latest'
|
|
||||||
extended: true
|
|
||||||
|
|
||||||
build-hugo:
|
|
||||||
name: Build - Hugo Site
|
|
||||||
needs: setup-hugo
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
submodules: recursive
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Setup Hugo
|
|
||||||
uses: peaceiris/actions-hugo@v2
|
|
||||||
with:
|
|
||||||
hugo-version: 'latest'
|
|
||||||
extended: true
|
|
||||||
|
|
||||||
- name: Build Hugo site
|
|
||||||
working-directory: services/docs
|
|
||||||
run: hugo --gc --minify
|
|
||||||
@@ -1,204 +0,0 @@
|
|||||||
name: services/static - next/required
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [next]
|
|
||||||
paths:
|
|
||||||
- 'services/static/**'
|
|
||||||
- 'packages/ui/**'
|
|
||||||
- 'packages/stl/**'
|
|
||||||
- 'packages/i18n/**'
|
|
||||||
- '.github/workflows/services-static-next-required.yml'
|
|
||||||
- 'pnpm-lock.yaml'
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ci-static-${{ github.ref_name }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
actions: read
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
setup-stage:
|
|
||||||
name: Setup - Stage
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
outputs:
|
|
||||||
cache-hit: ${{ steps.cache-pnpm-store.outputs.cache-hit }}
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
|
|
||||||
- name: Setup Node.js with pnpm cache
|
|
||||||
uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
|
|
||||||
- name: Cache pnpm store
|
|
||||||
id: cache-pnpm-store
|
|
||||||
uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: ~/.pnpm-store
|
|
||||||
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
|
|
||||||
build-configs:
|
|
||||||
name: Build - Configs
|
|
||||||
needs: setup-stage
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
- name: Build Rsbuild config
|
|
||||||
run: pnpm --filter @ermnvldmr/rsbuild-config build
|
|
||||||
- name: Build i18n
|
|
||||||
run: pnpm --filter @ermnvldmr/i18n build
|
|
||||||
- name: Upload Config Artifacts
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: rsbuild-config-dist
|
|
||||||
path: packages/rsbuild-config/dist
|
|
||||||
retention-days: 1
|
|
||||||
- name: Upload i18n dist
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: i18n-dist
|
|
||||||
path: packages/i18n/dist
|
|
||||||
retention-days: 1
|
|
||||||
|
|
||||||
lint-static:
|
|
||||||
name: Lint - Static
|
|
||||||
needs: build-configs
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
- name: Download Config Artifacts
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: rsbuild-config-dist
|
|
||||||
path: packages/rsbuild-config/dist
|
|
||||||
- name: Download i18n dist
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: i18n-dist
|
|
||||||
path: packages/i18n/dist
|
|
||||||
- name: Lint static service
|
|
||||||
run: pnpm --filter @ermnvldmr/static lint
|
|
||||||
|
|
||||||
typecheck-static:
|
|
||||||
name: Typecheck - Static
|
|
||||||
needs: build-configs
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
- name: Download Config Artifacts
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: rsbuild-config-dist
|
|
||||||
path: packages/rsbuild-config/dist
|
|
||||||
- name: Download i18n dist
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: i18n-dist
|
|
||||||
path: packages/i18n/dist
|
|
||||||
- name: Typecheck static service
|
|
||||||
run: pnpm --filter @ermnvldmr/static typecheck
|
|
||||||
|
|
||||||
build-static:
|
|
||||||
name: Build - Static Site
|
|
||||||
needs: build-configs
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
- name: Download Config Artifacts
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: rsbuild-config-dist
|
|
||||||
path: packages/rsbuild-config/dist
|
|
||||||
- name: Download i18n dist
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: i18n-dist
|
|
||||||
path: packages/i18n/dist
|
|
||||||
- name: Build static service
|
|
||||||
run: pnpm --filter @ermnvldmr/static build
|
|
||||||
- name: Upload build artifacts
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: static-dist
|
|
||||||
path: services/static/dist/
|
|
||||||
retention-days: 1
|
|
||||||
|
|
||||||
deploy-s3:
|
|
||||||
name: Deploy - S3
|
|
||||||
needs: [lint-static, typecheck-static, build-static]
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
if: github.event_name == 'push' && github.ref == 'refs/heads/next'
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Download build artifacts
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: static-dist
|
|
||||||
path: services/static/dist/
|
|
||||||
|
|
||||||
- name: Deploy to S3
|
|
||||||
env:
|
|
||||||
AWS_ACCESS_KEY_ID: ${{ secrets.STATIC_AWS_ACCESS_KEY_ID }}
|
|
||||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.STATIC_AWS_SECRET_ACCESS_KEY }}
|
|
||||||
AWS_DEFAULT_REGION: ${{ secrets.STATIC_AWS_REGION }}
|
|
||||||
S3_BUCKET: ${{ secrets.STATIC_S3_BUCKET }}
|
|
||||||
AWS_REGION: ${{ secrets.STATIC_AWS_REGION }}
|
|
||||||
S3_ENDPOINT_URL: ${{ secrets.STATIC_S3_ENDPOINT_URL }}
|
|
||||||
run: |
|
|
||||||
chmod +x ci/scripts/deploy-static.sh
|
|
||||||
./ci/scripts/deploy-static.sh
|
|
||||||
@@ -1,177 +0,0 @@
|
|||||||
name: services/static - pr/required
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
branches: [next]
|
|
||||||
paths:
|
|
||||||
- 'services/static/**'
|
|
||||||
- 'packages/ui/**'
|
|
||||||
- 'packages/stl/**'
|
|
||||||
- 'packages/i18n/**'
|
|
||||||
- '.github/workflows/services-static-pr-required.yml'
|
|
||||||
- 'pnpm-lock.yaml'
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ci-pr-static-${{ github.head_ref }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
actions: read
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
setup-stage:
|
|
||||||
name: Setup - Stage
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
outputs:
|
|
||||||
cache-hit: ${{ steps.cache-pnpm-store.outputs.cache-hit }}
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
|
|
||||||
- name: Setup Node.js with pnpm cache
|
|
||||||
uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
|
|
||||||
- name: Cache pnpm store
|
|
||||||
id: cache-pnpm-store
|
|
||||||
uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: ~/.pnpm-store
|
|
||||||
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
|
|
||||||
build-configs:
|
|
||||||
name: Build - Configs
|
|
||||||
needs: setup-stage
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
- name: Build Rsbuild config
|
|
||||||
run: pnpm --filter @ermnvldmr/rsbuild-config build
|
|
||||||
- name: Build i18n
|
|
||||||
run: pnpm --filter @ermnvldmr/i18n build
|
|
||||||
- name: Upload Config Artifacts
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: rsbuild-config-dist-${{ github.run_id }}
|
|
||||||
path: packages/rsbuild-config/dist
|
|
||||||
retention-days: 1
|
|
||||||
- name: Upload i18n dist
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: i18n-dist-${{ github.run_id }}
|
|
||||||
path: packages/i18n/dist
|
|
||||||
retention-days: 1
|
|
||||||
|
|
||||||
lint-static:
|
|
||||||
name: Lint - Static
|
|
||||||
needs: build-configs
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
- name: Download Config Artifacts
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: rsbuild-config-dist-${{ github.run_id }}
|
|
||||||
path: packages/rsbuild-config/dist
|
|
||||||
- name: Download i18n dist
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: i18n-dist-${{ github.run_id }}
|
|
||||||
path: packages/i18n/dist
|
|
||||||
- name: Lint static service
|
|
||||||
run: pnpm --filter @ermnvldmr/static lint
|
|
||||||
|
|
||||||
typecheck-static:
|
|
||||||
name: Typecheck - Static
|
|
||||||
needs: build-configs
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
- name: Download Config Artifacts
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: rsbuild-config-dist-${{ github.run_id }}
|
|
||||||
path: packages/rsbuild-config/dist
|
|
||||||
- name: Download i18n dist
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: i18n-dist-${{ github.run_id }}
|
|
||||||
path: packages/i18n/dist
|
|
||||||
- name: Typecheck static service
|
|
||||||
run: pnpm --filter @ermnvldmr/static typecheck
|
|
||||||
|
|
||||||
build-static:
|
|
||||||
name: Build - Static Site
|
|
||||||
needs: build-configs
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
- name: Download Config Artifacts
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: rsbuild-config-dist-${{ github.run_id }}
|
|
||||||
path: packages/rsbuild-config/dist
|
|
||||||
- name: Download i18n dist
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: i18n-dist-${{ github.run_id }}
|
|
||||||
path: packages/i18n/dist
|
|
||||||
- name: Build static service
|
|
||||||
run: pnpm --filter @ermnvldmr/static build
|
|
||||||
- name: Upload build artifacts
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: static-dist-${{ github.run_id }}
|
|
||||||
path: services/static/dist/
|
|
||||||
retention-days: 1
|
|
||||||
@@ -1,486 +0,0 @@
|
|||||||
name: services/www - next/required
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [next]
|
|
||||||
paths:
|
|
||||||
- 'services/www/**'
|
|
||||||
- 'packages/ui/**'
|
|
||||||
- 'packages/stl/**'
|
|
||||||
- 'packages/i18n/**'
|
|
||||||
- '.github/workflows/services-www-next-required.yml'
|
|
||||||
- 'pnpm-lock.yaml'
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ci-www-${{ github.ref_name }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
actions: read
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
setup-stage:
|
|
||||||
name: Setup - Stage
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
outputs:
|
|
||||||
cache-hit: ${{ steps.cache-pnpm-store.outputs.cache-hit }}
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
|
|
||||||
- name: Setup Node.js with pnpm cache
|
|
||||||
uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
|
|
||||||
- name: Cache pnpm store
|
|
||||||
id: cache-pnpm-store
|
|
||||||
uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: ~/.pnpm-store
|
|
||||||
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
|
|
||||||
build-configs:
|
|
||||||
name: Build - Configs
|
|
||||||
needs: setup-stage
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
- name: Build Rsbuild config
|
|
||||||
run: pnpm --filter @ermnvldmr/rsbuild-config build
|
|
||||||
- name: Build Storybook config
|
|
||||||
run: pnpm --filter @ermnvldmr/storybook-config build
|
|
||||||
- name: Upload Rsbuild Config
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: rsbuild-config-dist
|
|
||||||
path: packages/rsbuild-config/dist
|
|
||||||
retention-days: 1
|
|
||||||
- name: Upload Storybook Config
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: storybook-config-dist
|
|
||||||
path: packages/storybook-config/dist
|
|
||||||
retention-days: 1
|
|
||||||
- name: Build i18n package
|
|
||||||
run: pnpm --filter @ermnvldmr/i18n build
|
|
||||||
- name: Upload i18n dist
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: i18n-dist
|
|
||||||
path: packages/i18n/dist
|
|
||||||
retention-days: 1
|
|
||||||
|
|
||||||
lint-www:
|
|
||||||
name: Lint - WWW
|
|
||||||
needs: build-configs
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
- name: Download Rsbuild Config
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: rsbuild-config-dist
|
|
||||||
path: packages/rsbuild-config/dist
|
|
||||||
- name: Download i18n dist
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: i18n-dist
|
|
||||||
path: packages/i18n/dist
|
|
||||||
- name: Download Storybook Config
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: storybook-config-dist
|
|
||||||
path: packages/storybook-config/dist
|
|
||||||
- name: Lint WWW service
|
|
||||||
run: pnpm --filter @ermnvldmr/www lint
|
|
||||||
|
|
||||||
typecheck-www:
|
|
||||||
name: Typecheck - WWW
|
|
||||||
needs: build-configs
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
- name: Download Rsbuild Config
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: rsbuild-config-dist
|
|
||||||
path: packages/rsbuild-config/dist
|
|
||||||
- name: Download i18n dist
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: i18n-dist
|
|
||||||
path: packages/i18n/dist
|
|
||||||
- name: Download Storybook Config
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: storybook-config-dist
|
|
||||||
path: packages/storybook-config/dist
|
|
||||||
- name: Typecheck WWW service
|
|
||||||
run: pnpm --filter @ermnvldmr/www typecheck
|
|
||||||
|
|
||||||
build-storybook:
|
|
||||||
name: Build - Storybook
|
|
||||||
needs: build-configs
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
- name: Download Rsbuild Config
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: rsbuild-config-dist
|
|
||||||
path: packages/rsbuild-config/dist
|
|
||||||
- name: Download i18n dist
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: i18n-dist
|
|
||||||
path: packages/i18n/dist
|
|
||||||
- name: Download Storybook Config
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: storybook-config-dist
|
|
||||||
path: packages/storybook-config/dist
|
|
||||||
- name: Build WWW Storybook
|
|
||||||
run: pnpm --filter @ermnvldmr/www build-storybook
|
|
||||||
- name: Upload Storybook build
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: storybook-static
|
|
||||||
path: services/www/storybook-static/
|
|
||||||
retention-days: 1
|
|
||||||
|
|
||||||
test-www:
|
|
||||||
name: Test - Unit
|
|
||||||
needs: build-configs
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
- name: Download Rsbuild Config
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: rsbuild-config-dist
|
|
||||||
path: packages/rsbuild-config/dist
|
|
||||||
- name: Download i18n dist
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: i18n-dist
|
|
||||||
path: packages/i18n/dist
|
|
||||||
- name: Download Storybook Config
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: storybook-config-dist
|
|
||||||
path: packages/storybook-config/dist
|
|
||||||
- name: Test WWW service
|
|
||||||
run: pnpm --filter @ermnvldmr/www test:coverage
|
|
||||||
- name: Upload Unit coverage to Codecov
|
|
||||||
uses: codecov/codecov-action@v4
|
|
||||||
with:
|
|
||||||
files: ./services/www/coverage/lcov.info
|
|
||||||
flags: www
|
|
||||||
env:
|
|
||||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
|
||||||
|
|
||||||
test-storybook:
|
|
||||||
name: Test - Storybook
|
|
||||||
needs: build-storybook
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
- name: Download Rsbuild Config
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: rsbuild-config-dist
|
|
||||||
path: packages/rsbuild-config/dist
|
|
||||||
- name: Download i18n dist
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: i18n-dist
|
|
||||||
path: packages/i18n/dist
|
|
||||||
- name: Download Storybook Config
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: storybook-config-dist
|
|
||||||
path: packages/storybook-config/dist
|
|
||||||
- name: Install Playwright browsers
|
|
||||||
run: pnpm --filter @ermnvldmr/www exec playwright install --with-deps chromium
|
|
||||||
- name: Download Storybook build
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: storybook-static
|
|
||||||
path: services/www/storybook-static/
|
|
||||||
- name: Serve Storybook and run tests with coverage
|
|
||||||
run: pnpm --filter @ermnvldmr/www test:storybook:ci
|
|
||||||
- name: Upload Storybook coverage to Codecov
|
|
||||||
uses: codecov/codecov-action@v4
|
|
||||||
with:
|
|
||||||
files: ./services/www/coverage/storybook/lcov.info
|
|
||||||
flags: www-storybook
|
|
||||||
env:
|
|
||||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
|
||||||
|
|
||||||
build-www:
|
|
||||||
name: Build - WWW Service
|
|
||||||
needs: build-configs
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
- name: Download Rsbuild Config
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: rsbuild-config-dist
|
|
||||||
path: packages/rsbuild-config/dist
|
|
||||||
- name: Download i18n dist
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: i18n-dist
|
|
||||||
path: packages/i18n/dist
|
|
||||||
- name: Download Storybook Config
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: storybook-config-dist
|
|
||||||
path: packages/storybook-config/dist
|
|
||||||
- name: Build WWW service (all locales)
|
|
||||||
run: pnpm --filter @ermnvldmr/www build:all
|
|
||||||
env:
|
|
||||||
RSDOCTOR: 'true'
|
|
||||||
- name: Upload Rsdoctor report
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: rsdoctor-report
|
|
||||||
path: services/www/rsdoctor/
|
|
||||||
retention-days: 30
|
|
||||||
|
|
||||||
build-docker:
|
|
||||||
name: Build - Docker Image
|
|
||||||
needs: [lint-www, typecheck-www, test-www, test-storybook, build-www]
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
packages: write
|
|
||||||
outputs:
|
|
||||||
short_sha: ${{ steps.vars.outputs.short_sha }}
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Calculate Short SHA
|
|
||||||
id: vars
|
|
||||||
run: |
|
|
||||||
SHORT_SHA="sha-$(echo ${{ github.sha }} | cut -c1-7)"
|
|
||||||
echo "short_sha=$SHORT_SHA" >> $GITHUB_OUTPUT
|
|
||||||
|
|
||||||
- name: Log in to GitHub Container Registry
|
|
||||||
uses: docker/login-action@v3
|
|
||||||
with:
|
|
||||||
registry: ghcr.io
|
|
||||||
username: ${{ github.actor }}
|
|
||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
|
||||||
uses: docker/setup-buildx-action@v3
|
|
||||||
|
|
||||||
- name: Build and push Docker image
|
|
||||||
uses: docker/build-push-action@v5
|
|
||||||
with:
|
|
||||||
context: .
|
|
||||||
file: ci/docker/www/Dockerfile
|
|
||||||
push: true
|
|
||||||
tags: ghcr.io/${{ github.repository }}/www:${{ steps.vars.outputs.short_sha }}
|
|
||||||
build-args: |
|
|
||||||
COMMIT_SHA=${{ steps.vars.outputs.short_sha }}
|
|
||||||
VERSION=${{ steps.vars.outputs.short_sha }}
|
|
||||||
|
|
||||||
release-tag-docker:
|
|
||||||
name: Release - Tag & Docker
|
|
||||||
needs: build-docker
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
environment: services-www-releases-publish
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
packages: write
|
|
||||||
outputs:
|
|
||||||
version: ${{ steps.calver.outputs.version }}
|
|
||||||
short_sha: ${{ needs.build-docker.outputs.short_sha }}
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Calculate CalVer Version
|
|
||||||
id: calver
|
|
||||||
run: |
|
|
||||||
VERSION=$(bash ci/scripts/calver-release.sh)
|
|
||||||
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
|
||||||
|
|
||||||
- name: Create and Push Tag
|
|
||||||
run: |
|
|
||||||
TAG_NAME="${{ steps.calver.outputs.version }}"
|
|
||||||
git tag "$TAG_NAME"
|
|
||||||
git push origin "$TAG_NAME"
|
|
||||||
|
|
||||||
- name: Log in to GitHub Container Registry
|
|
||||||
uses: docker/login-action@v3
|
|
||||||
with:
|
|
||||||
registry: ghcr.io
|
|
||||||
username: ${{ github.actor }}
|
|
||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
|
||||||
uses: docker/setup-buildx-action@v3
|
|
||||||
|
|
||||||
- name: Tag and Push Release Docker Image
|
|
||||||
run: |
|
|
||||||
docker buildx imagetools create \
|
|
||||||
ghcr.io/${{ github.repository }}/www:${{ needs.build-docker.outputs.short_sha }} \
|
|
||||||
--tag ghcr.io/${{ github.repository }}/www:${{ steps.calver.outputs.version }}
|
|
||||||
|
|
||||||
deploy:
|
|
||||||
name: Deploy - Kubernetes (GitOps)
|
|
||||||
needs: release-tag-docker
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
environment:
|
|
||||||
name: services-www-releases-deploy
|
|
||||||
url: https://ermnvldmr.com
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
ref: next
|
|
||||||
token: ${{ secrets.GITOPS_TOKEN || secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
- name: Setup Kustomize
|
|
||||||
uses: imranismail/setup-kustomize@v2
|
|
||||||
with:
|
|
||||||
kustomize-version: "5.3.0"
|
|
||||||
|
|
||||||
- name: Deploy via GitOps
|
|
||||||
run: |
|
|
||||||
WWW_TAG="${{ needs.release-tag-docker.outputs.short_sha }}"
|
|
||||||
bash ci/scripts/deploy-gitops.sh www "${WWW_TAG}"
|
|
||||||
|
|
||||||
verify-rollout:
|
|
||||||
name: Verify - Production Rollout
|
|
||||||
needs: [release-tag-docker, deploy]
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Await production rollout
|
|
||||||
run: |
|
|
||||||
TARGET_COMMIT="${{ needs.release-tag-docker.outputs.short_sha }}"
|
|
||||||
ENDPOINT="https://www.ermnvldmr.com/version.json"
|
|
||||||
|
|
||||||
echo "========================================================"
|
|
||||||
echo "Verifying production deployment on $ENDPOINT"
|
|
||||||
echo "Expected commit: $TARGET_COMMIT"
|
|
||||||
echo "========================================================"
|
|
||||||
|
|
||||||
MAX_ATTEMPTS=45
|
|
||||||
ATTEMPT=1
|
|
||||||
|
|
||||||
while [ $ATTEMPT -le $MAX_ATTEMPTS ]; do
|
|
||||||
echo "Attempt $ATTEMPT/$MAX_ATTEMPTS: Polling $ENDPOINT..."
|
|
||||||
|
|
||||||
RESPONSE=$(curl -sfL --max-time 10 -H "User-Agent: GitHub-Actions-Rollout-Verifier" "$ENDPOINT" 2>/dev/null || true)
|
|
||||||
|
|
||||||
if [ -n "$RESPONSE" ]; then
|
|
||||||
LIVE_COMMIT=$(echo "$RESPONSE" | jq -r '.commit // empty')
|
|
||||||
|
|
||||||
echo " Live commit: ${LIVE_COMMIT:-<none>}"
|
|
||||||
|
|
||||||
if [ "$LIVE_COMMIT" = "$TARGET_COMMIT" ]; then
|
|
||||||
echo "✅ Success! Production has successfully rolled out $TARGET_COMMIT."
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo " Endpoint did not return valid JSON or timed out."
|
|
||||||
fi
|
|
||||||
|
|
||||||
ATTEMPT=$((ATTEMPT + 1))
|
|
||||||
sleep 10
|
|
||||||
done
|
|
||||||
|
|
||||||
echo "❌ Deployment verification timed out after 7.5 minutes."
|
|
||||||
exit 1
|
|
||||||
@@ -1,331 +0,0 @@
|
|||||||
name: services/www - pr/required
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
branches: [next]
|
|
||||||
paths:
|
|
||||||
- 'services/www/**'
|
|
||||||
- 'packages/ui/**'
|
|
||||||
- 'packages/stl/**'
|
|
||||||
- 'packages/i18n/**'
|
|
||||||
- '.github/workflows/services-www-pr-required.yml'
|
|
||||||
- 'pnpm-lock.yaml'
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ci-pr-www-${{ github.head_ref }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
actions: read
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
setup-stage:
|
|
||||||
name: Setup - Stage
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
outputs:
|
|
||||||
cache-hit: ${{ steps.cache-pnpm-store.outputs.cache-hit }}
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
|
|
||||||
- name: Setup Node.js with pnpm cache
|
|
||||||
uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
|
|
||||||
- name: Cache pnpm store
|
|
||||||
id: cache-pnpm-store
|
|
||||||
uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: ~/.pnpm-store
|
|
||||||
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
|
|
||||||
build-configs:
|
|
||||||
name: Build - Configs
|
|
||||||
needs: setup-stage
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
- name: Build Rsbuild config
|
|
||||||
run: pnpm --filter @ermnvldmr/rsbuild-config build
|
|
||||||
- name: Build Storybook config
|
|
||||||
run: pnpm --filter @ermnvldmr/storybook-config build
|
|
||||||
- name: Upload Rsbuild Config
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: rsbuild-config-dist-${{ github.run_id }}
|
|
||||||
path: packages/rsbuild-config/dist
|
|
||||||
retention-days: 1
|
|
||||||
- name: Upload Storybook Config
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: storybook-config-dist-${{ github.run_id }}
|
|
||||||
path: packages/storybook-config/dist
|
|
||||||
retention-days: 1
|
|
||||||
- name: Build i18n package
|
|
||||||
run: pnpm --filter @ermnvldmr/i18n build
|
|
||||||
- name: Upload i18n dist
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: i18n-dist-${{ github.run_id }}
|
|
||||||
path: packages/i18n/dist
|
|
||||||
retention-days: 1
|
|
||||||
|
|
||||||
lint-www:
|
|
||||||
name: Lint - WWW
|
|
||||||
needs: build-configs
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
- name: Download Rsbuild Config
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: rsbuild-config-dist-${{ github.run_id }}
|
|
||||||
path: packages/rsbuild-config/dist
|
|
||||||
- name: Download i18n dist
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: i18n-dist-${{ github.run_id }}
|
|
||||||
path: packages/i18n/dist
|
|
||||||
- name: Download Storybook Config
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: storybook-config-dist-${{ github.run_id }}
|
|
||||||
path: packages/storybook-config/dist
|
|
||||||
- name: Lint WWW service
|
|
||||||
run: pnpm --filter @ermnvldmr/www lint
|
|
||||||
|
|
||||||
typecheck-www:
|
|
||||||
name: Typecheck - WWW
|
|
||||||
needs: build-configs
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
- name: Download Rsbuild Config
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: rsbuild-config-dist-${{ github.run_id }}
|
|
||||||
path: packages/rsbuild-config/dist
|
|
||||||
- name: Download i18n dist
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: i18n-dist-${{ github.run_id }}
|
|
||||||
path: packages/i18n/dist
|
|
||||||
- name: Download Storybook Config
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: storybook-config-dist-${{ github.run_id }}
|
|
||||||
path: packages/storybook-config/dist
|
|
||||||
- name: Typecheck WWW service
|
|
||||||
run: pnpm --filter @ermnvldmr/www typecheck
|
|
||||||
|
|
||||||
build-storybook:
|
|
||||||
name: Build - Storybook
|
|
||||||
needs: build-configs
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
- name: Download Rsbuild Config
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: rsbuild-config-dist-${{ github.run_id }}
|
|
||||||
path: packages/rsbuild-config/dist
|
|
||||||
- name: Download i18n dist
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: i18n-dist-${{ github.run_id }}
|
|
||||||
path: packages/i18n/dist
|
|
||||||
- name: Download Storybook Config
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: storybook-config-dist-${{ github.run_id }}
|
|
||||||
path: packages/storybook-config/dist
|
|
||||||
- name: Build WWW Storybook
|
|
||||||
run: pnpm --filter @ermnvldmr/www build-storybook
|
|
||||||
- name: Upload Storybook build
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: www-storybook-static-${{ github.run_id }}
|
|
||||||
path: services/www/storybook-static/
|
|
||||||
retention-days: 1
|
|
||||||
|
|
||||||
test-www:
|
|
||||||
name: Test - Unit
|
|
||||||
needs: build-configs
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
- name: Download Rsbuild Config
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: rsbuild-config-dist-${{ github.run_id }}
|
|
||||||
path: packages/rsbuild-config/dist
|
|
||||||
- name: Download i18n dist
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: i18n-dist-${{ github.run_id }}
|
|
||||||
path: packages/i18n/dist
|
|
||||||
- name: Download Storybook Config
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: storybook-config-dist-${{ github.run_id }}
|
|
||||||
path: packages/storybook-config/dist
|
|
||||||
- name: Test WWW service
|
|
||||||
run: pnpm --filter @ermnvldmr/www test:coverage
|
|
||||||
- name: Upload Unit coverage to Codecov
|
|
||||||
uses: codecov/codecov-action@v4
|
|
||||||
with:
|
|
||||||
files: ./services/www/coverage/lcov.info
|
|
||||||
flags: www
|
|
||||||
env:
|
|
||||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
|
||||||
|
|
||||||
test-storybook:
|
|
||||||
name: Test - Storybook
|
|
||||||
needs: build-storybook
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
- name: Download Rsbuild Config
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: rsbuild-config-dist-${{ github.run_id }}
|
|
||||||
path: packages/rsbuild-config/dist
|
|
||||||
- name: Download i18n dist
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: i18n-dist-${{ github.run_id }}
|
|
||||||
path: packages/i18n/dist
|
|
||||||
- name: Download Storybook Config
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: storybook-config-dist-${{ github.run_id }}
|
|
||||||
path: packages/storybook-config/dist
|
|
||||||
- name: Install Playwright browsers
|
|
||||||
run: pnpm --filter @ermnvldmr/www exec playwright install --with-deps chromium
|
|
||||||
- name: Download Storybook build
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: www-storybook-static-${{ github.run_id }}
|
|
||||||
path: services/www/storybook-static/
|
|
||||||
- name: Serve Storybook and run tests with coverage
|
|
||||||
run: pnpm --filter @ermnvldmr/www test:storybook:ci
|
|
||||||
- name: Upload Storybook coverage to Codecov
|
|
||||||
uses: codecov/codecov-action@v4
|
|
||||||
with:
|
|
||||||
files: ./services/www/coverage/storybook/lcov.info
|
|
||||||
flags: www-storybook
|
|
||||||
env:
|
|
||||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
|
||||||
|
|
||||||
build-www:
|
|
||||||
name: Build - WWW Service
|
|
||||||
needs: build-configs
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 9.12.3
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
- name: Download Rsbuild Config
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: rsbuild-config-dist-${{ github.run_id }}
|
|
||||||
path: packages/rsbuild-config/dist
|
|
||||||
- name: Download i18n dist
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: i18n-dist-${{ github.run_id }}
|
|
||||||
path: packages/i18n/dist
|
|
||||||
- name: Download Storybook Config
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: storybook-config-dist-${{ github.run_id }}
|
|
||||||
path: packages/storybook-config/dist
|
|
||||||
- name: Build WWW service (all locales)
|
|
||||||
run: pnpm --filter @ermnvldmr/www build:all
|
|
||||||
env:
|
|
||||||
RSDOCTOR: 'true'
|
|
||||||
- name: Upload Rsdoctor report
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: rsdoctor-report-${{ github.run_id }}
|
|
||||||
path: services/www/rsdoctor/
|
|
||||||
retention-days: 7
|
|
||||||
@@ -25,6 +25,9 @@ playwright-report/
|
|||||||
.env
|
.env
|
||||||
.env.keys
|
.env.keys
|
||||||
|
|
||||||
|
# local development certificates
|
||||||
|
.certs/
|
||||||
|
|
||||||
# macOS-specific files
|
# macOS-specific files
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|
||||||
@@ -43,3 +46,9 @@ docs/superpowers/
|
|||||||
.sops/keys.txt
|
.sops/keys.txt
|
||||||
ci/k8s/**/secret.yaml
|
ci/k8s/**/secret.yaml
|
||||||
ci/cloud-init/user-data.yaml
|
ci/cloud-init/user-data.yaml
|
||||||
|
|
||||||
|
# Packer & QEMU Build Artifacts
|
||||||
|
output-qemu/
|
||||||
|
*.qcow2
|
||||||
|
*.iso
|
||||||
|
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
creation_rules:
|
creation_rules:
|
||||||
- path_regex: ci/k8s/.*secret.*\.yaml$
|
- path_regex: ci/k8s/.*secret.*\.yaml$
|
||||||
encrypted_regex: '^(data|stringData)$'
|
encrypted_regex: '^(data|stringData)$'
|
||||||
age: "age1jpa7hqyzzdfq7lvnw3l8qy6648mtjgpcqnljl5jz92dcqjrnsqfsn7m0fl"
|
age: "age15zq3cje3ttmx2fhqp9cpeght6feq2w8e5m38799stjetj8urcccs36r4rc,age1jpa7hqyzzdfq7lvnw3l8qy6648mtjgpcqnljl5jz92dcqjrnsqfsn7m0fl"
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
# [ermnvldmr.com](https://ermnvldmr.com)
|
# [ermnvldmr.com](https://ermnvldmr.com)
|
||||||
|
|
||||||
[](https://app.codecov.io/github/deytenit/ermnvldmr.com)
|
|
||||||
|
|
||||||
The monorepo powering the front pages of my own
|
The monorepo powering the front pages of my own
|
||||||
|
|
||||||
@@ -58,7 +57,7 @@ Want to contribute or understand the codebase.
|
|||||||
- UI Library: `pnpm ui:dev`
|
- UI Library: `pnpm ui:dev`
|
||||||
- **Development Guide**: [AGENTS.md](./AGENTS.md)
|
- **Development Guide**: [AGENTS.md](./AGENTS.md)
|
||||||
- **Component Development**: `pnpm ui:storybook`
|
- **Component Development**: `pnpm ui:storybook`
|
||||||
- **Testing**: `pnpm test` or `pnpm test:coverage` (View results on [Codecov](https://app.codecov.io/github/deytenit/ermnvldmr.com))
|
- **Testing**: `pnpm test` or `pnpm test:coverage`
|
||||||
- **Code Quality**: `pnpm lint` and `pnpm typecheck`
|
- **Code Quality**: `pnpm lint` and `pnpm typecheck`
|
||||||
|
|
||||||
### Designer
|
### Designer
|
||||||
|
|||||||
@@ -35,186 +35,8 @@ write_files:
|
|||||||
# public key: age1jpa7hqyzzdfq7lvnw3l8qy6648mtjgpcqnljl5jz92dcqjrnsqfsn7m0fl
|
# public key: age1jpa7hqyzzdfq7lvnw3l8qy6648mtjgpcqnljl5jz92dcqjrnsqfsn7m0fl
|
||||||
AGE-SECRET-KEY-1PLACEHOLDERFORYOURPRIVATEAGEKEY
|
AGE-SECRET-KEY-1PLACEHOLDERFORYOURPRIVATEAGEKEY
|
||||||
|
|
||||||
# ----------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# 3. Security Hardening Configuration
|
# 3. Bootstrap Cluster (Pre-baked script mounts disk, starts K3s, and syncs Flux)
|
||||||
# ----------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
- path: /etc/ssh/sshd_config.d/99-security-hardening.conf
|
|
||||||
owner: root:root
|
|
||||||
permissions: '0600'
|
|
||||||
content: |
|
|
||||||
PasswordAuthentication no
|
|
||||||
PermitRootLogin prohibit-password
|
|
||||||
KbdInteractiveAuthentication no
|
|
||||||
X11Forwarding no
|
|
||||||
MaxAuthTries 3
|
|
||||||
ClientAliveInterval 300
|
|
||||||
ClientAliveCountMax 2
|
|
||||||
|
|
||||||
- path: /etc/sysctl.d/99-k3s-hardening.conf
|
|
||||||
owner: root:root
|
|
||||||
permissions: '0644'
|
|
||||||
content: |
|
|
||||||
# Network SYN Flood Protection
|
|
||||||
net.ipv4.tcp_syncookies = 1
|
|
||||||
# Disable ICMP redirects
|
|
||||||
net.ipv4.conf.all.accept_redirects = 0
|
|
||||||
net.ipv4.conf.default.accept_redirects = 0
|
|
||||||
net.ipv4.conf.all.send_redirects = 0
|
|
||||||
net.ipv4.conf.default.send_redirects = 0
|
|
||||||
# Disable Source Routing
|
|
||||||
net.ipv4.conf.all.accept_source_route = 0
|
|
||||||
net.ipv4.conf.default.accept_source_route = 0
|
|
||||||
# Anti-spoofing (Reverse Path Filtering)
|
|
||||||
net.ipv4.conf.all.rp_filter = 1
|
|
||||||
net.ipv4.conf.default.rp_filter = 1
|
|
||||||
# Required for K8s pod networking
|
|
||||||
net.ipv4.ip_forward = 1
|
|
||||||
# System Hardening
|
|
||||||
kernel.kptr_restrict = 2
|
|
||||||
fs.protected_hardlinks = 1
|
|
||||||
fs.protected_symlinks = 1
|
|
||||||
fs.inotify.max_user_watches = 524288
|
|
||||||
fs.inotify.max_user_instances = 512
|
|
||||||
|
|
||||||
- path: /etc/rancher/k3s/config.yaml
|
|
||||||
owner: root:root
|
|
||||||
permissions: '0600'
|
|
||||||
content: |
|
|
||||||
write-kubeconfig-mode: "0644"
|
|
||||||
|
|
||||||
# ----------------------------------------------------------------------------
|
|
||||||
# 4. Bootstrap Cluster Script
|
|
||||||
# ----------------------------------------------------------------------------
|
|
||||||
- path: /usr/local/bin/bootstrap-cluster.sh
|
|
||||||
owner: root:root
|
|
||||||
permissions: '0755'
|
|
||||||
content: |
|
|
||||||
#!/usr/bin/env bash
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
echo "=== [Bootstrap] Ensuring Reliable DNS Resolution ==="
|
|
||||||
if ! grep -q "nameserver" /etc/resolv.conf 2>/dev/null; then
|
|
||||||
cat << 'EOF_DNS' > /etc/resolv.conf
|
|
||||||
nameserver 1.1.1.1
|
|
||||||
nameserver 8.8.8.8
|
|
||||||
nameserver 77.88.8.8
|
|
||||||
EOF_DNS
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "=== [Bootstrap] Applying Sysctl Hardening ==="
|
|
||||||
sysctl --system
|
|
||||||
|
|
||||||
echo "=== [Bootstrap] Ensuring SSH Host Keys & Starting SSH ==="
|
|
||||||
ssh-keygen -A
|
|
||||||
systemctl restart ssh || systemctl restart sshd || true
|
|
||||||
|
|
||||||
echo "=== [Bootstrap] Configuring UFW Firewall ==="
|
|
||||||
ufw default deny incoming
|
|
||||||
ufw default allow outgoing
|
|
||||||
ufw default allow routed
|
|
||||||
ufw allow 22/tcp comment 'SSH'
|
|
||||||
ufw allow 80/tcp comment 'HTTP Traefik'
|
|
||||||
ufw allow 443/tcp comment 'HTTPS Traefik'
|
|
||||||
# Allow Kubernetes Pod & Service traffic
|
|
||||||
ufw allow in on cni0 || true
|
|
||||||
ufw allow in on flannel.1 || true
|
|
||||||
ufw allow from 10.42.0.0/16 comment 'K3s Pod CIDR'
|
|
||||||
ufw allow from 10.43.0.0/16 comment 'K3s Service CIDR'
|
|
||||||
ufw --force enable
|
|
||||||
|
|
||||||
echo "=== [Bootstrap] Enabling Fail2ban ==="
|
|
||||||
systemctl enable --now fail2ban || true
|
|
||||||
|
|
||||||
echo "=== [Bootstrap] Checking for Secondary Persistent Data Disk ==="
|
|
||||||
if [ -b /dev/vdb ]; then
|
|
||||||
echo "Secondary disk /dev/vdb detected."
|
|
||||||
if ! blkid /dev/vdb >/dev/null 2>&1; then
|
|
||||||
echo "Formatting /dev/vdb with ext4 filesystem..."
|
|
||||||
mkfs.ext4 -F -L k3s-storage /dev/vdb
|
|
||||||
fi
|
|
||||||
mkdir -p /var/lib/rancher/k3s/storage
|
|
||||||
if ! grep -qs '/var/lib/rancher/k3s/storage' /proc/mounts; then
|
|
||||||
mount /dev/vdb /var/lib/rancher/k3s/storage
|
|
||||||
echo "LABEL=k3s-storage /var/lib/rancher/k3s/storage ext4 defaults,noatime 0 2" >> /etc/fstab
|
|
||||||
echo "Mounted /dev/vdb to /var/lib/rancher/k3s/storage."
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "=== [Bootstrap] Starting K3s Service ==="
|
|
||||||
systemctl enable --now k3s.service
|
|
||||||
|
|
||||||
echo "=== [Bootstrap] Waiting for K3s API server ready ==="
|
|
||||||
export KUBECONFIG=/etc/rancher/k3s/k3s.yaml
|
|
||||||
until kubectl get nodes >/dev/null 2>&1; do
|
|
||||||
echo "Waiting for Kubernetes API..."
|
|
||||||
sleep 3
|
|
||||||
done
|
|
||||||
|
|
||||||
echo "=== [Bootstrap] Cluster node is online ==="
|
|
||||||
kubectl get nodes
|
|
||||||
|
|
||||||
echo "=== [Bootstrap] Creating flux-system namespace ==="
|
|
||||||
kubectl create namespace flux-system --dry-run=client -o yaml | kubectl apply -f -
|
|
||||||
|
|
||||||
echo "=== [Bootstrap] Injecting SOPS age decryption key ==="
|
|
||||||
if [ -f /root/.config/sops/age/keys.txt ]; then
|
|
||||||
kubectl create secret generic sops-age \
|
|
||||||
--namespace=flux-system \
|
|
||||||
--from-file=age.agekey=/root/.config/sops/age/keys.txt \
|
|
||||||
--dry-run=client -o yaml | kubectl apply -f -
|
|
||||||
echo "sops-age secret created."
|
|
||||||
else
|
|
||||||
echo "WARNING: /root/.config/sops/age/keys.txt not found. Inject key manually via kubectl."
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "=== [Bootstrap] Installing Flux Operator / Custom Resources ==="
|
|
||||||
kubectl apply -f https://github.com/fluxcd/flux2/releases/download/v2.4.0/install.yaml
|
|
||||||
|
|
||||||
echo "=== [Bootstrap] Setting up Kubectl access for non-root users ==="
|
|
||||||
for home_dir in /home/*; do
|
|
||||||
if [ -d "$home_dir" ]; then
|
|
||||||
user_name=$(basename "$home_dir")
|
|
||||||
mkdir -p "$home_dir/.kube"
|
|
||||||
cp /etc/rancher/k3s/k3s.yaml "$home_dir/.kube/config"
|
|
||||||
chown -R "$user_name:$user_name" "$home_dir/.kube"
|
|
||||||
chmod 600 "$home_dir/.kube/config"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
echo "=== [Bootstrap] Applying initial GitOps root sync ==="
|
|
||||||
kubectl apply -f - << 'EOF_GITOPS'
|
|
||||||
apiVersion: source.toolkit.fluxcd.io/v1
|
|
||||||
kind: GitRepository
|
|
||||||
metadata:
|
|
||||||
name: ermnvldmr-repo
|
|
||||||
namespace: flux-system
|
|
||||||
spec:
|
|
||||||
interval: 1m
|
|
||||||
url: https://github.com/deytenit/ermnvldmr.com.git
|
|
||||||
ref:
|
|
||||||
branch: next
|
|
||||||
---
|
|
||||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
|
||||||
kind: Kustomization
|
|
||||||
metadata:
|
|
||||||
name: cluster-sync
|
|
||||||
namespace: flux-system
|
|
||||||
spec:
|
|
||||||
interval: 5m
|
|
||||||
sourceRef:
|
|
||||||
kind: GitRepository
|
|
||||||
name: ermnvldmr-repo
|
|
||||||
path: ./ci/k8s/clusters/production
|
|
||||||
prune: true
|
|
||||||
wait: true
|
|
||||||
timeout: 2m
|
|
||||||
decryption:
|
|
||||||
provider: sops
|
|
||||||
secretRef:
|
|
||||||
name: sops-age
|
|
||||||
EOF_GITOPS
|
|
||||||
|
|
||||||
echo "=== [Bootstrap] First-Boot Bootstrap Sequence Complete ==="
|
|
||||||
|
|
||||||
runcmd:
|
runcmd:
|
||||||
- /usr/local/bin/bootstrap-cluster.sh
|
- /usr/local/bin/bootstrap-cluster.sh
|
||||||
@@ -5,6 +5,16 @@ server {
|
|||||||
root /usr/share/nginx/html;
|
root /usr/share/nginx/html;
|
||||||
index index.html;
|
index index.html;
|
||||||
|
|
||||||
|
# Prevent HTTP protocol downgrade behind reverse proxy on redirects
|
||||||
|
absolute_redirect off;
|
||||||
|
|
||||||
|
# Security Headers (Defense in depth)
|
||||||
|
add_header X-Content-Type-Options "nosniff" always;
|
||||||
|
add_header X-Frame-Options "DENY" always;
|
||||||
|
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
|
||||||
|
add_header Cross-Origin-Opener-Policy "same-origin" always;
|
||||||
|
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
|
||||||
|
|
||||||
# Gzip compression
|
# Gzip compression
|
||||||
gzip on;
|
gzip on;
|
||||||
gzip_vary on;
|
gzip_vary on;
|
||||||
@@ -25,13 +35,15 @@ server {
|
|||||||
# root is inherited from server block, so /en/static/js/file.js resolves correctly
|
# root is inherited from server block, so /en/static/js/file.js resolves correctly
|
||||||
location ~* \.(js|css|woff|woff2|ttf|eot)$ {
|
location ~* \.(js|css|woff|woff2|ttf|eot)$ {
|
||||||
expires 1y;
|
expires 1y;
|
||||||
add_header Cache-Control "public, immutable";
|
add_header Cache-Control "public, immutable" always;
|
||||||
|
add_header Access-Control-Allow-Origin "*" always;
|
||||||
}
|
}
|
||||||
|
|
||||||
# Cache images
|
# Cache images
|
||||||
location ~* \.(png|jpg|jpeg|gif|ico|svg)$ {
|
location ~* \.(png|jpg|jpeg|gif|ico|svg)$ {
|
||||||
expires 1y;
|
expires 1y;
|
||||||
add_header Cache-Control "public, no-transform";
|
add_header Cache-Control "public, no-transform" always;
|
||||||
|
add_header Access-Control-Allow-Origin "*" always;
|
||||||
}
|
}
|
||||||
|
|
||||||
# English locale — SPA fallback for non-asset routes
|
# English locale — SPA fallback for non-asset routes
|
||||||
@@ -48,6 +60,7 @@ server {
|
|||||||
location = /version.json {
|
location = /version.json {
|
||||||
add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0" always;
|
add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0" always;
|
||||||
add_header Content-Type "application/json" always;
|
add_header Content-Type "application/json" always;
|
||||||
|
add_header Access-Control-Allow-Origin "*" always;
|
||||||
try_files /version.json =404;
|
try_files /version.json =404;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ spec:
|
|||||||
spec:
|
spec:
|
||||||
containers:
|
containers:
|
||||||
- name: docs
|
- name: docs
|
||||||
image: ghcr.io/deytenit/ermnvldmr.com/docs:sha-91f5245
|
image: git.ermnvldmr.com/deytenit/ermnvldmr.com/docs:sha-91f5245
|
||||||
imagePullPolicy: IfNotPresent
|
imagePullPolicy: IfNotPresent
|
||||||
ports:
|
ports:
|
||||||
- name: http
|
- name: http
|
||||||
|
|||||||
@@ -5,5 +5,6 @@ resources:
|
|||||||
- deployment.yaml
|
- deployment.yaml
|
||||||
- service.yaml
|
- service.yaml
|
||||||
images:
|
images:
|
||||||
- name: ghcr.io/deytenit/ermnvldmr.com/docs
|
- name: git.ermnvldmr.com/deytenit/ermnvldmr.com/docs
|
||||||
newTag: sha-4e4cac0
|
newName: git.ermnvldmr.com/deytenit/ermnvldmr.com/docs
|
||||||
|
newTag: sha-4e0bb72
|
||||||
@@ -12,11 +12,20 @@ sops:
|
|||||||
age:
|
age:
|
||||||
- enc: |
|
- enc: |
|
||||||
-----BEGIN AGE ENCRYPTED FILE-----
|
-----BEGIN AGE ENCRYPTED FILE-----
|
||||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAxRXIvMEpaWU1XNjV2OFpp
|
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBRWFNtaHhPbmlodUZXSFgy
|
||||||
Z1lYb25kOFVVaXlRYkdzSmxWbmxqaXR6TEhRCnF0M2ovRVNmdTU3WnNOcy82OExV
|
S1YwUjc4ZnZWdy9TM1NiejdrRHJuZnR5aG5rCjJrMWY2OXExZkpmUHpUNTE1T05x
|
||||||
YXNjZVJrbTdXQWJxMjQvNEdZNlBwcjAKLS0tIEEzczNmZjFwT1d2aXVKV1Bvdm1Q
|
dzBYbmI3ZmVHRlhXaHk5dFFEMjIxUUUKLS0tIEd0L2N4TUsxV0tjWm81cUQ4dVdS
|
||||||
UnZoNVNCYjJiYWd6WlNobGEyUGh5NmMKkUTDkYlNkXH8DegvBT7ymkL7h1B9x77N
|
WDVuSGxuNVAxeVk2UUdhQnFDV1FZOW8K4Fc8T/XM+E6F0iOqpSMbh/pOAI2vq3am
|
||||||
IxeZI5mp8vc347/620+cbMMr2+aELlgs9/bJhUcLRm0Bv8UDVLOleg==
|
9rMDxzwfIL9hwNDoy5LVPdnBfOXlCoZ8OnMR9Euj8FBW6pHErkmBUA==
|
||||||
|
-----END AGE ENCRYPTED FILE-----
|
||||||
|
recipient: age15zq3cje3ttmx2fhqp9cpeght6feq2w8e5m38799stjetj8urcccs36r4rc
|
||||||
|
- enc: |
|
||||||
|
-----BEGIN AGE ENCRYPTED FILE-----
|
||||||
|
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA0K3k2cis1T3hrSmZGa2hq
|
||||||
|
ME1VQy9HSG5MWUhjdXgzb0cwNitYY1ZvRVI4Cm0vYXptOW9TUDJFZzZvNEJLOHJB
|
||||||
|
VnhnK1hOWUgxd2E1VmFDbFJPZUlQajAKLS0tIEszV0FRMHoyQ2lFUm5IWGtnVUNH
|
||||||
|
Q244Nmd2czZXSmxEMnk3cWV1bm8rS28KGyANylD4EQkhWKDHwmGQHyAm1ZjA5acw
|
||||||
|
VisJZnJ9KuFPB2Toi7FTMeHRNYPk1uXgwKoDFLSrzMElPXWDWm4B7A==
|
||||||
-----END AGE ENCRYPTED FILE-----
|
-----END AGE ENCRYPTED FILE-----
|
||||||
recipient: age1jpa7hqyzzdfq7lvnw3l8qy6648mtjgpcqnljl5jz92dcqjrnsqfsn7m0fl
|
recipient: age1jpa7hqyzzdfq7lvnw3l8qy6648mtjgpcqnljl5jz92dcqjrnsqfsn7m0fl
|
||||||
encrypted_regex: ^(data|stringData)$
|
encrypted_regex: ^(data|stringData)$
|
||||||
|
|||||||
@@ -6,3 +6,4 @@ metadata:
|
|||||||
data:
|
data:
|
||||||
DATABASE_TYPE: "postgresql"
|
DATABASE_TYPE: "postgresql"
|
||||||
CLIENT_IP_HEADER: "X-Forwarded-For"
|
CLIENT_IP_HEADER: "X-Forwarded-For"
|
||||||
|
TRACKER_SCRIPT_NAME: "trace.js"
|
||||||
@@ -17,6 +17,8 @@ spec:
|
|||||||
metadata:
|
metadata:
|
||||||
labels:
|
labels:
|
||||||
app: umami
|
app: umami
|
||||||
|
annotations:
|
||||||
|
config/tracker-script-name: "trace.js"
|
||||||
spec:
|
spec:
|
||||||
containers:
|
containers:
|
||||||
- name: umami
|
- name: umami
|
||||||
|
|||||||
@@ -11,11 +11,20 @@ sops:
|
|||||||
age:
|
age:
|
||||||
- enc: |
|
- enc: |
|
||||||
-----BEGIN AGE ENCRYPTED FILE-----
|
-----BEGIN AGE ENCRYPTED FILE-----
|
||||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBGZ2h6THNGTnY2ay9Tc2Q3
|
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA4SHJWSm54SHorbTZBOGtF
|
||||||
S0xxU3NEZGx2TS9MRFdqZDV6aEtUalBWRFVJCjZMd1VCdkg1cjIxSlliZXNRQnU0
|
VkRrQlpHbTgxSkh3L2ljZW42emEzQlBHa0hvCmxuQ3VjR2hQNzVlZ3FVS2Q3THp4
|
||||||
YnMzTXJOSGdsUDUwNkdDdWZWcmRaZjgKLS0tIDdEOFoyOWtvZytITys4bk9ra082
|
SEZGa09EM1BYSlUxWEtuMGp0Tld3R3cKLS0tIEcwcUd6ZkdDdTAvMDFtSGpCZ3ls
|
||||||
WmFIREJMS1BVU0o1VnZHby9ZSHN4cGcKReBW7hdTPH8eGqPzEYkOdrIUYm9a1jOi
|
TVJYdHRDMXlWVmx4WStsT2hGUUZkeEkK26wJbgH0yvKPFXR4TC2rdeBD0axAs4WU
|
||||||
du/1fhAyhjimbbCNdOSuSjrSP8QX6mxwPoDb1dVlKi0Rah5VGW+HWw==
|
rfJ8MWet6AbEAyOmiAjigNbM9bJwGlDW1UThnGQ/fFQfJW6U4T1Tgw==
|
||||||
|
-----END AGE ENCRYPTED FILE-----
|
||||||
|
recipient: age15zq3cje3ttmx2fhqp9cpeght6feq2w8e5m38799stjetj8urcccs36r4rc
|
||||||
|
- enc: |
|
||||||
|
-----BEGIN AGE ENCRYPTED FILE-----
|
||||||
|
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBKVUt1UlNLTHZmV1djWEZp
|
||||||
|
akVLUnliV2VQY0dzSmVMdmxMRTRoL2FWZm5rCm1WWkZPK2tEWW4rNVRObktuVVdk
|
||||||
|
cEdNTHd6V2t6ZjVRMWhRbk5GNXpFdjgKLS0tIHZoZS9wblR1bTFkMzV4OWxLSm5B
|
||||||
|
QWpwUG93dTc5MGNBbjAyVnNWMlRJblEK8ZRPL4/aCSKjPUg1K+kH9IigwZX1tB1U
|
||||||
|
Y1P8IYiuTJ+YD/UcQyh0Pp2d8l5gQsTc1ES9388wcKBKMeKHV9FqYg==
|
||||||
-----END AGE ENCRYPTED FILE-----
|
-----END AGE ENCRYPTED FILE-----
|
||||||
recipient: age1jpa7hqyzzdfq7lvnw3l8qy6648mtjgpcqnljl5jz92dcqjrnsqfsn7m0fl
|
recipient: age1jpa7hqyzzdfq7lvnw3l8qy6648mtjgpcqnljl5jz92dcqjrnsqfsn7m0fl
|
||||||
encrypted_regex: ^(data|stringData)$
|
encrypted_regex: ^(data|stringData)$
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ spec:
|
|||||||
spec:
|
spec:
|
||||||
containers:
|
containers:
|
||||||
- name: www
|
- name: www
|
||||||
image: ghcr.io/deytenit/ermnvldmr.com/www:sha-6d33b71
|
image: git.ermnvldmr.com/deytenit/ermnvldmr.com/www:sha-6d33b71
|
||||||
imagePullPolicy: IfNotPresent
|
imagePullPolicy: IfNotPresent
|
||||||
ports:
|
ports:
|
||||||
- name: http
|
- name: http
|
||||||
|
|||||||
@@ -5,5 +5,6 @@ resources:
|
|||||||
- deployment.yaml
|
- deployment.yaml
|
||||||
- service.yaml
|
- service.yaml
|
||||||
images:
|
images:
|
||||||
- name: ghcr.io/deytenit/ermnvldmr.com/www
|
- name: git.ermnvldmr.com/deytenit/ermnvldmr.com/www
|
||||||
newTag: sha-a60b095
|
newName: git.ermnvldmr.com/deytenit/ermnvldmr.com/www
|
||||||
|
newTag: sha-4e0bb72
|
||||||
@@ -5,7 +5,7 @@ metadata:
|
|||||||
namespace: flux-system
|
namespace: flux-system
|
||||||
spec:
|
spec:
|
||||||
interval: 1m
|
interval: 1m
|
||||||
url: https://github.com/deytenit/ermnvldmr.com.git
|
url: https://git.ermnvldmr.com/deytenit/ermnvldmr.com.git
|
||||||
ref:
|
ref:
|
||||||
branch: next
|
branch: next
|
||||||
---
|
---
|
||||||
|
|||||||
File diff suppressed because it is too large.
Load diff
@@ -1,5 +1,5 @@
|
|||||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
kind: Kustomization
|
kind: Kustomization
|
||||||
resources:
|
resources:
|
||||||
- https://github.com/cert-manager/cert-manager/releases/download/v1.17.0/cert-manager.yaml
|
- install.yaml
|
||||||
- cluster-issuer.yaml
|
- cluster-issuer.yaml
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: beacon-ingress
|
||||||
|
namespace: com-ermnvldmr
|
||||||
|
annotations:
|
||||||
|
traefik.ingress.kubernetes.io/router.entrypoints: web,websecure
|
||||||
|
traefik.ingress.kubernetes.io/router.middlewares: com-ermnvldmr-strip-beacon@kubernetescrd
|
||||||
|
traefik.ingress.kubernetes.io/router.priority: "100"
|
||||||
|
spec:
|
||||||
|
ingressClassName: traefik
|
||||||
|
tls:
|
||||||
|
- hosts:
|
||||||
|
- www.ermnvldmr.com
|
||||||
|
secretName: ermnvldmr-tls
|
||||||
|
- hosts:
|
||||||
|
- docs.ermnvldmr.com
|
||||||
|
secretName: docs-ermnvldmr-tls
|
||||||
|
rules:
|
||||||
|
- host: www.ermnvldmr.com
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
- path: /trace
|
||||||
|
pathType: Prefix
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: umami-service
|
||||||
|
port:
|
||||||
|
number: 3000
|
||||||
|
- host: docs.ermnvldmr.com
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
- path: /trace
|
||||||
|
pathType: Prefix
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: umami-service
|
||||||
|
port:
|
||||||
|
number: 3000
|
||||||
@@ -1,23 +1,18 @@
|
|||||||
apiVersion: networking.k8s.io/v1
|
apiVersion: networking.k8s.io/v1
|
||||||
kind: Ingress
|
kind: Ingress
|
||||||
metadata:
|
metadata:
|
||||||
name: main-ingress
|
name: www-ingress
|
||||||
namespace: com-ermnvldmr
|
namespace: com-ermnvldmr
|
||||||
annotations:
|
annotations:
|
||||||
cert-manager.io/cluster-issuer: letsencrypt-prod
|
cert-manager.io/cluster-issuer: letsencrypt-prod
|
||||||
traefik.ingress.kubernetes.io/router.entrypoints: web,websecure
|
traefik.ingress.kubernetes.io/router.entrypoints: web,websecure
|
||||||
|
traefik.ingress.kubernetes.io/router.middlewares: com-ermnvldmr-sec-headers-common@kubernetescrd,com-ermnvldmr-sec-headers-www@kubernetescrd
|
||||||
spec:
|
spec:
|
||||||
ingressClassName: traefik
|
ingressClassName: traefik
|
||||||
tls:
|
tls:
|
||||||
- hosts:
|
- hosts:
|
||||||
- www.ermnvldmr.com
|
- www.ermnvldmr.com
|
||||||
secretName: ermnvldmr-tls
|
secretName: ermnvldmr-tls
|
||||||
- hosts:
|
|
||||||
- docs.ermnvldmr.com
|
|
||||||
secretName: docs-ermnvldmr-tls
|
|
||||||
- hosts:
|
|
||||||
- umami.ermnvldmr.com
|
|
||||||
secretName: umami-ermnvldmr-tls
|
|
||||||
rules:
|
rules:
|
||||||
- host: www.ermnvldmr.com
|
- host: www.ermnvldmr.com
|
||||||
http:
|
http:
|
||||||
@@ -29,6 +24,23 @@ spec:
|
|||||||
name: www-service
|
name: www-service
|
||||||
port:
|
port:
|
||||||
number: 80
|
number: 80
|
||||||
|
---
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: docs-ingress
|
||||||
|
namespace: com-ermnvldmr
|
||||||
|
annotations:
|
||||||
|
cert-manager.io/cluster-issuer: letsencrypt-prod
|
||||||
|
traefik.ingress.kubernetes.io/router.entrypoints: web,websecure
|
||||||
|
traefik.ingress.kubernetes.io/router.middlewares: com-ermnvldmr-sec-headers-common@kubernetescrd,com-ermnvldmr-sec-headers-docs@kubernetescrd
|
||||||
|
spec:
|
||||||
|
ingressClassName: traefik
|
||||||
|
tls:
|
||||||
|
- hosts:
|
||||||
|
- docs.ermnvldmr.com
|
||||||
|
secretName: docs-ermnvldmr-tls
|
||||||
|
rules:
|
||||||
- host: docs.ermnvldmr.com
|
- host: docs.ermnvldmr.com
|
||||||
http:
|
http:
|
||||||
paths:
|
paths:
|
||||||
@@ -39,6 +51,23 @@ spec:
|
|||||||
name: docs-service
|
name: docs-service
|
||||||
port:
|
port:
|
||||||
number: 80
|
number: 80
|
||||||
|
---
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: umami-ingress
|
||||||
|
namespace: com-ermnvldmr
|
||||||
|
annotations:
|
||||||
|
cert-manager.io/cluster-issuer: letsencrypt-prod
|
||||||
|
traefik.ingress.kubernetes.io/router.entrypoints: web,websecure
|
||||||
|
traefik.ingress.kubernetes.io/router.middlewares: com-ermnvldmr-sec-headers-common@kubernetescrd,com-ermnvldmr-sec-headers-umami@kubernetescrd
|
||||||
|
spec:
|
||||||
|
ingressClassName: traefik
|
||||||
|
tls:
|
||||||
|
- hosts:
|
||||||
|
- umami.ermnvldmr.com
|
||||||
|
secretName: umami-ermnvldmr-tls
|
||||||
|
rules:
|
||||||
- host: umami.ermnvldmr.com
|
- host: umami.ermnvldmr.com
|
||||||
http:
|
http:
|
||||||
paths:
|
paths:
|
||||||
|
|||||||
@@ -2,3 +2,9 @@ apiVersion: kustomize.config.k8s.io/v1beta1
|
|||||||
kind: Kustomization
|
kind: Kustomization
|
||||||
resources:
|
resources:
|
||||||
- ingress.yaml
|
- ingress.yaml
|
||||||
|
- middleware-strip-beacon.yaml
|
||||||
|
- ingress-beacon.yaml
|
||||||
|
- middleware-sec-headers-common.yaml
|
||||||
|
- middleware-sec-headers-www.yaml
|
||||||
|
- middleware-sec-headers-docs.yaml
|
||||||
|
- middleware-sec-headers-umami.yaml
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
apiVersion: traefik.io/v1alpha1
|
||||||
|
kind: Middleware
|
||||||
|
metadata:
|
||||||
|
name: sec-headers-common
|
||||||
|
namespace: com-ermnvldmr
|
||||||
|
spec:
|
||||||
|
headers:
|
||||||
|
stsSeconds: 63072000
|
||||||
|
stsIncludeSubdomains: true
|
||||||
|
stsPreload: true
|
||||||
|
forceSTSHeader: true
|
||||||
|
customFrameOptionsValue: "DENY"
|
||||||
|
contentTypeNosniff: true
|
||||||
|
browserXssFilter: false
|
||||||
|
referrerPolicy: "strict-origin-when-cross-origin"
|
||||||
|
customResponseHeaders:
|
||||||
|
Cross-Origin-Opener-Policy: "same-origin"
|
||||||
|
Permissions-Policy: "camera=(), microphone=(), geolocation=(), browsing-topics=()"
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
apiVersion: traefik.io/v1alpha1
|
||||||
|
kind: Middleware
|
||||||
|
metadata:
|
||||||
|
name: sec-headers-docs
|
||||||
|
namespace: com-ermnvldmr
|
||||||
|
spec:
|
||||||
|
headers:
|
||||||
|
contentSecurityPolicy: "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https://static.ermnvldmr.com; font-src 'self' data:; connect-src 'self'; object-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'none'; require-trusted-types-for 'script'; trusted-types default; upgrade-insecure-requests;"
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
apiVersion: traefik.io/v1alpha1
|
||||||
|
kind: Middleware
|
||||||
|
metadata:
|
||||||
|
name: sec-headers-umami
|
||||||
|
namespace: com-ermnvldmr
|
||||||
|
spec:
|
||||||
|
headers:
|
||||||
|
contentSecurityPolicy: "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; connect-src 'self'; object-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'none'; upgrade-insecure-requests;"
|
||||||
|
customResponseHeaders:
|
||||||
|
Content-Security-Policy-Report-Only: "require-trusted-types-for 'script'; trusted-types default;"
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
apiVersion: traefik.io/v1alpha1
|
||||||
|
kind: Middleware
|
||||||
|
metadata:
|
||||||
|
name: sec-headers-www
|
||||||
|
namespace: com-ermnvldmr
|
||||||
|
spec:
|
||||||
|
headers:
|
||||||
|
contentSecurityPolicy: "default-src 'self'; script-src 'self' 'sha256-gUpIj4OcSwECFlSp351SCYJAe1wTOCQlrKBlASuO3CY=' 'sha256-3VjVzYfJpuNMLKyrxQTIc8ACxv37paQ4Talwg1s/7N0='; style-src 'self' 'unsafe-inline'; img-src 'self' data: https://static.ermnvldmr.com; font-src 'self' data:; connect-src 'self'; object-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'none'; require-trusted-types-for 'script'; trusted-types default; upgrade-insecure-requests;"
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
apiVersion: traefik.io/v1alpha1
|
||||||
|
kind: Middleware
|
||||||
|
metadata:
|
||||||
|
name: strip-beacon
|
||||||
|
namespace: com-ermnvldmr
|
||||||
|
spec:
|
||||||
|
stripPrefix:
|
||||||
|
prefixes:
|
||||||
|
- /trace
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
[git.ermnvldmr.com]:22222,[45.150.33.239]:22222 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBXcvf3Lds3AKfGHGh00IWR9tSRbBBqrV/CC6JBGmcrD
|
||||||
@@ -9,7 +9,7 @@ packer {
|
|||||||
|
|
||||||
variable "debian_cloud_image_url" {
|
variable "debian_cloud_image_url" {
|
||||||
type = string
|
type = string
|
||||||
default = "https://cloud.debian.org/images/cloud/bookworm/latest/debian-12-nocloud-amd64.qcow2"
|
default = "https://cloud.debian.org/images/cloud/bookworm/latest/debian-12-genericcloud-amd64.qcow2"
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "debian_cloud_image_checksum" {
|
variable "debian_cloud_image_checksum" {
|
||||||
@@ -42,6 +42,8 @@ source "qemu" "debian_k3s" {
|
|||||||
ssh_password = "packer"
|
ssh_password = "packer"
|
||||||
ssh_timeout = "5m"
|
ssh_timeout = "5m"
|
||||||
vm_name = var.vm_name
|
vm_name = var.vm_name
|
||||||
|
cpus = 2
|
||||||
|
memory = 2048
|
||||||
net_device = "virtio-net"
|
net_device = "virtio-net"
|
||||||
disk_interface = "virtio"
|
disk_interface = "virtio"
|
||||||
headless = true
|
headless = true
|
||||||
|
|||||||
@@ -85,4 +85,45 @@ auto eth0
|
|||||||
iface eth0 inet dhcp
|
iface eth0 inet dhcp
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
# Apply kernel hardening sysctl parameters
|
||||||
|
cat << 'EOF' > /etc/sysctl.d/99-k3s-hardening.conf
|
||||||
|
# Network SYN Flood Protection
|
||||||
|
net.ipv4.tcp_syncookies = 1
|
||||||
|
# Disable ICMP redirects
|
||||||
|
net.ipv4.conf.all.accept_redirects = 0
|
||||||
|
net.ipv4.conf.default.accept_redirects = 0
|
||||||
|
net.ipv4.conf.all.send_redirects = 0
|
||||||
|
net.ipv4.conf.default.send_redirects = 0
|
||||||
|
# Disable Source Routing
|
||||||
|
net.ipv4.conf.all.accept_source_route = 0
|
||||||
|
net.ipv4.conf.default.accept_source_route = 0
|
||||||
|
# Anti-spoofing (Reverse Path Filtering)
|
||||||
|
net.ipv4.conf.all.rp_filter = 1
|
||||||
|
net.ipv4.conf.default.rp_filter = 1
|
||||||
|
# Required for K8s pod networking
|
||||||
|
net.ipv4.ip_forward = 1
|
||||||
|
# System Hardening
|
||||||
|
kernel.kptr_restrict = 2
|
||||||
|
fs.protected_hardlinks = 1
|
||||||
|
fs.protected_symlinks = 1
|
||||||
|
fs.inotify.max_user_watches = 524288
|
||||||
|
fs.inotify.max_user_instances = 512
|
||||||
|
EOF
|
||||||
|
sysctl --system || true
|
||||||
|
|
||||||
|
# Configure baseline UFW firewall & fail2ban
|
||||||
|
ufw default deny incoming
|
||||||
|
ufw default allow outgoing
|
||||||
|
ufw default allow routed
|
||||||
|
ufw allow 22/tcp comment 'SSH'
|
||||||
|
ufw allow 80/tcp comment 'HTTP Traefik'
|
||||||
|
ufw allow 443/tcp comment 'HTTPS Traefik'
|
||||||
|
ufw allow 6443/tcp comment 'K3s API'
|
||||||
|
ufw allow in on cni0 || true
|
||||||
|
ufw allow in on flannel.1 || true
|
||||||
|
ufw allow from 10.42.0.0/16 comment 'K3s Pod CIDR'
|
||||||
|
ufw allow from 10.43.0.0/16 comment 'K3s Service CIDR'
|
||||||
|
ufw --force enable
|
||||||
|
systemctl enable fail2ban || true
|
||||||
|
|
||||||
echo "=== Base System Configuration Complete ==="
|
echo "=== Base System Configuration Complete ==="
|
||||||
@@ -9,7 +9,8 @@ export INSTALL_K3S_SKIP_START="true"
|
|||||||
export INSTALL_K3S_VERSION="v1.31.2+k3s1"
|
export INSTALL_K3S_VERSION="v1.31.2+k3s1"
|
||||||
|
|
||||||
# Download official K3s installer and install binary/systemd unit without starting
|
# Download official K3s installer and install binary/systemd unit without starting
|
||||||
curl -sfL https://get.k3s.io | sh -
|
install -m 0755 /tmp/scripts/k3s /usr/local/bin/k3s
|
||||||
|
INSTALL_K3S_SKIP_DOWNLOAD=true sh /tmp/scripts/k3s-install.sh
|
||||||
|
|
||||||
# Verify k3s binary is located in /usr/local/bin
|
# Verify k3s binary is located in /usr/local/bin
|
||||||
which k3s
|
which k3s
|
||||||
@@ -19,7 +20,117 @@ k3s --version
|
|||||||
systemctl stop k3s.service || true
|
systemctl stop k3s.service || true
|
||||||
systemctl disable k3s.service || true
|
systemctl disable k3s.service || true
|
||||||
|
|
||||||
# Create configuration directory
|
# Create configuration directory and default config
|
||||||
mkdir -p /etc/rancher/k3s
|
mkdir -p /etc/rancher/k3s
|
||||||
|
cat << 'EOF' > /etc/rancher/k3s/config.yaml
|
||||||
|
write-kubeconfig-mode: "0644"
|
||||||
|
EOF
|
||||||
|
chmod 644 /etc/rancher/k3s/config.yaml
|
||||||
|
|
||||||
|
# Pre-stage default GitOps root sync manifest
|
||||||
|
mkdir -p /etc/flux
|
||||||
|
install -m 0644 /tmp/scripts/flux-install.yaml /etc/flux/install.yaml
|
||||||
|
cat << 'EOF' > /etc/flux/cluster-sync.yaml
|
||||||
|
apiVersion: source.toolkit.fluxcd.io/v1
|
||||||
|
kind: GitRepository
|
||||||
|
metadata:
|
||||||
|
name: ermnvldmr-repo
|
||||||
|
namespace: flux-system
|
||||||
|
spec:
|
||||||
|
interval: 1m
|
||||||
|
url: https://git.ermnvldmr.com/deytenit/ermnvldmr.com.git
|
||||||
|
ref:
|
||||||
|
branch: next
|
||||||
|
---
|
||||||
|
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||||
|
kind: Kustomization
|
||||||
|
metadata:
|
||||||
|
name: cluster-sync
|
||||||
|
namespace: flux-system
|
||||||
|
spec:
|
||||||
|
interval: 1m
|
||||||
|
sourceRef:
|
||||||
|
kind: GitRepository
|
||||||
|
name: ermnvldmr-repo
|
||||||
|
path: ./ci/k8s/clusters/production
|
||||||
|
prune: true
|
||||||
|
wait: true
|
||||||
|
timeout: 3m
|
||||||
|
decryption:
|
||||||
|
provider: sops
|
||||||
|
secretRef:
|
||||||
|
name: sops-age
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Install the cluster bootstrap script into /usr/local/bin
|
||||||
|
cat << 'EOF' > /usr/local/bin/bootstrap-cluster.sh
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
echo "=== [Bootstrap] Checking for Secondary Persistent Data Disk ==="
|
||||||
|
if [ -b /dev/vdb ]; then
|
||||||
|
echo "Secondary disk /dev/vdb detected."
|
||||||
|
if ! blkid /dev/vdb >/dev/null 2>&1; then
|
||||||
|
echo "Formatting /dev/vdb with ext4 filesystem..."
|
||||||
|
mkfs.ext4 -F -L k3s-storage /dev/vdb
|
||||||
|
fi
|
||||||
|
mkdir -p /var/lib/rancher/k3s/storage
|
||||||
|
if ! grep -qs '/var/lib/rancher/k3s/storage' /proc/mounts; then
|
||||||
|
mount /dev/vdb /var/lib/rancher/k3s/storage
|
||||||
|
echo "LABEL=k3s-storage /var/lib/rancher/k3s/storage ext4 defaults,noatime 0 2" >> /etc/fstab
|
||||||
|
echo "Mounted /dev/vdb to /var/lib/rancher/k3s/storage."
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "=== [Bootstrap] Starting K3s Service ==="
|
||||||
|
systemctl enable --now k3s.service
|
||||||
|
|
||||||
|
echo "=== [Bootstrap] Waiting for K3s API server ready ==="
|
||||||
|
export KUBECONFIG=/etc/rancher/k3s/k3s.yaml
|
||||||
|
until kubectl get nodes >/dev/null 2>&1; do
|
||||||
|
echo "Waiting for Kubernetes API..."
|
||||||
|
sleep 2
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "=== [Bootstrap] Cluster node is online ==="
|
||||||
|
kubectl get nodes
|
||||||
|
|
||||||
|
echo "=== [Bootstrap] Setting up Kubectl access for non-root users ==="
|
||||||
|
for home_dir in /home/*; do
|
||||||
|
if [ -d "$home_dir" ]; then
|
||||||
|
user_name=$(basename "$home_dir")
|
||||||
|
mkdir -p "$home_dir/.kube"
|
||||||
|
cp /etc/rancher/k3s/k3s.yaml "$home_dir/.kube/config"
|
||||||
|
chown -R "$user_name:$user_name" "$home_dir/.kube"
|
||||||
|
chmod 600 "$home_dir/.kube/config"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "=== [Bootstrap] Creating flux-system namespace ==="
|
||||||
|
kubectl create namespace flux-system --dry-run=client -o yaml | kubectl apply -f -
|
||||||
|
|
||||||
|
echo "=== [Bootstrap] Injecting SOPS age decryption key ==="
|
||||||
|
if [ -f /root/.config/sops/age/keys.txt ]; then
|
||||||
|
kubectl create secret generic sops-age \
|
||||||
|
--namespace=flux-system \
|
||||||
|
--from-file=age.agekey=/root/.config/sops/age/keys.txt \
|
||||||
|
--dry-run=client -o yaml | kubectl apply -f -
|
||||||
|
echo "sops-age secret created."
|
||||||
|
else
|
||||||
|
echo "WARNING: /root/.config/sops/age/keys.txt not found. Inject key manually via kubectl."
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "=== [Bootstrap] Installing Flux Operator / Custom Resources ==="
|
||||||
|
kubectl apply -f /etc/flux/install.yaml
|
||||||
|
|
||||||
|
echo "=== [Bootstrap] Applying initial GitOps root sync ==="
|
||||||
|
if [ -f /etc/flux/cluster-sync.yaml ]; then
|
||||||
|
kubectl apply -f /etc/flux/cluster-sync.yaml
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "=== [Bootstrap] First-Boot Bootstrap Sequence Complete ==="
|
||||||
|
EOF
|
||||||
|
|
||||||
|
chmod 755 /usr/local/bin/bootstrap-cluster.sh
|
||||||
|
|
||||||
echo "=== K3s Pre-installation Complete ==="
|
echo "=== K3s Pre-installation Complete ==="
|
||||||
@@ -4,6 +4,21 @@ export DEBIAN_FRONTEND=noninteractive
|
|||||||
|
|
||||||
echo "=== Sanitizing Machine Identity & Temporary Files ==="
|
echo "=== Sanitizing Machine Identity & Temporary Files ==="
|
||||||
|
|
||||||
|
# Lock temporary packer build user
|
||||||
|
passwd -l debian || true
|
||||||
|
|
||||||
|
# Apply SSH security hardening before final image capture
|
||||||
|
mkdir -p /etc/ssh/sshd_config.d
|
||||||
|
cat << 'EOF' > /etc/ssh/sshd_config.d/99-security-hardening.conf
|
||||||
|
PasswordAuthentication no
|
||||||
|
PermitRootLogin prohibit-password
|
||||||
|
KbdInteractiveAuthentication no
|
||||||
|
X11Forwarding no
|
||||||
|
MaxAuthTries 3
|
||||||
|
ClientAliveInterval 300
|
||||||
|
ClientAliveCountMax 2
|
||||||
|
EOF
|
||||||
|
|
||||||
# Clean APT caches and logs
|
# Clean APT caches and logs
|
||||||
apt-get autoremove -y --purge
|
apt-get autoremove -y --purge
|
||||||
apt-get clean
|
apt-get clean
|
||||||
|
|||||||
Executable
+64
@@ -0,0 +1,64 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SERVICE="${1:-}"
|
||||||
|
TARGET_COMMIT="${2:-}"
|
||||||
|
ENDPOINT="${3:-https://${SERVICE}.ermnvldmr.com/version.json}"
|
||||||
|
|
||||||
|
if [ -z "$SERVICE" ] || [ -z "$TARGET_COMMIT" ]; then
|
||||||
|
echo "Usage: $0 <service: www|docs> <target_commit> [endpoint_url]" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "========================================================"
|
||||||
|
echo "Verifying production deployment on $ENDPOINT"
|
||||||
|
echo "Expected commit: $TARGET_COMMIT"
|
||||||
|
echo "========================================================"
|
||||||
|
|
||||||
|
MAX_ATTEMPTS=45
|
||||||
|
ATTEMPT=1
|
||||||
|
CF_BLOCKED_COUNT=0
|
||||||
|
|
||||||
|
while [ $ATTEMPT -le $MAX_ATTEMPTS ]; do
|
||||||
|
echo "Attempt $ATTEMPT/$MAX_ATTEMPTS: Polling $ENDPOINT..."
|
||||||
|
|
||||||
|
RESP_FILE=$(mktemp)
|
||||||
|
HTTP_CODE=$(curl -sL --max-time 10 \
|
||||||
|
-H "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36" \
|
||||||
|
-H "Accept: application/json" \
|
||||||
|
-o "$RESP_FILE" \
|
||||||
|
-w "%{http_code}" \
|
||||||
|
"$ENDPOINT" || echo "000")
|
||||||
|
|
||||||
|
if [ "$HTTP_CODE" = "200" ]; then
|
||||||
|
LIVE_COMMIT=$(jq -r '.commit // empty' "$RESP_FILE" 2>/dev/null || true)
|
||||||
|
LIVE_VERSION=$(jq -r '.version // empty' "$RESP_FILE" 2>/dev/null || true)
|
||||||
|
echo " Live commit: ${LIVE_COMMIT:-<none>}, Live version: ${LIVE_VERSION:-<none>}"
|
||||||
|
|
||||||
|
if [ "$LIVE_COMMIT" = "$TARGET_COMMIT" ] || [ "$LIVE_VERSION" = "$TARGET_COMMIT" ]; then
|
||||||
|
echo "✅ Success! Production $SERVICE has successfully rolled out $TARGET_COMMIT."
|
||||||
|
rm -f "$RESP_FILE"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
elif [ "$HTTP_CODE" = "403" ] || [ "$HTTP_CODE" = "503" ]; then
|
||||||
|
echo " HTTP $HTTP_CODE: Cloudflare WAF/challenge encountered from runner IP."
|
||||||
|
CF_BLOCKED_COUNT=$((CF_BLOCKED_COUNT + 1))
|
||||||
|
else
|
||||||
|
echo " HTTP $HTTP_CODE: Endpoint returned unexpected status code or timed out."
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -f "$RESP_FILE"
|
||||||
|
|
||||||
|
if [ $CF_BLOCKED_COUNT -ge 5 ]; then
|
||||||
|
echo "⚠️ Cloudflare WAF consistently blocked external probe requests from this runner IP (HTTP $HTTP_CODE)."
|
||||||
|
echo "The GitOps release commit was already pushed to the repository; FluxCD will reconcile the cluster."
|
||||||
|
echo "Skipping further external HTTP verification to avoid false negative."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
ATTEMPT=$((ATTEMPT + 1))
|
||||||
|
sleep 10
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "❌ Deployment verification timed out after 7.5 minutes."
|
||||||
|
exit 1
|
||||||
Executable
+54
@@ -0,0 +1,54 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
mkdir -p output-qemu
|
||||||
|
|
||||||
|
echo "Downloading official Debian 12 cloud image..."
|
||||||
|
curl -fsSL -o base.qcow2 https://cloud.debian.org/images/cloud/bookworm/latest/debian-12-genericcloud-amd64.qcow2
|
||||||
|
|
||||||
|
echo "Expanding disk image to 10G..."
|
||||||
|
qemu-img resize base.qcow2 10G
|
||||||
|
|
||||||
|
echo "Connecting disk image via NBD..."
|
||||||
|
sudo modprobe nbd max_part=8
|
||||||
|
sudo qemu-nbd --connect=/dev/nbd0 base.qcow2
|
||||||
|
sleep 1
|
||||||
|
sudo partx -u /dev/nbd0 || true
|
||||||
|
|
||||||
|
echo "Mounting disk filesystem..."
|
||||||
|
sudo mkdir -p /mnt/target
|
||||||
|
sudo mount /dev/nbd0p1 /mnt/target
|
||||||
|
|
||||||
|
echo "Mounting host virtual filesystems and configuring DNS..."
|
||||||
|
sudo rm -f /mnt/target/etc/resolv.conf
|
||||||
|
echo "nameserver 1.1.1.1" | sudo tee /mnt/target/etc/resolv.conf
|
||||||
|
echo "nameserver 8.8.8.8" | sudo tee -a /mnt/target/etc/resolv.conf
|
||||||
|
sudo mount --bind /dev /mnt/target/dev
|
||||||
|
sudo mount --bind /dev/pts /mnt/target/dev/pts
|
||||||
|
sudo mount --bind /proc /mnt/target/proc
|
||||||
|
sudo mount --bind /sys /mnt/target/sys
|
||||||
|
|
||||||
|
echo "Copying provisioner scripts..."
|
||||||
|
sudo mkdir -p /mnt/target/tmp/scripts
|
||||||
|
sudo cp ci/packer/scripts/*.sh /mnt/target/tmp/scripts/
|
||||||
|
sudo cp /opt/ci/assets/k3s /opt/ci/assets/k3s-install.sh /mnt/target/tmp/scripts/
|
||||||
|
sudo cp /opt/ci/assets/flux-install-local.yaml /mnt/target/tmp/scripts/flux-install.yaml
|
||||||
|
sudo chmod +x /mnt/target/tmp/scripts/*.sh
|
||||||
|
|
||||||
|
echo "Running provisioner scripts in chroot..."
|
||||||
|
sudo chroot /mnt/target /bin/bash /tmp/scripts/01-base-system.sh
|
||||||
|
sudo chroot /mnt/target /bin/bash /tmp/scripts/02-install-k3s.sh
|
||||||
|
sudo chroot /mnt/target /bin/bash /tmp/scripts/03-cleanup.sh
|
||||||
|
sudo rm -rf /mnt/target/tmp/scripts
|
||||||
|
|
||||||
|
echo "Unmounting filesystems..."
|
||||||
|
sudo umount /mnt/target/sys
|
||||||
|
sudo umount /mnt/target/proc
|
||||||
|
sudo umount /mnt/target/dev/pts
|
||||||
|
sudo umount /mnt/target/dev
|
||||||
|
sudo umount /mnt/target
|
||||||
|
sudo qemu-nbd --disconnect /dev/nbd0
|
||||||
|
|
||||||
|
echo "Compressing and optimizing qcow2 with 2M cluster size..."
|
||||||
|
qemu-img convert -f qcow2 -O qcow2 -o cluster_size=2M -c base.qcow2 output-qemu/com-ermnvldmr-debian-12-k3s-amd64.qcow2
|
||||||
|
echo "Golden image built successfully."
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
import hashlib
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import platform
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
import tarfile
|
||||||
|
import tempfile
|
||||||
|
import urllib.error
|
||||||
|
import urllib.parse
|
||||||
|
import urllib.request
|
||||||
|
import zipfile
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
SERVER='https://git.ermnvldmr.com'
|
||||||
|
|
||||||
|
|
||||||
|
def eligible(run, repository, current_run):
|
||||||
|
if run.get('repository',{}).get('full_name')!=repository:
|
||||||
|
return False
|
||||||
|
if str(run.get('id'))==current_run:
|
||||||
|
return True
|
||||||
|
return run.get('head_branch')=='next' and run.get('event') in ('push','workflow_dispatch') and run.get('status')=='completed' and run.get('conclusion')=='success'
|
||||||
|
|
||||||
|
|
||||||
|
def request(url):
|
||||||
|
if not url.startswith(SERVER+'/'):
|
||||||
|
raise ValueError('Unexpected cache artifact host')
|
||||||
|
class LocalRedirect(urllib.request.HTTPRedirectHandler):
|
||||||
|
def redirect_request(self, req, fp, code, msg, headers, newurl):
|
||||||
|
if not newurl.startswith(SERVER+'/'):
|
||||||
|
raise ValueError('Unexpected cache storage host')
|
||||||
|
return super().redirect_request(req,fp,code,msg,headers,newurl)
|
||||||
|
req=urllib.request.Request(url,headers={'Authorization':'token '+os.environ['CACHE_TOKEN']})
|
||||||
|
return urllib.request.build_opener(LocalRedirect).open(req,timeout=60)
|
||||||
|
|
||||||
|
|
||||||
|
def api(path):
|
||||||
|
with request(SERVER+'/api/v1/repos/'+os.environ['GITHUB_REPOSITORY']+path) as response:
|
||||||
|
return json.load(response)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
store=Path(subprocess.check_output(['pnpm','store','path','--silent'],text=True).strip())
|
||||||
|
archive=Path('.ci/pnpm-store.tar')
|
||||||
|
if sys.argv[1]=='pack':
|
||||||
|
archive.parent.mkdir(exist_ok=True)
|
||||||
|
store.mkdir(parents=True,exist_ok=True)
|
||||||
|
with tarfile.open(archive,'w') as target:target.add(store,arcname='.')
|
||||||
|
return
|
||||||
|
versions=subprocess.check_output(['node','--version'],text=True).strip()+'-'+subprocess.check_output(['pnpm','--version'],text=True).strip()
|
||||||
|
key='pnpm-'+platform.system().lower()+'-'+platform.machine()+'-'+versions+'-'+hashlib.sha256(Path('pnpm-lock.yaml').read_bytes()).hexdigest()
|
||||||
|
with open(os.environ['GITHUB_OUTPUT'],'a') as output:output.write('key='+key+'\n')
|
||||||
|
try:
|
||||||
|
artifacts=api('/actions/artifacts?name='+urllib.parse.quote(key))['artifacts']
|
||||||
|
artifacts.sort(key=lambda a:a['id'],reverse=True)
|
||||||
|
for artifact in artifacts:
|
||||||
|
if artifact.get('expired',True) or artifact.get('name')!=key:
|
||||||
|
continue
|
||||||
|
run_id=artifact.get('workflow_run',{}).get('id')
|
||||||
|
if not run_id:
|
||||||
|
continue
|
||||||
|
run=api('/actions/runs/'+str(run_id))
|
||||||
|
if not eligible(run,os.environ['GITHUB_REPOSITORY'],os.environ['GITHUB_RUN_ID']):
|
||||||
|
continue
|
||||||
|
with tempfile.TemporaryDirectory(prefix='pnpm-artifact-cache-') as directory:
|
||||||
|
downloaded=Path(directory)/'cache.zip'
|
||||||
|
with request(SERVER+'/api/v1/repos/'+os.environ['GITHUB_REPOSITORY']+'/actions/artifacts/'+str(artifact['id'])+'/zip') as response,downloaded.open('wb') as target:
|
||||||
|
while chunk:=response.read(1048576):target.write(chunk)
|
||||||
|
with zipfile.ZipFile(downloaded) as zipped:
|
||||||
|
members=[name for name in zipped.namelist() if name.rsplit('/',1)[-1]=='pnpm-store.tar']
|
||||||
|
if len(members)!=1:
|
||||||
|
raise ValueError('Invalid cache archive')
|
||||||
|
packed=Path(directory)/'store.tar'
|
||||||
|
with zipped.open(members[0]) as source,packed.open('wb') as target:
|
||||||
|
while chunk:=source.read(1048576):target.write(chunk)
|
||||||
|
store.mkdir(parents=True,exist_ok=True)
|
||||||
|
with tarfile.open(packed) as tar:tar.extractall(store,filter='data')
|
||||||
|
print('Restored repository-scoped pnpm cache artifact')
|
||||||
|
return
|
||||||
|
except (urllib.error.HTTPError,urllib.error.URLError,ValueError,tarfile.TarError,zipfile.BadZipFile):
|
||||||
|
print('Cache unavailable; dependencies will be fetched normally')
|
||||||
|
return
|
||||||
|
print('No eligible cache artifact; dependencies will be fetched normally')
|
||||||
|
|
||||||
|
|
||||||
|
if __name__=='__main__':main()
|
||||||
@@ -1,21 +1,79 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
|
MODE="version"
|
||||||
|
SERVICE=""
|
||||||
|
COMMIT="HEAD"
|
||||||
|
EXPLICIT_VERSION=""
|
||||||
|
|
||||||
|
if [ $# -ge 2 ] && [ "$1" = "tag" ]; then
|
||||||
|
MODE="tag"
|
||||||
|
SERVICE="$2"
|
||||||
|
COMMIT="${3:-HEAD}"
|
||||||
|
EXPLICIT_VERSION="${4:-}"
|
||||||
|
elif [ $# -ge 1 ]; then
|
||||||
|
SERVICE="$1"
|
||||||
|
fi
|
||||||
|
|
||||||
YEAR_MONTH=$(date -u +'%Y.%m')
|
YEAR_MONTH=$(date -u +'%Y.%m')
|
||||||
git fetch --tags --quiet 2>/dev/null || true
|
git fetch --tags --quiet 2>/dev/null || true
|
||||||
|
|
||||||
# Find highest MICRO version for current YYYY.MM (matching tags formatted like YYYY.MM.MICRO)
|
if [ -n "$SERVICE" ]; then
|
||||||
LATEST_TAG=$(git tag -l "${YEAR_MONTH}.*" | sort -V | tail -n1 || echo "")
|
PREFIX="services/${SERVICE}-"
|
||||||
|
if [ -n "$EXPLICIT_VERSION" ]; then
|
||||||
if [ -z "$LATEST_TAG" ]; then
|
VERSION="$EXPLICIT_VERSION"
|
||||||
MICRO=0
|
else
|
||||||
|
PATTERN="${PREFIX}${YEAR_MONTH}.*"
|
||||||
|
LATEST_TAG=$(git tag -l "$PATTERN" | sort -V | tail -n1 || echo "")
|
||||||
|
if [ -z "$LATEST_TAG" ]; then
|
||||||
|
MICRO=1
|
||||||
|
else
|
||||||
|
LATEST_MICRO="${LATEST_TAG#"${PREFIX}${YEAR_MONTH}."}"
|
||||||
|
if [[ "$LATEST_MICRO" =~ ^[0-9]+$ ]]; then
|
||||||
|
MICRO=$((LATEST_MICRO + 1))
|
||||||
|
else
|
||||||
|
MICRO=1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
VERSION="${YEAR_MONTH}.${MICRO}"
|
||||||
|
fi
|
||||||
|
TAG_NAME="${PREFIX}${VERSION}"
|
||||||
else
|
else
|
||||||
|
if [ -n "$EXPLICIT_VERSION" ]; then
|
||||||
|
VERSION="$EXPLICIT_VERSION"
|
||||||
|
else
|
||||||
|
PATTERN="${YEAR_MONTH}.*"
|
||||||
|
LATEST_TAG=$(git tag -l "$PATTERN" | sort -V | tail -n1 || echo "")
|
||||||
|
if [ -z "$LATEST_TAG" ]; then
|
||||||
|
MICRO=0
|
||||||
|
else
|
||||||
LATEST_MICRO="${LATEST_TAG#"${YEAR_MONTH}."}"
|
LATEST_MICRO="${LATEST_TAG#"${YEAR_MONTH}."}"
|
||||||
if [[ "$LATEST_MICRO" =~ ^[0-9]+$ ]]; then
|
if [[ "$LATEST_MICRO" =~ ^[0-9]+$ ]]; then
|
||||||
MICRO=$((LATEST_MICRO + 1))
|
MICRO=$((LATEST_MICRO + 1))
|
||||||
else
|
else
|
||||||
MICRO=0
|
MICRO=0
|
||||||
fi
|
fi
|
||||||
|
fi
|
||||||
|
VERSION="${YEAR_MONTH}.${MICRO}"
|
||||||
|
fi
|
||||||
|
TAG_NAME="$VERSION"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "${YEAR_MONTH}.${MICRO}"
|
if [ "$MODE" = "tag" ]; then
|
||||||
|
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
||||||
|
if git rev-parse -q --verify "refs/tags/$TAG_NAME" >/dev/null; then
|
||||||
|
EXISTING_COMMIT=$(git rev-parse "refs/tags/$TAG_NAME")
|
||||||
|
if [ "$EXISTING_COMMIT" = "$(git rev-parse "$COMMIT")" ]; then
|
||||||
|
echo "Tag $TAG_NAME already points to $COMMIT"
|
||||||
|
else
|
||||||
|
echo "Tag $TAG_NAME exists but points to $EXISTING_COMMIT, skipping create"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "Creating tag $TAG_NAME on $COMMIT..."
|
||||||
|
git tag "$TAG_NAME" "$COMMIT"
|
||||||
|
fi
|
||||||
|
echo "Pushing tag $TAG_NAME..."
|
||||||
|
python3 "$ROOT_DIR/ci/scripts/git_write.py" "refs/tags/$TAG_NAME"
|
||||||
|
echo "Successfully created and pushed tag $TAG_NAME"
|
||||||
|
fi
|
||||||
|
echo "$VERSION"
|
||||||
@@ -19,17 +19,25 @@ fi
|
|||||||
|
|
||||||
echo "Updating Kustomize image tag for '$SERVICE' to '$TAG'..."
|
echo "Updating Kustomize image tag for '$SERVICE' to '$TAG'..."
|
||||||
cd "$APP_DIR"
|
cd "$APP_DIR"
|
||||||
kustomize edit set image "ghcr.io/deytenit/ermnvldmr.com/${SERVICE}:${TAG}"
|
IMAGE="git.ermnvldmr.com/deytenit/ermnvldmr.com/${SERVICE}"
|
||||||
|
if [[ "$TAG" =~ ^sha256:[0-9a-f]{64}$ ]]; then
|
||||||
|
kustomize edit set image "${IMAGE}=${IMAGE}@${TAG}"
|
||||||
|
elif [[ "$TAG" =~ ^[A-Za-z0-9_][A-Za-z0-9_.-]{0,127}$ ]]; then
|
||||||
|
kustomize edit set image "${IMAGE}=${IMAGE}:${TAG}"
|
||||||
|
else
|
||||||
|
echo "Invalid image digest or tag" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
cd "$ROOT_DIR"
|
cd "$ROOT_DIR"
|
||||||
git config user.name "adam-at-deytenit"
|
git config user.name "APEX CI"
|
||||||
git config user.email "221188529+adam-at-deytenit@users.noreply.github.com"
|
git config user.email "adam@ermnvldmr.com"
|
||||||
git add "ci/k8s/apps/${SERVICE}/kustomization.yaml"
|
git add "ci/k8s/apps/${SERVICE}/kustomization.yaml"
|
||||||
|
|
||||||
if git diff --staged --quiet; then
|
if git diff --staged --quiet; then
|
||||||
echo "No manifest changes to commit for $SERVICE."
|
echo "No manifest changes to commit for $SERVICE."
|
||||||
else
|
else
|
||||||
git commit -m "chore(release): deploy ${SERVICE} ${TAG} [skip ci]"
|
git commit --no-gpg-sign -m "chore(release): deploy ${SERVICE} ${TAG} [skip ci]"
|
||||||
git push origin next
|
python3 "$ROOT_DIR/ci/scripts/git_write.py" HEAD:next
|
||||||
echo "Successfully deployed $SERVICE ($TAG) via GitOps."
|
echo "Successfully deployed $SERVICE ($TAG) via GitOps."
|
||||||
fi
|
fi
|
||||||
@@ -29,14 +29,23 @@ fi
|
|||||||
|
|
||||||
# Configure AWS region
|
# Configure AWS region
|
||||||
export AWS_DEFAULT_REGION="$AWS_REGION"
|
export AWS_DEFAULT_REGION="$AWS_REGION"
|
||||||
ENDPOINT_URL="$S3_ENDPOINT_URL"
|
ENDPOINT_URL="${S3_ENDPOINT_URL%/}"
|
||||||
|
|
||||||
# Upload all static files
|
# Set S3 max_concurrent_requests to 1 to prevent race conditions on S3-compatible endpoints
|
||||||
|
aws configure set default.s3.max_concurrent_requests 1
|
||||||
|
|
||||||
|
# Upload all static files with retry
|
||||||
echo "Uploading static files..."
|
echo "Uploading static files..."
|
||||||
aws s3 cp "$DIST_DIR/" "s3://$S3_BUCKET/" \
|
for attempt in 1 2 3; do
|
||||||
--recursive \
|
echo "Attempt $attempt/3: syncing static files..."
|
||||||
|
if aws s3 sync "$DIST_DIR/" "s3://$S3_BUCKET/" \
|
||||||
--endpoint-url="$ENDPOINT_URL" \
|
--endpoint-url="$ENDPOINT_URL" \
|
||||||
--cache-control "max-age=300" \
|
--cache-control "max-age=300"; then
|
||||||
--metadata-directive REPLACE
|
echo "Static files deployed successfully!"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
sleep 2
|
||||||
|
done
|
||||||
|
|
||||||
echo "Static files deployed successfully!"
|
echo "Error: Failed to upload static files after 3 attempts."
|
||||||
|
exit 1
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
import json
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
def lines(value):
|
||||||
|
return [line.strip() for line in value.splitlines() if line.strip()]
|
||||||
|
|
||||||
|
|
||||||
|
def output(name, value):
|
||||||
|
with open(os.environ['GITHUB_OUTPUT'], 'a') as stream:
|
||||||
|
stream.write(f'{name}<<GITEA_VALUE\n{value}\nGITEA_VALUE\n')
|
||||||
|
|
||||||
|
|
||||||
|
def metadata(images, rules, sha):
|
||||||
|
result = []
|
||||||
|
for rule in lines(rules):
|
||||||
|
fields = dict(part.split('=', 1) for part in rule.split(',') if '=' in part)
|
||||||
|
if fields.get('enable', 'true').lower() == 'false':
|
||||||
|
continue
|
||||||
|
kind = fields.get('type')
|
||||||
|
if kind == 'sha':
|
||||||
|
tag = 'sha-' + sha[:7]
|
||||||
|
elif kind == 'raw':
|
||||||
|
tag = fields['value']
|
||||||
|
else:
|
||||||
|
raise ValueError('Unsupported metadata rule')
|
||||||
|
if not re.fullmatch(r'[A-Za-z0-9_][A-Za-z0-9_.-]{0,127}', tag):
|
||||||
|
raise ValueError('Invalid image tag')
|
||||||
|
result.extend(image.lower() + ':' + tag for image in lines(images))
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
mode = sys.argv[1]
|
||||||
|
if mode == 'login':
|
||||||
|
subprocess.run(['docker', 'login', os.environ['REGISTRY'], '--username', os.environ['REGISTRY_USER'], '--password-stdin'], input=os.environ['REGISTRY_TOKEN'], text=True, check=True)
|
||||||
|
elif mode == 'metadata':
|
||||||
|
output('tags', '\n'.join(metadata(os.environ['IMAGES'], os.environ['TAG_RULES'], os.environ['SOURCE_SHA'])))
|
||||||
|
output('labels', 'org.opencontainers.image.revision=' + os.environ['SOURCE_SHA'])
|
||||||
|
elif mode == 'build':
|
||||||
|
command = ['docker', 'buildx', 'build', '--metadata-file', '/tmp/image-metadata.json']
|
||||||
|
for env, flag in [('TAGS', '--tag'), ('LABELS', '--label'), ('BUILD_ARGS', '--build-arg')]:
|
||||||
|
for value in lines(os.environ.get(env, '')):
|
||||||
|
command.extend([flag, value])
|
||||||
|
command += ['--label', 'org.opencontainers.image.revision=' + os.environ['SOURCE_SHA'], '--label', 'com.ermnvldmr.ci.run=' + os.environ['RUN_ID']]
|
||||||
|
if os.environ.get('PLATFORMS'):
|
||||||
|
command += ['--platform', os.environ['PLATFORMS']]
|
||||||
|
if os.environ.get('DOCKERFILE'):
|
||||||
|
command += ['--file', os.environ['DOCKERFILE']]
|
||||||
|
if os.environ.get('PUSH', 'false').lower() == 'true':
|
||||||
|
command.append('--push')
|
||||||
|
command.append(os.environ.get('CONTEXT', '.'))
|
||||||
|
subprocess.run(command, check=True)
|
||||||
|
output('digest', json.loads(Path('/tmp/image-metadata.json').read_text())['containerimage.digest'])
|
||||||
|
else:
|
||||||
|
raise ValueError('Unknown docker operation')
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
@@ -0,0 +1,334 @@
|
|||||||
|
import { execFileSync } from 'node:child_process';
|
||||||
|
import {
|
||||||
|
appendFileSync,
|
||||||
|
chmodSync,
|
||||||
|
existsSync,
|
||||||
|
mkdirSync,
|
||||||
|
readFileSync,
|
||||||
|
rmSync,
|
||||||
|
writeFileSync,
|
||||||
|
} from 'node:fs';
|
||||||
|
import { homedir, tmpdir } from 'node:os';
|
||||||
|
import { dirname, join } from 'node:path';
|
||||||
|
import { fileURLToPath } from 'node:url';
|
||||||
|
import { createRequire } from 'node:module';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether a hostname entry exists in the specified hosts file.
|
||||||
|
*
|
||||||
|
* @param {string} domain - Domain to search for
|
||||||
|
* @param {string} hostsPath - Path to hosts file
|
||||||
|
* @returns {boolean} Whether domain is present
|
||||||
|
*/
|
||||||
|
export function hasHostsEntry(domain = 'localhost.ermnvldmr.com', hostsPath = '/etc/hosts') {
|
||||||
|
if (!existsSync(hostsPath)) return false;
|
||||||
|
try {
|
||||||
|
const content = readFileSync(hostsPath, 'utf8');
|
||||||
|
const lines = content.split('\n');
|
||||||
|
for (const line of lines) {
|
||||||
|
const uncommented = (line.split('#')[0] || '').trim();
|
||||||
|
if (!uncommented) continue;
|
||||||
|
const tokens = uncommented.split(/\s+/);
|
||||||
|
const hostnames = tokens.slice(1);
|
||||||
|
if (tokens.length >= 2 && hostnames.some((host) => host === domain)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
} catch {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const DOMAIN_PATTERN = /^[a-zA-Z0-9.-]+$/;
|
||||||
|
const IP_PATTERN = /^[\da-fA-F.:]+$/;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ensures a mapping for the domain exists in /etc/hosts.
|
||||||
|
*
|
||||||
|
* @param {string} domain - Domain to map
|
||||||
|
* @param {string} ip - Target IP address
|
||||||
|
* @param {string} hostsPath - Path to hosts file
|
||||||
|
* @returns {boolean} Whether entry is present
|
||||||
|
*/
|
||||||
|
export function ensureHostsEntry(
|
||||||
|
domain = 'localhost.ermnvldmr.com',
|
||||||
|
ip = '127.0.0.1',
|
||||||
|
hostsPath = '/etc/hosts'
|
||||||
|
) {
|
||||||
|
if (!DOMAIN_PATTERN.test(domain) || !IP_PATTERN.test(ip)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasHostsEntry(domain, hostsPath)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const entry = `${ip} ${domain}`;
|
||||||
|
|
||||||
|
try {
|
||||||
|
appendFileSync(hostsPath, `\n${entry}\n`);
|
||||||
|
console.log(`[hosts] Added "${entry}" to ${hostsPath}`);
|
||||||
|
return true;
|
||||||
|
} catch {
|
||||||
|
// Requires elevated permissions
|
||||||
|
}
|
||||||
|
|
||||||
|
const isInteractive = Boolean(
|
||||||
|
process.stdin && process.stdin.isTTY && process.stdout && process.stdout.isTTY
|
||||||
|
);
|
||||||
|
if (isInteractive) {
|
||||||
|
try {
|
||||||
|
console.log(`[hosts] Adding "${entry}" to ${hostsPath} (requires sudo)...`);
|
||||||
|
execFileSync('sudo', ['tee', '-a', hostsPath], {
|
||||||
|
input: `\n${entry}\n`,
|
||||||
|
stdio: ['pipe', 'ignore', 'inherit'],
|
||||||
|
});
|
||||||
|
console.log(`[hosts] Successfully added "${entry}" to ${hostsPath}`);
|
||||||
|
return true;
|
||||||
|
} catch {
|
||||||
|
console.warn(`[hosts] Could not automatically update ${hostsPath}.`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.warn(
|
||||||
|
`[hosts] Notice: "${entry}" is missing from ${hostsPath}.\nPlease run:\n sudo sh -c 'echo "${entry}" >> ${hostsPath}'`
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Traverses upwards to find the monorepo root containing pnpm-workspace.yaml.
|
||||||
|
*
|
||||||
|
* @param {string} startDir - Directory to start searching from
|
||||||
|
* @returns {string} Absolute path to workspace root
|
||||||
|
*/
|
||||||
|
export function findWorkspaceRoot(startDir = dirname(fileURLToPath(import.meta.url))) {
|
||||||
|
let current = startDir;
|
||||||
|
while (current !== dirname(current)) {
|
||||||
|
if (existsSync(join(current, 'pnpm-workspace.yaml'))) {
|
||||||
|
return current;
|
||||||
|
}
|
||||||
|
current = dirname(current);
|
||||||
|
}
|
||||||
|
return process.cwd();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves the development Root CA private key from the environment or .env.dev.
|
||||||
|
*
|
||||||
|
* @param {string} workspaceRoot - Absolute path to workspace root
|
||||||
|
* @returns {string | undefined} The PEM private key string, or undefined if unavailable
|
||||||
|
*/
|
||||||
|
export function loadDevRootCaKey(workspaceRoot = findWorkspaceRoot()) {
|
||||||
|
if (process.env.COM_ERMNVLDMR_DEV_ROOT_CA_KEY) {
|
||||||
|
const raw = process.env.COM_ERMNVLDMR_DEV_ROOT_CA_KEY;
|
||||||
|
return raw.includes('\\n') ? raw.replace(/\\n/g, '\n') : raw;
|
||||||
|
}
|
||||||
|
|
||||||
|
const envDevPath = join(workspaceRoot, '.env.dev');
|
||||||
|
const envKeysPath = join(workspaceRoot, '.env.keys');
|
||||||
|
|
||||||
|
if (!existsSync(envDevPath)) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
const candidatePackages = [
|
||||||
|
join(workspaceRoot, 'packages/cli/package.json'),
|
||||||
|
join(workspaceRoot, 'package.json'),
|
||||||
|
];
|
||||||
|
|
||||||
|
for (const pkgPath of candidatePackages) {
|
||||||
|
if (!existsSync(pkgPath)) continue;
|
||||||
|
try {
|
||||||
|
const req = createRequire(pkgPath);
|
||||||
|
const dotenvx = req('@dotenvx/dotenvx');
|
||||||
|
if (dotenvx && typeof dotenvx.config === 'function') {
|
||||||
|
dotenvx.config({ path: envDevPath, envKeysFile: envKeysPath });
|
||||||
|
const key = process.env.COM_ERMNVLDMR_DEV_ROOT_CA_KEY;
|
||||||
|
if (key) {
|
||||||
|
return key.includes('\\n') ? key.replace(/\\n/g, '\n') : key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// Continue to next candidate package
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remote public URL for the Ermnvldmr development root CA certificate.
|
||||||
|
*/
|
||||||
|
export const REMOTE_ROOT_CA_URL =
|
||||||
|
'https://static.ermnvldmr.com/dev/ssl/certs/ErmnvldmrDevelopmentRootCA.pem';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ensures valid development certificates exist for localhost.ermnvldmr.com.
|
||||||
|
*
|
||||||
|
* @param {string} workspaceRoot - Absolute path to workspace root
|
||||||
|
* @returns {{ certPath: string, keyPath: string }} Paths to cert and key
|
||||||
|
*/
|
||||||
|
export function ensureDevCertificates(workspaceRoot = findWorkspaceRoot()) {
|
||||||
|
const certsDir = join(workspaceRoot, '.certs');
|
||||||
|
const certPath = join(certsDir, 'localhost.ermnvldmr.com.pem');
|
||||||
|
const keyPath = join(certsDir, 'localhost.ermnvldmr.com-key.pem');
|
||||||
|
const caCertPath = join(certsDir, 'ErmnvldmrDevelopmentRootCA.pem');
|
||||||
|
const caKeyPath = join(certsDir, 'ErmnvldmrDevelopmentRootCA-key.pem');
|
||||||
|
|
||||||
|
ensureHostsEntry('localhost.ermnvldmr.com', '127.0.0.1');
|
||||||
|
|
||||||
|
const home = homedir();
|
||||||
|
const globalCaDir = join(home, '.local/share/mkcert');
|
||||||
|
const globalCaCert = join(globalCaDir, 'ErmnvldmrDevelopmentRootCA.pem');
|
||||||
|
const globalCaKey = join(globalCaDir, 'ErmnvldmrDevelopmentRootCA-key.pem');
|
||||||
|
|
||||||
|
mkdirSync(certsDir, { recursive: true, mode: 0o700 });
|
||||||
|
|
||||||
|
// 1. Sync CA cert from global cache if available, or download from remote static URL
|
||||||
|
if (!existsSync(caCertPath)) {
|
||||||
|
if (existsSync(globalCaCert)) {
|
||||||
|
writeFileSync(caCertPath, readFileSync(globalCaCert));
|
||||||
|
chmodSync(caCertPath, 0o644);
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
execFileSync('curl', ['-sSfL', REMOTE_ROOT_CA_URL, '-o', caCertPath], {
|
||||||
|
stdio: 'ignore',
|
||||||
|
});
|
||||||
|
chmodSync(caCertPath, 0o644);
|
||||||
|
try {
|
||||||
|
mkdirSync(globalCaDir, { recursive: true });
|
||||||
|
writeFileSync(globalCaCert, readFileSync(caCertPath));
|
||||||
|
chmodSync(globalCaCert, 0o644);
|
||||||
|
} catch {
|
||||||
|
// Best-effort global cache
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// Failed to download, will fall back to generation if key also needed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Sync CA key from global cache if available, or decrypt from .env.dev
|
||||||
|
if (!existsSync(caKeyPath)) {
|
||||||
|
if (existsSync(globalCaKey)) {
|
||||||
|
writeFileSync(caKeyPath, readFileSync(globalCaKey));
|
||||||
|
chmodSync(caKeyPath, 0o600);
|
||||||
|
} else {
|
||||||
|
const decryptedKey = loadDevRootCaKey(workspaceRoot);
|
||||||
|
if (decryptedKey) {
|
||||||
|
writeFileSync(caKeyPath, decryptedKey);
|
||||||
|
chmodSync(caKeyPath, 0o600);
|
||||||
|
try {
|
||||||
|
mkdirSync(globalCaDir, { recursive: true });
|
||||||
|
writeFileSync(globalCaKey, decryptedKey);
|
||||||
|
chmodSync(globalCaKey, 0o600);
|
||||||
|
} catch {
|
||||||
|
// Best-effort global cache
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If server cert and CA cert already exist, return them
|
||||||
|
if (existsSync(certPath) && existsSync(keyPath) && existsSync(caCertPath)) {
|
||||||
|
return { certPath, keyPath, caCertPath };
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure ErmnvldmrDevelopmentRootCA exists
|
||||||
|
if (!existsSync(caCertPath) || !existsSync(caKeyPath)) {
|
||||||
|
mkdirSync(globalCaDir, { recursive: true });
|
||||||
|
execFileSync(
|
||||||
|
'openssl',
|
||||||
|
[
|
||||||
|
'req',
|
||||||
|
'-x509',
|
||||||
|
'-nodes',
|
||||||
|
'-newkey',
|
||||||
|
'rsa:3072',
|
||||||
|
'-keyout',
|
||||||
|
caKeyPath,
|
||||||
|
'-out',
|
||||||
|
caCertPath,
|
||||||
|
'-days',
|
||||||
|
'3650',
|
||||||
|
'-subj',
|
||||||
|
'/CN=Ermnvldmr Development Root CA/O=ermnvldmr.com',
|
||||||
|
'-batch',
|
||||||
|
],
|
||||||
|
{ stdio: 'pipe' }
|
||||||
|
);
|
||||||
|
chmodSync(caKeyPath, 0o600);
|
||||||
|
chmodSync(caCertPath, 0o644);
|
||||||
|
|
||||||
|
writeFileSync(globalCaCert, readFileSync(caCertPath));
|
||||||
|
writeFileSync(globalCaKey, readFileSync(caKeyPath));
|
||||||
|
chmodSync(globalCaKey, 0o600);
|
||||||
|
chmodSync(globalCaCert, 0o644);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate server certificate signed by ErmnvldmrDevelopmentRootCA
|
||||||
|
const tempDir = tmpdir();
|
||||||
|
const tempCsr = join(tempDir, `ermnvldmr-dev-${Date.now()}.csr`);
|
||||||
|
const tempExt = join(tempDir, `ermnvldmr-dev-${Date.now()}.cnf`);
|
||||||
|
|
||||||
|
try {
|
||||||
|
writeFileSync(
|
||||||
|
tempExt,
|
||||||
|
'subjectAltName=DNS:localhost.ermnvldmr.com,DNS:*.localhost.ermnvldmr.com,DNS:localhost,IP:127.0.0.1,IP:::1\n'
|
||||||
|
);
|
||||||
|
execFileSync(
|
||||||
|
'openssl',
|
||||||
|
[
|
||||||
|
'req',
|
||||||
|
'-new',
|
||||||
|
'-nodes',
|
||||||
|
'-newkey',
|
||||||
|
'rsa:2048',
|
||||||
|
'-keyout',
|
||||||
|
keyPath,
|
||||||
|
'-out',
|
||||||
|
tempCsr,
|
||||||
|
'-subj',
|
||||||
|
'/CN=localhost.ermnvldmr.com',
|
||||||
|
'-batch',
|
||||||
|
],
|
||||||
|
{ stdio: 'pipe' }
|
||||||
|
);
|
||||||
|
execFileSync(
|
||||||
|
'openssl',
|
||||||
|
[
|
||||||
|
'x509',
|
||||||
|
'-req',
|
||||||
|
'-in',
|
||||||
|
tempCsr,
|
||||||
|
'-CA',
|
||||||
|
caCertPath,
|
||||||
|
'-CAkey',
|
||||||
|
caKeyPath,
|
||||||
|
'-CAcreateserial',
|
||||||
|
'-out',
|
||||||
|
certPath,
|
||||||
|
'-days',
|
||||||
|
'825',
|
||||||
|
'-extfile',
|
||||||
|
tempExt,
|
||||||
|
],
|
||||||
|
{ stdio: 'pipe' }
|
||||||
|
);
|
||||||
|
chmodSync(keyPath, 0o600);
|
||||||
|
chmodSync(certPath, 0o644);
|
||||||
|
} finally {
|
||||||
|
rmSync(tempCsr, { force: true });
|
||||||
|
rmSync(tempExt, { force: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
return { certPath, keyPath, caCertPath };
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run if called directly
|
||||||
|
if (process.argv[1] && process.argv[1].endsWith('ensure-dev-certs.mjs')) {
|
||||||
|
const { certPath, keyPath } = ensureDevCertificates();
|
||||||
|
console.log(`[certs] Ready:\n Cert: ${certPath}\n Key: ${keyPath}`);
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
import os
|
||||||
|
import re
|
||||||
|
import shlex
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
import tempfile
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
ref=sys.argv[1]
|
||||||
|
if ref not in ('HEAD:next','trunk') and not re.fullmatch(r'refs/tags/[A-Za-z0-9][A-Za-z0-9._-]*(/[A-Za-z0-9][A-Za-z0-9._-]*)*',ref):
|
||||||
|
raise ValueError('Unexpected publication ref')
|
||||||
|
repository=os.environ['GITHUB_REPOSITORY']
|
||||||
|
if not re.fullmatch(r'deytenit/[A-Za-z0-9_.-]+',repository):
|
||||||
|
raise ValueError('Unexpected repository owner')
|
||||||
|
with tempfile.TemporaryDirectory(prefix='gitea-write-key-') as directory:
|
||||||
|
key = Path(directory) / 'key'
|
||||||
|
key.write_text(os.environ['GIT_WRITE_KEY'])
|
||||||
|
key.chmod(0o600)
|
||||||
|
repo_root = Path(__file__).resolve().parents[2]
|
||||||
|
candidates = [
|
||||||
|
repo_root / '.gitea' / 'known_hosts',
|
||||||
|
repo_root / 'ci' / 'known_hosts',
|
||||||
|
Path(__file__).resolve().parent.parent / '.gitea' / 'known_hosts',
|
||||||
|
Path(__file__).resolve().parent.parent / 'known_hosts',
|
||||||
|
]
|
||||||
|
known = next((c for c in candidates if c.exists()), None)
|
||||||
|
if not known:
|
||||||
|
raise FileNotFoundError(f'Could not find known_hosts in {[str(c) for c in candidates]}')
|
||||||
|
env = dict(os.environ)
|
||||||
|
env.pop('GIT_WRITE_KEY', None)
|
||||||
|
env['GIT_SSH_COMMAND'] = shlex.join([
|
||||||
|
'ssh', '-T', '-i', str(key),
|
||||||
|
'-o', 'BatchMode=yes',
|
||||||
|
'-o', 'ConnectTimeout=15',
|
||||||
|
'-o', 'HostName=45.150.33.239',
|
||||||
|
'-o', 'IdentitiesOnly=yes',
|
||||||
|
'-o', 'StrictHostKeyChecking=yes',
|
||||||
|
'-o', 'HostKeyAlgorithms=ssh-ed25519',
|
||||||
|
'-o', f'UserKnownHostsFile={known}',
|
||||||
|
])
|
||||||
|
subprocess.run(['git', 'push', f'ssh://git@git.ermnvldmr.com:22222/{repository}.git', ref], env=env, check=True)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__=='__main__':main()
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
set -e
|
set -e
|
||||||
|
|
||||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
STATIC_DIR="$SCRIPT_DIR/../../services/www/public/static"
|
STATIC_DIR="${1:-$SCRIPT_DIR/../../services/www/public/static}"
|
||||||
|
|
||||||
if [ ! -d "$STATIC_DIR" ]; then
|
if [ ! -d "$STATIC_DIR" ]; then
|
||||||
echo "Directory $STATIC_DIR does not exist. Skipping."
|
echo "Directory $STATIC_DIR does not exist. Skipping."
|
||||||
|
|||||||
@@ -0,0 +1,161 @@
|
|||||||
|
import json
|
||||||
|
import base64
|
||||||
|
import io
|
||||||
|
import zipfile
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import subprocess
|
||||||
|
import urllib.request
|
||||||
|
|
||||||
|
SERVER = 'https://git.ermnvldmr.com'
|
||||||
|
REPO = 'deytenit/ermnvldmr.com'
|
||||||
|
IMAGE = SERVER.removeprefix('https://') + '/' + REPO + '/www'
|
||||||
|
|
||||||
|
|
||||||
|
def validate_input(sha, digest, run_id):
|
||||||
|
if not re.fullmatch(r'[0-9a-f]{40}', sha):
|
||||||
|
raise ValueError(f'Full source SHA required: {sha}')
|
||||||
|
if not re.fullmatch(r'sha256:[0-9a-f]{64}', digest):
|
||||||
|
raise ValueError(f'OCI sha256 digest required: {digest}')
|
||||||
|
if not re.fullmatch(r'[1-9][0-9]*', str(run_id)):
|
||||||
|
raise ValueError(f'Numeric build run ID required: {run_id}')
|
||||||
|
|
||||||
|
|
||||||
|
def validate_run(run, sha):
|
||||||
|
expected = {'head_sha': sha, 'head_branch': 'next', 'status': 'completed', 'conclusion': 'success'}
|
||||||
|
if any(run.get(key) != value for key, value in expected.items()):
|
||||||
|
raise ValueError('Build did not succeed for this next commit')
|
||||||
|
if run.get('repository', {}).get('full_name') != REPO or (run.get('head_repository') and run['head_repository'].get('full_name') != REPO):
|
||||||
|
raise ValueError('Build source repository mismatch')
|
||||||
|
if run.get('path') != 'services-www-next-required.yml@refs/heads/next':
|
||||||
|
raise ValueError('Wrong build workflow')
|
||||||
|
if run.get('event') not in ('push', 'workflow_dispatch'):
|
||||||
|
raise ValueError('Untrusted build event')
|
||||||
|
|
||||||
|
|
||||||
|
def api(path):
|
||||||
|
req = urllib.request.Request(SERVER + '/api/v1/repos/' + REPO + path, headers={'Authorization': 'token ' + os.environ['PROVENANCE_TOKEN']})
|
||||||
|
with urllib.request.urlopen(req, timeout=30) as response:
|
||||||
|
return json.load(response)
|
||||||
|
|
||||||
|
|
||||||
|
def validate_labels(labels, sha, run_id):
|
||||||
|
if labels.get('org.opencontainers.image.revision') != sha or labels.get('com.ermnvldmr.ci.run') != str(run_id):
|
||||||
|
raise ValueError('Immutable image provenance mismatch')
|
||||||
|
|
||||||
|
|
||||||
|
def validate_manifest(manifest, sha, digest, run_id):
|
||||||
|
expected = {'sha': sha, 'digest': digest, 'run_id': str(run_id), 'repository': REPO}
|
||||||
|
if any(str(manifest.get(k)) != str(v) for k, v in expected.items()):
|
||||||
|
raise ValueError(f'Build artifact does not attest requested image digest: got {manifest}, expected {expected}')
|
||||||
|
|
||||||
|
|
||||||
|
def artifact_manifest(run_id, name='www-provenance', filename='www-provenance.json'):
|
||||||
|
artifacts = api('/actions/runs/' + str(run_id) + '/artifacts')['artifacts']
|
||||||
|
matching = [a for a in artifacts if a.get('name') == name and not a.get('expired', True)]
|
||||||
|
if len(matching) != 1:
|
||||||
|
raise ValueError(f'Exactly one unexpired build provenance artifact required for {name} on run {run_id}, found {len(matching)}')
|
||||||
|
class SameHostRedirect(urllib.request.HTTPRedirectHandler):
|
||||||
|
def redirect_request(self, req, fp, code, msg, headers, newurl):
|
||||||
|
if not newurl.startswith(SERVER + '/'):
|
||||||
|
raise ValueError('Unexpected artifact storage host')
|
||||||
|
return super().redirect_request(req, fp, code, msg, headers, newurl)
|
||||||
|
request = urllib.request.Request(SERVER + '/api/v1/repos/' + REPO + '/actions/artifacts/' + str(matching[0]['id']) + '/zip', headers={'Authorization': 'token ' + os.environ['PROVENANCE_TOKEN']})
|
||||||
|
with urllib.request.build_opener(SameHostRedirect).open(request, timeout=30) as response:
|
||||||
|
payload = response.read(1024 * 1024 + 1)
|
||||||
|
if len(payload) > 1024 * 1024:
|
||||||
|
raise ValueError('Unexpected provenance artifact size')
|
||||||
|
with zipfile.ZipFile(io.BytesIO(payload)) as archive:
|
||||||
|
members = [name for name in archive.namelist() if name.rsplit('/', 1)[-1] == filename]
|
||||||
|
if len(members) != 1:
|
||||||
|
raise ValueError('Missing or ambiguous provenance manifest')
|
||||||
|
if archive.getinfo(members[0]).file_size > 65536:
|
||||||
|
raise ValueError('Unexpected provenance document size')
|
||||||
|
return json.loads(archive.read(members[0]))
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
sha = os.environ.get('TESTED_SHA', '').strip()
|
||||||
|
digest = os.environ.get('TESTED_DIGEST', '').strip()
|
||||||
|
run_id = os.environ.get('BUILD_RUN_ID', '').strip()
|
||||||
|
release_id = os.environ.get('RELEASE_RUN_ID', '').strip()
|
||||||
|
release_tag = os.environ.get('RELEASE_TAG', '').strip()
|
||||||
|
is_deploy = os.environ.get('IS_DEPLOY', 'false').lower() == 'true' or bool(release_id or release_tag)
|
||||||
|
|
||||||
|
current = api('/actions/runs/' + os.environ['GITHUB_RUN_ID'])
|
||||||
|
if current.get('event') != 'workflow_dispatch' or current.get('head_branch') != 'next':
|
||||||
|
raise ValueError('Approval must be manually dispatched on protected next')
|
||||||
|
actor = current.get('trigger_actor') or current.get('actor') or {}
|
||||||
|
if actor.get('login') != 'deytenit':
|
||||||
|
raise ValueError('Only the repository owner may approve promotion')
|
||||||
|
if not api('/branches/next').get('protected'):
|
||||||
|
raise ValueError('The next branch must be protected before promotion')
|
||||||
|
|
||||||
|
if is_deploy:
|
||||||
|
if not release_id:
|
||||||
|
runs_data = api('/actions/workflows/services-www-release-manual.yml/runs?branch=next&limit=10')
|
||||||
|
candidates = [
|
||||||
|
r for r in runs_data.get('workflow_runs', [])
|
||||||
|
if r.get('status') == 'completed' and r.get('conclusion') == 'success'
|
||||||
|
]
|
||||||
|
if not candidates:
|
||||||
|
raise ValueError('No successful completed run found for services-www-release-manual.yml on next')
|
||||||
|
release_id = str(candidates[0]['id'])
|
||||||
|
|
||||||
|
release = api('/actions/runs/' + release_id)
|
||||||
|
release_actor = release.get('trigger_actor') or release.get('actor') or {}
|
||||||
|
if release.get('conclusion') != 'success' or release.get('status') != 'completed' or release.get('event') != 'workflow_dispatch' or release.get('head_branch') != 'next' or release.get('path') != 'services-www-release-manual.yml@refs/heads/next' or release_actor.get('login') != 'deytenit':
|
||||||
|
raise ValueError('Successful independently approved release required')
|
||||||
|
|
||||||
|
rel_manifest = artifact_manifest(release_id, 'www-release-provenance', 'www-release.json')
|
||||||
|
if not release_tag:
|
||||||
|
release_tag = rel_manifest['release_tag']
|
||||||
|
if not sha:
|
||||||
|
sha = rel_manifest['sha']
|
||||||
|
if not digest:
|
||||||
|
digest = rel_manifest['digest']
|
||||||
|
if not run_id:
|
||||||
|
run_id = str(rel_manifest['run_id'])
|
||||||
|
|
||||||
|
expected_rel = {'sha': sha, 'digest': digest, 'run_id': str(run_id), 'repository': REPO, 'release_tag': release_tag}
|
||||||
|
if any(str(rel_manifest.get(k)) != str(v) for k, v in expected_rel.items()):
|
||||||
|
raise ValueError(f'Release approval does not match requested artifact: got {rel_manifest}, expected {expected_rel}')
|
||||||
|
else:
|
||||||
|
if not sha or not digest or not run_id:
|
||||||
|
runs_data = api('/actions/workflows/services-www-next-required.yml/runs?branch=next&limit=10')
|
||||||
|
candidates = [
|
||||||
|
r for r in runs_data.get('workflow_runs', [])
|
||||||
|
if r.get('status') == 'completed' and r.get('conclusion') == 'success'
|
||||||
|
]
|
||||||
|
if not candidates:
|
||||||
|
raise ValueError('No successful completed run found for services-www-next-required.yml on next')
|
||||||
|
build_run = candidates[0]
|
||||||
|
run_id = str(build_run['id'])
|
||||||
|
sha = build_run['head_sha']
|
||||||
|
build_manifest = artifact_manifest(run_id, 'www-provenance', 'www-provenance.json')
|
||||||
|
digest = build_manifest['digest']
|
||||||
|
|
||||||
|
validate_input(sha, digest, run_id)
|
||||||
|
validate_run(api('/actions/runs/' + run_id), sha)
|
||||||
|
validate_manifest(artifact_manifest(run_id), sha, digest, run_id)
|
||||||
|
|
||||||
|
auth = base64.b64encode(('deytenit:' + os.environ['PROVENANCE_TOKEN']).encode()).decode()
|
||||||
|
subprocess.run(['git', '-c', 'http.https://git.ermnvldmr.com/.extraheader=AUTHORIZATION: basic ' + auth, 'fetch', 'origin', 'next'], check=True)
|
||||||
|
subprocess.run(['git', 'merge-base', '--is-ancestor', sha, 'origin/next'], check=True)
|
||||||
|
subprocess.run(['docker', 'pull', IMAGE + '@' + digest], check=True)
|
||||||
|
data = json.loads(subprocess.check_output(['docker', 'image', 'inspect', IMAGE + '@' + digest], text=True))
|
||||||
|
validate_labels(data[0]['Config'].get('Labels') or {}, sha, run_id)
|
||||||
|
|
||||||
|
with open(os.environ['GITHUB_OUTPUT'], 'a') as stream:
|
||||||
|
stream.write(f'short_sha=sha-{sha[:7]}\n')
|
||||||
|
stream.write(f'tested_sha={sha}\n')
|
||||||
|
stream.write(f'tested_digest={digest}\n')
|
||||||
|
stream.write(f'build_run_id={run_id}\n')
|
||||||
|
if release_tag:
|
||||||
|
stream.write(f'release_tag={release_tag}\n')
|
||||||
|
if release_id:
|
||||||
|
stream.write(f'release_run_id={release_id}\n')
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
Executable
+35
@@ -0,0 +1,35 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
PNPM_VERSION="${1:-9.12.3}"
|
||||||
|
NODE_VERSION="${2:-20}"
|
||||||
|
|
||||||
|
# Configure pnpm
|
||||||
|
case "$PNPM_VERSION" in
|
||||||
|
8|9|9.12.3) ;;
|
||||||
|
*) echo "Unsupported pnpm version: $PNPM_VERSION" >&2; exit 1 ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
PNPM_BIN="/opt/ci/pnpm/$PNPM_VERSION/bin"
|
||||||
|
if [ -d "$PNPM_BIN" ]; then
|
||||||
|
if [ -n "${GITHUB_PATH:-}" ]; then
|
||||||
|
echo "$PNPM_BIN" >> "$GITHUB_PATH"
|
||||||
|
fi
|
||||||
|
export PATH="$PNPM_BIN:$PATH"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Configure Node.js
|
||||||
|
case "$NODE_VERSION" in
|
||||||
|
18*) major=18 ;;
|
||||||
|
20*) major=20 ;;
|
||||||
|
22*) major=22 ;;
|
||||||
|
*) echo "Unsupported node version: $NODE_VERSION" >&2; exit 1 ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
NODE_BIN="/opt/ci/node/$major/bin"
|
||||||
|
if [ -d "$NODE_BIN" ]; then
|
||||||
|
if [ -n "${GITHUB_PATH:-}" ]; then
|
||||||
|
echo "$NODE_BIN" >> "$GITHUB_PATH"
|
||||||
|
fi
|
||||||
|
export PATH="$NODE_BIN:$PATH"
|
||||||
|
fi
|
||||||
Executable
+130
@@ -0,0 +1,130 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# ==============================================================================
|
||||||
|
# End-to-End QEMU Verification Script for Golden Image & Cloud-Init User-Data
|
||||||
|
# ==============================================================================
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
IMAGE_PATH="${1:-output-qemu/com-ermnvldmr-debian-12-k3s-amd64.qcow2}"
|
||||||
|
USER_DATA="${2:-ci/cloud-init/user-data.yaml}"
|
||||||
|
SSH_KEY="${3:-$HOME/.ssh/adam@ermnvldmr.com:ed25519}"
|
||||||
|
SSH_PORT="${4:-22222}"
|
||||||
|
|
||||||
|
if [ ! -f "$IMAGE_PATH" ]; then
|
||||||
|
echo "[-] Golden image not found at: $IMAGE_PATH"
|
||||||
|
echo " Build it first using: packer build -var 'accelerator=kvm' ci/packer/debian-12-k3s.pkr.hcl"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -f "$USER_DATA" ]; then
|
||||||
|
echo "[-] User-data file not found at: $USER_DATA"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -f "$SSH_KEY" ]; then
|
||||||
|
echo "[-] SSH private key not found at: $SSH_KEY"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Ensure prerequisite tools exist
|
||||||
|
for cmd in qemu-system-x86_64 qemu-img genisoimage ssh; do
|
||||||
|
if ! command -v "$cmd" &>/dev/null; then
|
||||||
|
echo "[-] Required command not found in PATH: $cmd"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
TMPDIR=$(mktemp -d /tmp/qemu-test-k3s-XXXXXX)
|
||||||
|
echo "=== [QEMU Test] Workdir: $TMPDIR ==="
|
||||||
|
|
||||||
|
QEMU_PID=""
|
||||||
|
cleanup() {
|
||||||
|
echo "=== [QEMU Test] Cleaning up resources ==="
|
||||||
|
if [ -n "$QEMU_PID" ] && kill -0 "$QEMU_PID" 2>/dev/null; then
|
||||||
|
echo "Stopping QEMU process (PID: $QEMU_PID)..."
|
||||||
|
kill "$QEMU_PID" 2>/dev/null || true
|
||||||
|
wait "$QEMU_PID" 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
rm -rf "$TMPDIR"
|
||||||
|
echo "=== [QEMU Test] Cleanup complete ==="
|
||||||
|
}
|
||||||
|
trap cleanup EXIT
|
||||||
|
|
||||||
|
echo "=== [QEMU Test] 1. Preparing Cloud-Init cidata ISO ==="
|
||||||
|
cp "$USER_DATA" "$TMPDIR/user-data"
|
||||||
|
cat << 'EOF' > "$TMPDIR/meta-data"
|
||||||
|
instance-id: qemu-test-vm-01
|
||||||
|
local-hostname: com-ermnvldmr
|
||||||
|
EOF
|
||||||
|
|
||||||
|
genisoimage -output "$TMPDIR/cidata.iso" -volid cidata -joliet -rock "$TMPDIR/user-data" "$TMPDIR/meta-data" 2>/dev/null
|
||||||
|
|
||||||
|
echo "=== [QEMU Test] 2. Creating Ephemeral Disks ==="
|
||||||
|
# CoW overlay for root OS disk (preserves original golden image intact)
|
||||||
|
qemu-img create -f qcow2 -b "$(realpath "$IMAGE_PATH")" -F qcow2 "$TMPDIR/test-os.qcow2" 20G >/dev/null
|
||||||
|
# Secondary data disk (/dev/vdb) to test persistent storage auto-mounting
|
||||||
|
qemu-img create -f qcow2 "$TMPDIR/test-vdb.qcow2" 10G >/dev/null
|
||||||
|
|
||||||
|
echo "=== [QEMU Test] 3. Launching VM in QEMU (KVM accelerated) ==="
|
||||||
|
qemu-system-x86_64 \
|
||||||
|
-enable-kvm \
|
||||||
|
-m 4096 \
|
||||||
|
-smp 2 \
|
||||||
|
-drive file="$TMPDIR/test-os.qcow2",if=virtio,format=qcow2 \
|
||||||
|
-drive file="$TMPDIR/test-vdb.qcow2",if=virtio,format=qcow2 \
|
||||||
|
-drive file="$TMPDIR/cidata.iso",if=virtio,format=raw \
|
||||||
|
-netdev user,id=net0,hostfwd=tcp::${SSH_PORT}-:22 \
|
||||||
|
-device virtio-net,netdev=net0 \
|
||||||
|
-nographic \
|
||||||
|
-serial file:"$TMPDIR/serial.log" &
|
||||||
|
QEMU_PID=$!
|
||||||
|
|
||||||
|
echo "QEMU started with PID $QEMU_PID. Forwarding guest SSH to localhost:$SSH_PORT"
|
||||||
|
|
||||||
|
echo "=== [QEMU Test] 4. Waiting for SSH Availability (up to 120s) ==="
|
||||||
|
MAX_WAIT=120
|
||||||
|
WAIT_COUNT=0
|
||||||
|
SSH_OPTS=(-i "$SSH_KEY" -p "$SSH_PORT" -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ConnectTimeout=3 -o BatchMode=yes)
|
||||||
|
|
||||||
|
until ssh "${SSH_OPTS[@]}" adam@127.0.0.1 "echo ssh_ready" 2>/dev/null; do
|
||||||
|
sleep 3
|
||||||
|
WAIT_COUNT=$((WAIT_COUNT + 3))
|
||||||
|
if [ "$WAIT_COUNT" -ge "$MAX_WAIT" ]; then
|
||||||
|
echo "[-] Timed out waiting for SSH on localhost:$SSH_PORT!"
|
||||||
|
echo "--- Last 50 lines of serial console log ---"
|
||||||
|
tail -n 50 "$TMPDIR/serial.log" || true
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
echo "[+] SSH connection established!"
|
||||||
|
|
||||||
|
echo "=== [QEMU Test] 5. Waiting for Cloud-Init Completion ==="
|
||||||
|
ssh "${SSH_OPTS[@]}" adam@127.0.0.1 "sudo cloud-init status --wait"
|
||||||
|
|
||||||
|
echo "=== [QEMU Test] 6. Verifying System Assertions ==="
|
||||||
|
|
||||||
|
# Check Hostname
|
||||||
|
HOSTNAME_ACTUAL=$(ssh "${SSH_OPTS[@]}" adam@127.0.0.1 "hostname")
|
||||||
|
echo "Hostname: $HOSTNAME_ACTUAL (Expected: com-ermnvldmr)"
|
||||||
|
[ "$HOSTNAME_ACTUAL" = "com-ermnvldmr" ]
|
||||||
|
|
||||||
|
# Check Secondary Disk Mount
|
||||||
|
MOUNT_CHECK=$(ssh "${SSH_OPTS[@]}" adam@127.0.0.1 "grep -qs '/var/lib/rancher/k3s/storage' /proc/mounts && echo MOUNTED || echo NOT_MOUNTED")
|
||||||
|
echo "Secondary disk mount: $MOUNT_CHECK"
|
||||||
|
[ "$MOUNT_CHECK" = "MOUNTED" ]
|
||||||
|
|
||||||
|
# Check K3s Node Status
|
||||||
|
NODE_STATUS=$(ssh "${SSH_OPTS[@]}" adam@127.0.0.1 "kubectl get nodes -o jsonpath='{.items[0].status.conditions[?(@.type==\"Ready\")].status}'")
|
||||||
|
echo "K3s Node Ready Status: $NODE_STATUS"
|
||||||
|
[ "$NODE_STATUS" = "True" ]
|
||||||
|
|
||||||
|
# Check Non-root Kubectl access
|
||||||
|
echo "Checking non-root kubectl execution without sudo:"
|
||||||
|
ssh "${SSH_OPTS[@]}" adam@127.0.0.1 "kubectl get nodes -o wide"
|
||||||
|
|
||||||
|
# Check Flux namespace and Age secret
|
||||||
|
echo "Checking Flux namespace and SOPS Age secret:"
|
||||||
|
ssh "${SSH_OPTS[@]}" adam@127.0.0.1 "kubectl get secret sops-age -n flux-system"
|
||||||
|
|
||||||
|
echo "=========================================================================="
|
||||||
|
echo " [SUCCESS] All Golden Image & Cloud-Init Assertions Passed in QEMU!"
|
||||||
|
echo "=========================================================================="
|
||||||
Executable
+16
@@ -0,0 +1,16 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
IMAGE_NAME="${1:-com-ermnvldmr-debian-12-k3s-amd64.qcow2}"
|
||||||
|
mv output-qemu/com-ermnvldmr-debian-12-k3s-amd64.qcow2 "output-qemu/${IMAGE_NAME}"
|
||||||
|
|
||||||
|
if [ -n "${S3_BUCKET:-}" ] && [ -n "${AWS_ACCESS_KEY_ID:-}" ]; then
|
||||||
|
ENDPOINT_FLAG=""
|
||||||
|
[ -n "${S3_ENDPOINT:-}" ] && ENDPOINT_FLAG="--endpoint-url=${S3_ENDPOINT}"
|
||||||
|
echo "Cleaning up older images in dev/images/ to free bucket storage..."
|
||||||
|
aws ${ENDPOINT_FLAG} s3 rm "s3://${S3_BUCKET}/dev/images/" --recursive --exclude "*" --include "com-ermnvldmr-debian-12-k3s-*.qcow2" || true
|
||||||
|
aws ${ENDPOINT_FLAG} s3 cp "output-qemu/${IMAGE_NAME}" "s3://${S3_BUCKET}/dev/images/${IMAGE_NAME}"
|
||||||
|
echo "Golden image uploaded to s3://${S3_BUCKET}/dev/images/${IMAGE_NAME}"
|
||||||
|
else
|
||||||
|
echo "S3 storage secrets not provided; skipping remote S3 upload. Image artifact is preserved in workflow run artifacts."
|
||||||
|
fi
|
||||||
-53
@@ -1,53 +0,0 @@
|
|||||||
codecov:
|
|
||||||
notify:
|
|
||||||
wait_for_ci: true
|
|
||||||
|
|
||||||
ignore:
|
|
||||||
- 'packages/eslint-config'
|
|
||||||
- 'packages/rsbuild-config'
|
|
||||||
- 'packages/storybook-config'
|
|
||||||
|
|
||||||
coverage:
|
|
||||||
status:
|
|
||||||
project:
|
|
||||||
default:
|
|
||||||
target: 80%
|
|
||||||
threshold: 1%
|
|
||||||
range: 10%
|
|
||||||
stl:
|
|
||||||
target: 80%
|
|
||||||
flags:
|
|
||||||
- stl
|
|
||||||
ui:
|
|
||||||
target: 80%
|
|
||||||
flags:
|
|
||||||
- ui
|
|
||||||
ui-storybook:
|
|
||||||
target: 80%
|
|
||||||
flags:
|
|
||||||
- ui-storybook
|
|
||||||
www:
|
|
||||||
target: 80%
|
|
||||||
flags:
|
|
||||||
- www
|
|
||||||
www-storybook:
|
|
||||||
target: 80%
|
|
||||||
flags:
|
|
||||||
- www-storybook
|
|
||||||
|
|
||||||
flags:
|
|
||||||
stl:
|
|
||||||
paths:
|
|
||||||
- packages/stl
|
|
||||||
ui:
|
|
||||||
paths:
|
|
||||||
- packages/ui
|
|
||||||
ui-storybook:
|
|
||||||
paths:
|
|
||||||
- packages/ui
|
|
||||||
www:
|
|
||||||
paths:
|
|
||||||
- services/www
|
|
||||||
www-storybook:
|
|
||||||
paths:
|
|
||||||
- services/www
|
|
||||||
+4
-1
@@ -14,7 +14,10 @@ export default [
|
|||||||
// Additional ignores for monorepo
|
// Additional ignores for monorepo
|
||||||
{
|
{
|
||||||
ignores: [
|
ignores: [
|
||||||
'services/docs/**/*', // Hugo content, no linting needed
|
'services/docs/public/**',
|
||||||
|
'services/docs/resources/**',
|
||||||
|
'services/docs/assets/**',
|
||||||
|
'services/docs/archetypes/**',
|
||||||
'**/node_modules/**',
|
'**/node_modules/**',
|
||||||
'**/dist/**',
|
'**/dist/**',
|
||||||
'**/build/**',
|
'**/build/**',
|
||||||
|
|||||||
@@ -32,6 +32,7 @@
|
|||||||
"www:storybook": "pnpm --filter @ermnvldmr/www storybook",
|
"www:storybook": "pnpm --filter @ermnvldmr/www storybook",
|
||||||
"docs:dev": "pnpm --filter @ermnvldmr/docs dev",
|
"docs:dev": "pnpm --filter @ermnvldmr/docs dev",
|
||||||
"docs:build": "pnpm --filter @ermnvldmr/docs build",
|
"docs:build": "pnpm --filter @ermnvldmr/docs build",
|
||||||
|
"docs:sync:static": "pnpm --filter @ermnvldmr/docs sync:static",
|
||||||
"static:dev": "pnpm --filter @ermnvldmr/static dev",
|
"static:dev": "pnpm --filter @ermnvldmr/static dev",
|
||||||
"static:build": "pnpm --filter @ermnvldmr/static build",
|
"static:build": "pnpm --filter @ermnvldmr/static build",
|
||||||
"static:lint": "pnpm --filter @ermnvldmr/static lint",
|
"static:lint": "pnpm --filter @ermnvldmr/static lint",
|
||||||
@@ -41,6 +42,7 @@
|
|||||||
"dev:www": "pnpm ui:build && pnpm kits:build && pnpm www:dev",
|
"dev:www": "pnpm ui:build && pnpm kits:build && pnpm www:dev",
|
||||||
"dev:static": "pnpm ui:build && pnpm kits:build && pnpm static:dev",
|
"dev:static": "pnpm ui:build && pnpm kits:build && pnpm static:dev",
|
||||||
"dev:docs": "pnpm docs:dev",
|
"dev:docs": "pnpm docs:dev",
|
||||||
|
"dev:certs": "node ci/scripts/ensure-dev-certs.mjs",
|
||||||
"build": "pnpm ui:build && pnpm --filter @ermnvldmr/kits build && pnpm -r --filter='./services/*' build",
|
"build": "pnpm ui:build && pnpm --filter @ermnvldmr/kits build && pnpm -r --filter='./services/*' build",
|
||||||
"build:storybooks": "pnpm ui:build && pnpm --filter @ermnvldmr/kits build && pnpm --filter @ermnvldmr/ui build-storybook && pnpm --filter @ermnvldmr/kits build-storybook && pnpm --filter @ermnvldmr/www build-storybook",
|
"build:storybooks": "pnpm ui:build && pnpm --filter @ermnvldmr/kits build && pnpm --filter @ermnvldmr/ui build-storybook && pnpm --filter @ermnvldmr/kits build-storybook && pnpm --filter @ermnvldmr/www build-storybook",
|
||||||
"lint": "pnpm -r lint",
|
"lint": "pnpm -r lint",
|
||||||
|
|||||||
@@ -40,6 +40,6 @@
|
|||||||
"@types/node": "^22.13.0",
|
"@types/node": "^22.13.0",
|
||||||
"sharp": "^0.35.2",
|
"sharp": "^0.35.2",
|
||||||
"typescript": "^5.8.2",
|
"typescript": "^5.8.2",
|
||||||
"vitest": "^4.0.18"
|
"vitest": "^4.1.11"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -297,4 +297,112 @@ describe('runS3Sync', () => {
|
|||||||
const commandInstance = mockSend.mock.calls[0][0];
|
const commandInstance = mockSend.mock.calls[0][0];
|
||||||
expect(commandInstance.input.Key).toBe('test/logo.webp');
|
expect(commandInstance.input.Key).toBe('test/logo.webp');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should support custom sourceFilesPattern and urlPrefixes for docs', async () => {
|
||||||
|
const staticDir = path.join(tempDir, 'static');
|
||||||
|
fs.mkdirSync(staticDir, { recursive: true });
|
||||||
|
|
||||||
|
fs.writeFileSync(path.join(staticDir, 'banner.png'), 'png-content');
|
||||||
|
fs.writeFileSync(path.join(staticDir, 'banner.webp'), 'webp-content');
|
||||||
|
|
||||||
|
const contentDir = path.join(tempDir, 'content');
|
||||||
|
fs.mkdirSync(contentDir, { recursive: true });
|
||||||
|
const docPath = path.join(contentDir, 'index.md');
|
||||||
|
fs.writeFileSync(docPath, '');
|
||||||
|
|
||||||
|
const cmd: S3SyncCommandConfig = {
|
||||||
|
name: 'sync',
|
||||||
|
description: 'desc',
|
||||||
|
targetPrefix: 'docs',
|
||||||
|
sourceDir: './static',
|
||||||
|
sourceFilesPattern: 'content/**/*.md',
|
||||||
|
urlPrefixes: ['/images/'],
|
||||||
|
type: 's3-sync',
|
||||||
|
};
|
||||||
|
|
||||||
|
await runS3Sync(cmd, {});
|
||||||
|
|
||||||
|
const content = fs.readFileSync(docPath, 'utf-8');
|
||||||
|
expect(content).toContain('https://s3.example.com/my-bucket/docs/banner.webp');
|
||||||
|
expect(content).not.toContain('/images/banner.png');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should use custom domain directly if bucket contains a dot', async () => {
|
||||||
|
const staticDir = path.join(tempDir, 'static');
|
||||||
|
fs.mkdirSync(staticDir, { recursive: true });
|
||||||
|
fs.writeFileSync(path.join(staticDir, 'img.webp'), 'webp-content');
|
||||||
|
|
||||||
|
const srcDir = path.join(tempDir, 'src');
|
||||||
|
fs.mkdirSync(srcDir, { recursive: true });
|
||||||
|
const srcPath = path.join(srcDir, 'index.ts');
|
||||||
|
fs.writeFileSync(srcPath, 'const img = "/static/img.webp";');
|
||||||
|
|
||||||
|
const cmd: S3SyncCommandConfig = {
|
||||||
|
name: 'sync',
|
||||||
|
description: 'desc',
|
||||||
|
bucket: 'static.ermnvldmr.com',
|
||||||
|
targetPrefix: 'docs',
|
||||||
|
sourceDir: './static',
|
||||||
|
type: 's3-sync',
|
||||||
|
};
|
||||||
|
|
||||||
|
await runS3Sync(cmd, {});
|
||||||
|
|
||||||
|
const content = fs.readFileSync(srcPath, 'utf-8');
|
||||||
|
expect(content).toContain('https://static.ermnvldmr.com/docs/img.webp');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should use explicit publicUrl if provided', async () => {
|
||||||
|
const staticDir = path.join(tempDir, 'static');
|
||||||
|
fs.mkdirSync(staticDir, { recursive: true });
|
||||||
|
fs.writeFileSync(path.join(staticDir, 'img.webp'), 'webp-content');
|
||||||
|
|
||||||
|
const srcDir = path.join(tempDir, 'src');
|
||||||
|
fs.mkdirSync(srcDir, { recursive: true });
|
||||||
|
const srcPath = path.join(srcDir, 'index.ts');
|
||||||
|
fs.writeFileSync(srcPath, 'const img = "/static/img.webp";');
|
||||||
|
|
||||||
|
const cmd: S3SyncCommandConfig = {
|
||||||
|
name: 'sync',
|
||||||
|
description: 'desc',
|
||||||
|
targetPrefix: 'www',
|
||||||
|
sourceDir: './static',
|
||||||
|
publicUrl: 'https://cdn.example.com',
|
||||||
|
type: 's3-sync',
|
||||||
|
};
|
||||||
|
|
||||||
|
await runS3Sync(cmd, {});
|
||||||
|
|
||||||
|
const content = fs.readFileSync(srcPath, 'utf-8');
|
||||||
|
expect(content).toContain('https://cdn.example.com/www/img.webp');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should fallback to COM_ERMNVLDMR_STATIC_PUBLIC_URL when publicUrl is not explicitly configured', async () => {
|
||||||
|
process.env.COM_ERMNVLDMR_STATIC_PUBLIC_URL = 'https://static.ermnvldmr.com';
|
||||||
|
|
||||||
|
const staticDir = path.join(tempDir, 'static');
|
||||||
|
fs.mkdirSync(staticDir, { recursive: true });
|
||||||
|
fs.writeFileSync(path.join(staticDir, 'asset.png'), 'png-content');
|
||||||
|
|
||||||
|
const srcDir = path.join(tempDir, 'src');
|
||||||
|
fs.mkdirSync(srcDir, { recursive: true });
|
||||||
|
const srcPath = path.join(srcDir, 'index.ts');
|
||||||
|
fs.writeFileSync(srcPath, 'const img = "/static/asset.png";');
|
||||||
|
|
||||||
|
const cmd: S3SyncCommandConfig = {
|
||||||
|
name: 'sync',
|
||||||
|
description: 'desc',
|
||||||
|
bucket: 'com-ermnvldmr-static',
|
||||||
|
targetPrefix: 'www',
|
||||||
|
sourceDir: './static',
|
||||||
|
type: 's3-sync',
|
||||||
|
};
|
||||||
|
|
||||||
|
await runS3Sync(cmd, {});
|
||||||
|
|
||||||
|
const content = fs.readFileSync(srcPath, 'utf-8');
|
||||||
|
expect(content).toContain('https://static.ermnvldmr.com/www/asset.png');
|
||||||
|
|
||||||
|
delete process.env.COM_ERMNVLDMR_STATIC_PUBLIC_URL;
|
||||||
|
});
|
||||||
});
|
});
|
||||||
@@ -53,6 +53,7 @@ export async function runS3Sync(
|
|||||||
const bucket = cmd.bucket ?? process.env.S3_BUCKET;
|
const bucket = cmd.bucket ?? process.env.S3_BUCKET;
|
||||||
const region = cmd.region ?? process.env.AWS_REGION ?? process.env.S3_REGION;
|
const region = cmd.region ?? process.env.AWS_REGION ?? process.env.S3_REGION;
|
||||||
const endpoint = cmd.endpoint ?? process.env.S3_ENDPOINT_URL ?? process.env.S3_ENDPOINT;
|
const endpoint = cmd.endpoint ?? process.env.S3_ENDPOINT_URL ?? process.env.S3_ENDPOINT;
|
||||||
|
const publicUrl = cmd.publicUrl ?? process.env.COM_ERMNVLDMR_STATIC_PUBLIC_URL ?? process.env.S3_PUBLIC_URL;
|
||||||
const accessKey = cmd.accessKeyId ?? process.env.AWS_ACCESS_KEY_ID ?? process.env.S3_ACCESS_KEY_ID;
|
const accessKey = cmd.accessKeyId ?? process.env.AWS_ACCESS_KEY_ID ?? process.env.S3_ACCESS_KEY_ID;
|
||||||
const secretKey = cmd.secretAccessKey ?? process.env.AWS_SECRET_ACCESS_KEY ?? process.env.S3_SECRET_ACCESS_KEY;
|
const secretKey = cmd.secretAccessKey ?? process.env.AWS_SECRET_ACCESS_KEY ?? process.env.S3_SECRET_ACCESS_KEY;
|
||||||
|
|
||||||
@@ -149,6 +150,13 @@ export async function runS3Sync(
|
|||||||
*/
|
*/
|
||||||
const getS3Url = (finalName: string): string => {
|
const getS3Url = (finalName: string): string => {
|
||||||
const normalizedKey = normalizeKey(cmd.targetPrefix, finalName);
|
const normalizedKey = normalizeKey(cmd.targetPrefix, finalName);
|
||||||
|
if (publicUrl) {
|
||||||
|
const cleanPublicUrl = publicUrl.replace(/\/+$/, '');
|
||||||
|
return `${cleanPublicUrl}/${normalizedKey}`;
|
||||||
|
}
|
||||||
|
if (bucket.includes('.')) {
|
||||||
|
return `https://${bucket}/${normalizedKey}`;
|
||||||
|
}
|
||||||
if (endpoint) {
|
if (endpoint) {
|
||||||
const cleanEndpoint = endpoint.replace(/\/+$/, '');
|
const cleanEndpoint = endpoint.replace(/\/+$/, '');
|
||||||
return `${cleanEndpoint}/${bucket}/${normalizedKey}`;
|
return `${cleanEndpoint}/${bucket}/${normalizedKey}`;
|
||||||
@@ -156,12 +164,17 @@ export async function runS3Sync(
|
|||||||
return `https://${bucket}.s3.${region}.amazonaws.com/${normalizedKey}`;
|
return `https://${bucket}.s3.${region}.amazonaws.com/${normalizedKey}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Find workspace source files matching `src/**/*.{ts,tsx,css,md,mdx}`
|
// Find workspace source files matching configured pattern or default `src/**/*.{ts,tsx,css,md,mdx}`
|
||||||
const sourceFiles = await fg('src/**/*.{ts,tsx,css,md,mdx}', {
|
const filePattern = cmd.sourceFilesPattern ?? 'src/**/*.{ts,tsx,css,md,mdx}';
|
||||||
|
const sourceFiles = await fg(filePattern, {
|
||||||
cwd: process.cwd(),
|
cwd: process.cwd(),
|
||||||
absolute: true,
|
absolute: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const urlPrefixes = cmd.urlPrefixes ?? ['/static/'];
|
||||||
|
const hasMatchingPrefix = (text: string): boolean =>
|
||||||
|
urlPrefixes.some((prefix) => text.includes(prefix));
|
||||||
|
|
||||||
// Sort assets by length descending to handle overlapping name replacement correctly
|
// Sort assets by length descending to handle overlapping name replacement correctly
|
||||||
const sortedAssets = [...processedFiles].sort(
|
const sortedAssets = [...processedFiles].sort(
|
||||||
(a, b) => b.originalName.length - a.originalName.length
|
(a, b) => b.originalName.length - a.originalName.length
|
||||||
@@ -170,28 +183,38 @@ export async function runS3Sync(
|
|||||||
// Replace static asset references in workspace source files
|
// Replace static asset references in workspace source files
|
||||||
for (const sourceFile of sourceFiles) {
|
for (const sourceFile of sourceFiles) {
|
||||||
let content = await fs.promises.readFile(sourceFile, 'utf-8');
|
let content = await fs.promises.readFile(sourceFile, 'utf-8');
|
||||||
if (!content.includes('/static/')) {
|
if (!hasMatchingPrefix(content)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let modified = false;
|
const originalContent = content;
|
||||||
|
|
||||||
for (const asset of sortedAssets) {
|
for (const asset of sortedAssets) {
|
||||||
let searchName = asset.originalName;
|
const namesToSearch =
|
||||||
if (searchName.startsWith('static/')) {
|
asset.finalName !== asset.originalName
|
||||||
searchName = searchName.substring('static/'.length);
|
? [asset.originalName, asset.finalName]
|
||||||
} else if (searchName.startsWith('/static/')) {
|
: [asset.originalName];
|
||||||
searchName = searchName.substring('/static/'.length);
|
|
||||||
|
for (const prefix of urlPrefixes) {
|
||||||
|
const cleanPrefix = prefix.replace(/^\/+|\/+$/g, '');
|
||||||
|
|
||||||
|
for (const name of namesToSearch) {
|
||||||
|
let searchName = name;
|
||||||
|
if (searchName.startsWith(`${cleanPrefix}/`)) {
|
||||||
|
searchName = searchName.substring(`${cleanPrefix}/`.length);
|
||||||
|
} else if (searchName.startsWith(`/${cleanPrefix}/`)) {
|
||||||
|
searchName = searchName.substring(`/${cleanPrefix}/`.length);
|
||||||
}
|
}
|
||||||
const searchStr = `/static/${searchName}`;
|
const searchStr = `/${cleanPrefix}/${searchName}`;
|
||||||
const assetUrl = getS3Url(asset.finalName);
|
const assetUrl = getS3Url(asset.finalName);
|
||||||
|
const escaped = searchStr.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
||||||
|
const regex = new RegExp('(?<!https?:\\/\\/[^\\s"\'`()]*)' + escaped, 'g');
|
||||||
|
|
||||||
if (content.includes(searchStr)) {
|
content = content.replace(regex, assetUrl);
|
||||||
content = content.split(searchStr).join(assetUrl);
|
}
|
||||||
modified = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (modified) {
|
if (content !== originalContent) {
|
||||||
await fs.promises.writeFile(sourceFile, content, 'utf-8');
|
await fs.promises.writeFile(sourceFile, content, 'utf-8');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -106,6 +106,10 @@ export interface S3SyncCommandConfig extends BaseCommandConfig {
|
|||||||
type: 's3-sync';
|
type: 's3-sync';
|
||||||
/** The source directory containing files to sync */
|
/** The source directory containing files to sync */
|
||||||
sourceDir?: string;
|
sourceDir?: string;
|
||||||
|
/** Glob pattern(s) matching source files where asset references should be replaced */
|
||||||
|
sourceFilesPattern?: string | string[];
|
||||||
|
/** URL prefixes to detect and replace with S3 URLs, defaults to ['/static/'] */
|
||||||
|
urlPrefixes?: string[];
|
||||||
/** The prefix (directory) under which to upload the files in the S3 bucket */
|
/** The prefix (directory) under which to upload the files in the S3 bucket */
|
||||||
targetPrefix: string;
|
targetPrefix: string;
|
||||||
/** Optional S3 bucket name */
|
/** Optional S3 bucket name */
|
||||||
@@ -114,6 +118,8 @@ export interface S3SyncCommandConfig extends BaseCommandConfig {
|
|||||||
region?: string;
|
region?: string;
|
||||||
/** Optional custom endpoint URL (e.g., for MinIO or Yandex Cloud) */
|
/** Optional custom endpoint URL (e.g., for MinIO or Yandex Cloud) */
|
||||||
endpoint?: string;
|
endpoint?: string;
|
||||||
|
/** Optional public base URL for assets (e.g., 'https://static.ermnvldmr.com') */
|
||||||
|
publicUrl?: string;
|
||||||
/** Optional AWS Access Key ID */
|
/** Optional AWS Access Key ID */
|
||||||
accessKeyId?: string;
|
accessKeyId?: string;
|
||||||
/** Optional AWS Secret Access Key */
|
/** Optional AWS Secret Access Key */
|
||||||
|
|||||||
@@ -10,6 +10,9 @@
|
|||||||
"files": [
|
"files": [
|
||||||
"src"
|
"src"
|
||||||
],
|
],
|
||||||
|
"scripts": {
|
||||||
|
"test": "node --test src/lib/rules/no-hanging-particles.test.js"
|
||||||
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@eslint/js": "^9.39.2",
|
"@eslint/js": "^9.39.2",
|
||||||
"eslint-config-prettier": "^10.1.2",
|
"eslint-config-prettier": "^10.1.2",
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
// @ts-check
|
||||||
|
import { i18nPlugin } from '../plugins/i18n.js';
|
||||||
|
import { markdownParser } from '../parsers/markdown.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* i18n typography and validation ESLint configuration.
|
||||||
|
*/
|
||||||
|
export const i18nConfig = [
|
||||||
|
{
|
||||||
|
files: ['**/*.i18n.{ts,tsx,js,jsx,mjs}'],
|
||||||
|
plugins: {
|
||||||
|
i18n: i18nPlugin,
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
'i18n/no-hanging-particles': 'error',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
files: ['**/*.{md,mdx}'],
|
||||||
|
languageOptions: {
|
||||||
|
parser: markdownParser,
|
||||||
|
},
|
||||||
|
plugins: {
|
||||||
|
i18n: i18nPlugin,
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
'no-irregular-whitespace': 'off',
|
||||||
|
'i18n/no-hanging-particles': 'error',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
@@ -6,6 +6,7 @@ import { jsdocConfig } from './jsdoc.js';
|
|||||||
import { testingConfig } from './testing.js';
|
import { testingConfig } from './testing.js';
|
||||||
import { toolingConfig } from './tooling.js';
|
import { toolingConfig } from './tooling.js';
|
||||||
import { defineMonorepoRestrictedImports } from './monorepo.js';
|
import { defineMonorepoRestrictedImports } from './monorepo.js';
|
||||||
|
import { i18nConfig } from './i18n.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Common ignores for the entire monorepo.
|
* Common ignores for the entire monorepo.
|
||||||
@@ -38,6 +39,9 @@ export function defineBaseConfig(rootDir) {
|
|||||||
...jsdocConfig,
|
...jsdocConfig,
|
||||||
...testingConfig,
|
...testingConfig,
|
||||||
...toolingConfig,
|
...toolingConfig,
|
||||||
|
...i18nConfig,
|
||||||
...defineMonorepoRestrictedImports(rootDir),
|
...defineMonorepoRestrictedImports(rootDir),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export { i18nConfig };
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
// @ts-check
|
// @ts-check
|
||||||
import path from 'node:path';
|
import path from 'node:path';
|
||||||
import { defineBaseConfig } from './config/index.js';
|
import { defineBaseConfig, i18nConfig } from './config/index.js';
|
||||||
|
import { i18nPlugin } from './plugins/i18n.js';
|
||||||
|
|
||||||
// Resolve the monorepo root relative to this library's location
|
// Resolve the monorepo root relative to this library's location
|
||||||
const rootDir = path.resolve(import.meta.dirname, '../../../../');
|
const rootDir = path.resolve(import.meta.dirname, '../../../../');
|
||||||
@@ -10,4 +11,4 @@ const rootDir = path.resolve(import.meta.dirname, '../../../../');
|
|||||||
*/
|
*/
|
||||||
export const baseConfig = defineBaseConfig(rootDir);
|
export const baseConfig = defineBaseConfig(rootDir);
|
||||||
|
|
||||||
export { defineBaseConfig };
|
export { defineBaseConfig, i18nConfig, i18nPlugin };
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
// @ts-check
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates start and end line/column locations for a string offset.
|
||||||
|
*
|
||||||
|
* @param {string} code - Entire source code.
|
||||||
|
* @returns {import('eslint').AST.SourceLocation} Full document SourceLocation.
|
||||||
|
*/
|
||||||
|
function getDocumentLocation(code) {
|
||||||
|
const lines = code.split('\n');
|
||||||
|
const lastLine = lines.length;
|
||||||
|
const lastColumn = lines[lines.length - 1].length;
|
||||||
|
|
||||||
|
return {
|
||||||
|
start: { line: 1, column: 0 },
|
||||||
|
end: { line: lastLine, column: lastColumn },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Custom lightweight parser for Markdown and MDX documents.
|
||||||
|
* Produces an AST that enables typography linting and autofixing on prose text.
|
||||||
|
*/
|
||||||
|
export const markdownParser = {
|
||||||
|
meta: {
|
||||||
|
name: 'eslint-parser-markdown-typography',
|
||||||
|
version: '1.0.0',
|
||||||
|
},
|
||||||
|
parseForESLint(code, options = {}) {
|
||||||
|
const filePath = options.filePath || '';
|
||||||
|
const isRu = /(?:^|[\\/])ru(?:[\\/]|\.ru\.)/i.test(filePath);
|
||||||
|
const isEn = /(?:^|[\\/])en(?:[\\/]|\.en\.)/i.test(filePath);
|
||||||
|
const locale = isRu ? 'ru' : isEn ? 'en' : undefined;
|
||||||
|
|
||||||
|
const loc = getDocumentLocation(code);
|
||||||
|
|
||||||
|
return {
|
||||||
|
ast: {
|
||||||
|
type: 'Program',
|
||||||
|
range: [0, code.length],
|
||||||
|
loc,
|
||||||
|
body: [
|
||||||
|
{
|
||||||
|
type: 'MarkdownDocument',
|
||||||
|
range: [0, code.length],
|
||||||
|
loc,
|
||||||
|
value: code,
|
||||||
|
locale,
|
||||||
|
filePath,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
tokens: [],
|
||||||
|
comments: [],
|
||||||
|
},
|
||||||
|
visitorKeys: {
|
||||||
|
Program: ['body'],
|
||||||
|
MarkdownDocument: [],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
};
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
// @ts-check
|
||||||
|
import { noHangingParticlesRule } from '../rules/no-hanging-particles.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ESLint plugin providing i18n translation validation and typography rules.
|
||||||
|
*/
|
||||||
|
export const i18nPlugin = {
|
||||||
|
meta: {
|
||||||
|
name: 'eslint-plugin-i18n',
|
||||||
|
version: '1.0.0',
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
'no-hanging-particles': noHangingParticlesRule,
|
||||||
|
},
|
||||||
|
};
|
||||||
@@ -0,0 +1,310 @@
|
|||||||
|
// @ts-check
|
||||||
|
|
||||||
|
const RU_PARTICLES = [
|
||||||
|
'[а-яё]',
|
||||||
|
'во', 'со', 'ко', 'до', 'по', 'на', 'из', 'за', 'от', 'об', 'не', 'ни', 'но', 'да', 'то', 'уж',
|
||||||
|
'обо', 'под', 'над', 'при', 'про', 'для', 'без', 'или', 'как', 'что', 'еще', 'ещё', 'уже',
|
||||||
|
'через', 'сквозь', 'перед', 'из-за', 'из-под',
|
||||||
|
].join('|');
|
||||||
|
|
||||||
|
const EN_PARTICLES = [
|
||||||
|
'a', 'an', 'the',
|
||||||
|
'in', 'on', 'at', 'to', 'of', 'by', 'for', 'up', 'as', 'if', 'is', 'it', 'no',
|
||||||
|
'and', 'or', 'nor', 'but', 'yet', 'so', 'with', 'into', 'from',
|
||||||
|
].join('|');
|
||||||
|
|
||||||
|
const RU_TRAILING = ['ли', 'ль', 'же', 'ж', 'бы', 'б'].join('|');
|
||||||
|
|
||||||
|
const KNOWN_LOCALES = new Set(['en', 'ru']);
|
||||||
|
const PLURAL_KEYS = new Set(['zero', 'one', 'two', 'few', 'many', 'other']);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applies non-breaking space typography rules to a translation string value.
|
||||||
|
*
|
||||||
|
* @param {string} input - The raw translation string.
|
||||||
|
* @param {string} [locale] - The locale code ('en' | 'ru').
|
||||||
|
* @returns {string} The transformed string with non-breaking spaces.
|
||||||
|
*/
|
||||||
|
export function applyTypography(input, locale) {
|
||||||
|
let text = input.replaceAll(' ', '\u00A0');
|
||||||
|
|
||||||
|
/** @type {string[]} */
|
||||||
|
const protectedTokens = [];
|
||||||
|
text = text.replace(/\{[^}]+\}|<[^>]+>|\]\([^)]+\)/g, (match) => {
|
||||||
|
const idx = protectedTokens.length;
|
||||||
|
protectedTokens.push(match);
|
||||||
|
return `__TYPO_PROT_${idx}__`;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Em-dash and en-dash (prepend non-breaking space)
|
||||||
|
text = text.replace(/(?<=\S)[\t \u00A0]+([—–])[\t ]+/g, '\u00A0$1 ');
|
||||||
|
|
||||||
|
// Numbers & units/symbols
|
||||||
|
text = text.replace(/(?<=\d)[\t ]+(?=[a-zA-Zа-яА-ЯёЁ%№$€₽]|__TYPO_PROT_)/g, '\u00A0');
|
||||||
|
text = text.replace(/(?<=[№§$€₽])[\t ]+(?=\d|__TYPO_PROT_)/g, '\u00A0');
|
||||||
|
|
||||||
|
// Trailing particles (Russian)
|
||||||
|
if (!locale || locale === 'ru') {
|
||||||
|
const trailingRegex = new RegExp(`(?<=[а-яА-ЯёЁ\\w])\\s+(${RU_TRAILING})(?=[\\s\\u00A0.,!?:;»"')\\]]|$)`, 'gi');
|
||||||
|
text = text.replace(trailingRegex, '\u00A0$1');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Leading particles (RU / EN)
|
||||||
|
const particles = locale === 'en' ? EN_PARTICLES : locale === 'ru' ? RU_PARTICLES : `${RU_PARTICLES}|${EN_PARTICLES}`;
|
||||||
|
const leadingRegex = new RegExp(`(?<=^|[\\s\\u00A0.,!?:;«"'(])(${particles})[ \\t]+(?=\\S)`, 'gi');
|
||||||
|
text = text.replace(leadingRegex, '$1\u00A0');
|
||||||
|
|
||||||
|
// Restore protected tokens
|
||||||
|
text = text.replace(/__TYPO_PROT_(\d+)__/g, (_, idx) => protectedTokens[Number(idx)]);
|
||||||
|
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Masks frontmatter non-title/description lines.
|
||||||
|
*
|
||||||
|
* @param {string} text - Raw document text.
|
||||||
|
* @param {(str: string) => string} mask - Masking function.
|
||||||
|
* @returns {string} Text with frontmatter metadata masked.
|
||||||
|
*/
|
||||||
|
function maskFrontmatter(text, mask) {
|
||||||
|
if (!text.startsWith('---')) return text;
|
||||||
|
const endIdx = text.indexOf('\n---', 3);
|
||||||
|
if (endIdx === -1) return text;
|
||||||
|
const fm = text.slice(0, endIdx + 4);
|
||||||
|
const rest = text.slice(endIdx + 4);
|
||||||
|
|
||||||
|
const lines = fm.split('\n');
|
||||||
|
const processedLines = lines.map((line, idx) => {
|
||||||
|
if (idx === 0 || idx === lines.length - 1) return mask(line);
|
||||||
|
const trimmed = line.trim();
|
||||||
|
if (trimmed.startsWith('title:') || trimmed.startsWith('description:')) {
|
||||||
|
return line;
|
||||||
|
}
|
||||||
|
return mask(line);
|
||||||
|
});
|
||||||
|
return processedLines.join('\n') + rest;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applies typography rules to a Markdown/MDX document, protecting code blocks,
|
||||||
|
* inline code, shortcodes, link URLs, HTML tags, and frontmatter metadata.
|
||||||
|
*
|
||||||
|
* @param {string} content - Markdown document content.
|
||||||
|
* @param {string} [locale] - The document locale ('en' | 'ru').
|
||||||
|
* @returns {string} Transformed markdown content.
|
||||||
|
*/
|
||||||
|
export function applyMarkdownTypography(content, locale) {
|
||||||
|
/** @type {string[]} */
|
||||||
|
const protectedTokens = [];
|
||||||
|
/**
|
||||||
|
* @param {string} str
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
function mask(str) {
|
||||||
|
const idx = protectedTokens.length;
|
||||||
|
protectedTokens.push(str);
|
||||||
|
return `__MD_PROT_${idx}__`;
|
||||||
|
}
|
||||||
|
|
||||||
|
let text = maskFrontmatter(content, mask);
|
||||||
|
|
||||||
|
// Mask fenced code blocks ```...``` and ~~~...~~~
|
||||||
|
text = text.replace(/```[\s\S]*?```|~~~[\s\S]*?~~~/g, mask);
|
||||||
|
// Mask Hugo shortcodes {{< ... >}} or {{% ... %}}
|
||||||
|
text = text.replace(/\{\{[<%][\s\S]*?[>%]\}\}/g, mask);
|
||||||
|
// Mask inline code `...`
|
||||||
|
text = text.replace(/`[^`\n]+`/g, mask);
|
||||||
|
// Mask Markdown link targets ](...)
|
||||||
|
text = text.replace(/\]\([^)]+\)/g, mask);
|
||||||
|
// Mask HTML tags
|
||||||
|
text = text.replace(/<[^>]+>/g, mask);
|
||||||
|
|
||||||
|
// Apply typography rules
|
||||||
|
text = applyTypography(text, locale);
|
||||||
|
|
||||||
|
// Restore protected tokens
|
||||||
|
text = text.replace(/__MD_PROT_(\d+)__/g, (_, idx) => protectedTokens[Number(idx)]);
|
||||||
|
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serializes a string into a valid JS string literal with specified quote.
|
||||||
|
*
|
||||||
|
* @param {string} str - String to escape and wrap.
|
||||||
|
* @param {string} quote - Quote character (' or ").
|
||||||
|
* @returns {string} Serialized literal.
|
||||||
|
*/
|
||||||
|
function serializeStringLiteral(str, quote) {
|
||||||
|
const escaped = str
|
||||||
|
.replace(/\\/g, '\\\\')
|
||||||
|
.replace(/\r/g, '\\r')
|
||||||
|
.replace(/\n/g, '\\n')
|
||||||
|
.replace(/\t/g, '\\t')
|
||||||
|
.replace(new RegExp(quote, 'g'), `\\${quote}`);
|
||||||
|
return `${quote}${escaped}${quote}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts property name from a property node.
|
||||||
|
*
|
||||||
|
* @param {any} prop - Property AST node.
|
||||||
|
* @returns {string | null} Property name or null.
|
||||||
|
*/
|
||||||
|
function getPropertyName(prop) {
|
||||||
|
if (!prop || !prop.key) return null;
|
||||||
|
if (prop.key.type === 'Identifier') return prop.key.name;
|
||||||
|
if (prop.key.type === 'Literal') return String(prop.key.value);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ESLint rule module for enforcing non-breaking spaces in i18n translation values
|
||||||
|
* and Markdown/MDX documentation.
|
||||||
|
*
|
||||||
|
* @type {import('eslint').Rule.RuleModule}
|
||||||
|
*/
|
||||||
|
export const noHangingParticlesRule = {
|
||||||
|
meta: {
|
||||||
|
type: 'layout',
|
||||||
|
docs: {
|
||||||
|
description: 'Enforce non-breaking spaces for hanging particles and numbers in i18n translation values and markdown documentation.',
|
||||||
|
recommended: true,
|
||||||
|
},
|
||||||
|
fixable: 'whitespace',
|
||||||
|
schema: [],
|
||||||
|
messages: {
|
||||||
|
hangingParticle: 'Translation value contains hanging particles or numbers that should be bound with a non-breaking space (\\u00A0).',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
create(context) {
|
||||||
|
/**
|
||||||
|
* Checks and fixes a single string literal node.
|
||||||
|
*
|
||||||
|
* @param {any} node - String Literal AST node.
|
||||||
|
* @param {string} [locale] - The locale code if known.
|
||||||
|
*/
|
||||||
|
function checkStringLiteral(node, locale) {
|
||||||
|
if (!node || typeof node.value !== 'string') return;
|
||||||
|
const original = node.value;
|
||||||
|
const formatted = applyTypography(original, locale);
|
||||||
|
|
||||||
|
if (original !== formatted) {
|
||||||
|
context.report({
|
||||||
|
node,
|
||||||
|
messageId: 'hangingParticle',
|
||||||
|
fix(fixer) {
|
||||||
|
const raw = node.raw || '';
|
||||||
|
const quote = raw.startsWith('"') ? '"' : "'";
|
||||||
|
return fixer.replaceText(node, serializeStringLiteral(formatted, quote));
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inspects a locale entry inside a translation item.
|
||||||
|
*
|
||||||
|
* @param {any} prop - Locale property node (e.g. en or ru).
|
||||||
|
*/
|
||||||
|
function processLocaleEntry(prop) {
|
||||||
|
const locale = getPropertyName(prop);
|
||||||
|
if (!locale || !KNOWN_LOCALES.has(locale)) return;
|
||||||
|
|
||||||
|
const valueNode = prop.value;
|
||||||
|
if (!valueNode) return;
|
||||||
|
|
||||||
|
if (valueNode.type === 'Literal') {
|
||||||
|
checkStringLiteral(valueNode, locale);
|
||||||
|
} else if (valueNode.type === 'ObjectExpression' && Array.isArray(valueNode.properties)) {
|
||||||
|
for (const pluralProp of valueNode.properties) {
|
||||||
|
if (pluralProp.type === 'Property') {
|
||||||
|
const pluralKey = getPropertyName(pluralProp);
|
||||||
|
if (pluralKey && PLURAL_KEYS.has(pluralKey) && pluralProp.value?.type === 'Literal') {
|
||||||
|
checkStringLiteral(pluralProp.value, locale);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processes keyset object dictionary properties.
|
||||||
|
*
|
||||||
|
* @param {any} objectNode - Keyset ObjectExpression AST node.
|
||||||
|
*/
|
||||||
|
function processKeysetObject(objectNode) {
|
||||||
|
if (!objectNode || !Array.isArray(objectNode.properties)) return;
|
||||||
|
|
||||||
|
for (const dictEntry of objectNode.properties) {
|
||||||
|
if (
|
||||||
|
dictEntry.type === 'Property' &&
|
||||||
|
dictEntry.value &&
|
||||||
|
dictEntry.value.type === 'ObjectExpression' &&
|
||||||
|
Array.isArray(dictEntry.value.properties)
|
||||||
|
) {
|
||||||
|
for (const localeProp of dictEntry.value.properties) {
|
||||||
|
if (localeProp.type === 'Property') {
|
||||||
|
processLocaleEntry(localeProp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
CallExpression(node) {
|
||||||
|
if (
|
||||||
|
node.callee &&
|
||||||
|
node.callee.type === 'Identifier' &&
|
||||||
|
node.callee.name === 'createKeyset' &&
|
||||||
|
node.arguments.length > 0 &&
|
||||||
|
node.arguments[0].type === 'ObjectExpression'
|
||||||
|
) {
|
||||||
|
processKeysetObject(node.arguments[0]);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
MarkdownDocument(node) {
|
||||||
|
if (!node || typeof node.value !== 'string') return;
|
||||||
|
const original = node.value;
|
||||||
|
const formatted = applyMarkdownTypography(original, node.locale);
|
||||||
|
|
||||||
|
if (original === formatted) return;
|
||||||
|
|
||||||
|
const origLines = original.split('\n');
|
||||||
|
const formLines = formatted.split('\n');
|
||||||
|
|
||||||
|
let reported = false;
|
||||||
|
for (let i = 0; i < origLines.length; i++) {
|
||||||
|
const origLine = origLines[i];
|
||||||
|
const formLine = formLines[i];
|
||||||
|
if (origLine !== formLine) {
|
||||||
|
let diffCol = 0;
|
||||||
|
while (
|
||||||
|
diffCol < origLine.length &&
|
||||||
|
diffCol < formLine.length &&
|
||||||
|
origLine[diffCol] === formLine[diffCol]
|
||||||
|
) {
|
||||||
|
diffCol++;
|
||||||
|
}
|
||||||
|
|
||||||
|
const isFirst = !reported;
|
||||||
|
reported = true;
|
||||||
|
|
||||||
|
context.report({
|
||||||
|
node,
|
||||||
|
loc: {
|
||||||
|
start: { line: i + 1, column: diffCol },
|
||||||
|
end: { line: i + 1, column: diffCol + 1 },
|
||||||
|
},
|
||||||
|
messageId: 'hangingParticle',
|
||||||
|
fix: isFirst ? (fixer) => fixer.replaceText(node, formatted) : undefined,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
};
|
||||||
@@ -0,0 +1,251 @@
|
|||||||
|
// @ts-check
|
||||||
|
import { describe, it } from 'node:test';
|
||||||
|
import { RuleTester } from 'eslint';
|
||||||
|
import { noHangingParticlesRule } from './no-hanging-particles.js';
|
||||||
|
import { markdownParser } from '../parsers/markdown.js';
|
||||||
|
|
||||||
|
// Configure RuleTester for node:test
|
||||||
|
RuleTester.describe = describe;
|
||||||
|
RuleTester.it = it;
|
||||||
|
|
||||||
|
const ruleTester = new RuleTester();
|
||||||
|
|
||||||
|
ruleTester.run('no-hanging-particles', noHangingParticlesRule, {
|
||||||
|
valid: [
|
||||||
|
{
|
||||||
|
code: `
|
||||||
|
createKeyset({
|
||||||
|
'Yet capturing context': {
|
||||||
|
en: 'Yet\\u00A0capturing context and\\u00A0architectural decisions',
|
||||||
|
ru: 'Мои мысли и\\u00A0проекты',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// Keys should not trigger errors even if they contain particles
|
||||||
|
code: `
|
||||||
|
createKeyset({
|
||||||
|
'и иные проблемы': {
|
||||||
|
en: 'and\\u00A0other issues',
|
||||||
|
ru: 'и\\u00A0иные проблемы',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// Manual {nbsp} token is allowed
|
||||||
|
code: `
|
||||||
|
createKeyset({
|
||||||
|
manual: {
|
||||||
|
en: 'Yet{nbsp}capturing',
|
||||||
|
ru: 'и{nbsp}иные',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// Not a createKeyset call
|
||||||
|
code: `
|
||||||
|
const regularObj = {
|
||||||
|
en: 'Yet capturing without keyset',
|
||||||
|
};
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
invalid: [
|
||||||
|
{
|
||||||
|
// English leading particle
|
||||||
|
code: `
|
||||||
|
createKeyset({
|
||||||
|
key: {
|
||||||
|
en: 'Yet capturing context',
|
||||||
|
ru: 'Фиксация контекста',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
`,
|
||||||
|
output: `
|
||||||
|
createKeyset({
|
||||||
|
key: {
|
||||||
|
en: 'Yet\u00A0capturing context',
|
||||||
|
ru: 'Фиксация контекста',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
`,
|
||||||
|
errors: [
|
||||||
|
{
|
||||||
|
messageId: 'hangingParticle',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// Russian leading particle
|
||||||
|
code: `
|
||||||
|
createKeyset({
|
||||||
|
'и иные проблемы': {
|
||||||
|
en: 'and other issues',
|
||||||
|
ru: 'и иные проблемы',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
`,
|
||||||
|
output: `
|
||||||
|
createKeyset({
|
||||||
|
'и иные проблемы': {
|
||||||
|
en: 'and\u00A0other issues',
|
||||||
|
ru: 'и\u00A0иные проблемы',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
`,
|
||||||
|
errors: [
|
||||||
|
{ messageId: 'hangingParticle' },
|
||||||
|
{ messageId: 'hangingParticle' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// Interpolation placeholder & trailing particles & dashes & numbers
|
||||||
|
code: `
|
||||||
|
createKeyset({
|
||||||
|
welcome: {
|
||||||
|
en: 'Inspect the {repositoryLink} for 10 items — all good',
|
||||||
|
ru: 'Загляните в {repositoryLink}, как же так — это 10 вещей в 2026 году',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
`,
|
||||||
|
output: `
|
||||||
|
createKeyset({
|
||||||
|
welcome: {
|
||||||
|
en: 'Inspect the\u00A0{repositoryLink} for\u00A010\u00A0items\u00A0— all good',
|
||||||
|
ru: 'Загляните в\u00A0{repositoryLink}, как\u00A0же так\u00A0— это 10\u00A0вещей в\u00A02026\u00A0году',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
`,
|
||||||
|
errors: [
|
||||||
|
{ messageId: 'hangingParticle' },
|
||||||
|
{ messageId: 'hangingParticle' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// HTML entity replacement
|
||||||
|
code: `
|
||||||
|
createKeyset({
|
||||||
|
test: {
|
||||||
|
en: 'Text with entity',
|
||||||
|
ru: 'Текст с сущностью',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
`,
|
||||||
|
output: `
|
||||||
|
createKeyset({
|
||||||
|
test: {
|
||||||
|
en: 'Text\u00A0with\u00A0entity',
|
||||||
|
ru: 'Текст\u00A0с\u00A0сущностью',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
`,
|
||||||
|
errors: [
|
||||||
|
{ messageId: 'hangingParticle' },
|
||||||
|
{ messageId: 'hangingParticle' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// Plural forms
|
||||||
|
code: `
|
||||||
|
createKeyset({
|
||||||
|
counter: {
|
||||||
|
en: {
|
||||||
|
one: '{count} item',
|
||||||
|
other: '{count} items in stock',
|
||||||
|
},
|
||||||
|
ru: {
|
||||||
|
one: '{count} штука в наличии',
|
||||||
|
few: '{count} штуки в наличии',
|
||||||
|
many: '{count} штук в наличии',
|
||||||
|
other: '{count} штук в наличии',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
`,
|
||||||
|
output: `
|
||||||
|
createKeyset({
|
||||||
|
counter: {
|
||||||
|
en: {
|
||||||
|
one: '{count} item',
|
||||||
|
other: '{count} items in\u00A0stock',
|
||||||
|
},
|
||||||
|
ru: {
|
||||||
|
one: '{count} штука в\u00A0наличии',
|
||||||
|
few: '{count} штуки в\u00A0наличии',
|
||||||
|
many: '{count} штук в\u00A0наличии',
|
||||||
|
other: '{count} штук в\u00A0наличии',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
`,
|
||||||
|
errors: [
|
||||||
|
{ messageId: 'hangingParticle' },
|
||||||
|
{ messageId: 'hangingParticle' },
|
||||||
|
{ messageId: 'hangingParticle' },
|
||||||
|
{ messageId: 'hangingParticle' },
|
||||||
|
{ messageId: 'hangingParticle' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
const markdownRuleTester = new RuleTester({
|
||||||
|
languageOptions: {
|
||||||
|
parser: markdownParser,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
markdownRuleTester.run('no-hanging-particles (markdown)', noHangingParticlesRule, {
|
||||||
|
valid: [
|
||||||
|
{
|
||||||
|
code: '# Title\n\nYet\\u00A0capturing context\\u00A0— for\\u00A010\\u00A0items',
|
||||||
|
filename: 'content/en/overview.md',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// Code blocks should be protected
|
||||||
|
code: '```ts\nconst in = 10;\n```',
|
||||||
|
filename: 'content/en/guide.md',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// Inline code and link targets should be protected
|
||||||
|
code: 'Use `in` keyword here [link](https://example.com/in/path).',
|
||||||
|
filename: 'content/en/guide.md',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// Hugo shortcodes should be protected
|
||||||
|
code: '{{< card link="apex" title="apex" >}}',
|
||||||
|
filename: 'content/en/guide.md',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// Frontmatter tags/date should be protected
|
||||||
|
code: '---\ntitle: "Title"\ntags: [a, in, on]\n---\nBody text',
|
||||||
|
filename: 'content/en/guide.md',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
invalid: [
|
||||||
|
{
|
||||||
|
code: '# Title\n\nYet capturing context — for 10 items',
|
||||||
|
output: '# Title\n\nYet\u00A0capturing context\u00A0— for\u00A010\u00A0items',
|
||||||
|
filename: 'content/en/overview.md',
|
||||||
|
errors: [{ messageId: 'hangingParticle' }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: 'Это руководство для заметок с нуля',
|
||||||
|
output: 'Это руководство для\u00A0заметок с\u00A0нуля',
|
||||||
|
filename: 'content/ru/overview.md',
|
||||||
|
errors: [{ messageId: 'hangingParticle' }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: '---\ntitle: "Руководство по развертыванию"\ntags: [a, in]\n---\nС нуля',
|
||||||
|
output: '---\ntitle: "Руководство по\u00A0развертыванию"\ntags: [a, in]\n---\nС\u00A0нуля',
|
||||||
|
filename: 'content/ru/guide.md',
|
||||||
|
errors: [
|
||||||
|
{ messageId: 'hangingParticle' },
|
||||||
|
{ messageId: 'hangingParticle' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
@@ -5,6 +5,7 @@
|
|||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "./dist/index.js",
|
"main": "./dist/index.js",
|
||||||
"types": "./dist/index.d.ts",
|
"types": "./dist/index.d.ts",
|
||||||
|
"sideEffects": false,
|
||||||
"exports": {
|
"exports": {
|
||||||
".": {
|
".": {
|
||||||
"import": "./dist/index.js",
|
"import": "./dist/index.js",
|
||||||
@@ -44,6 +45,6 @@
|
|||||||
"@vitest/coverage-v8": "^4.0.18",
|
"@vitest/coverage-v8": "^4.0.18",
|
||||||
"react": "^19.1.0",
|
"react": "^19.1.0",
|
||||||
"typescript": "^5.8.3",
|
"typescript": "^5.8.3",
|
||||||
"vitest": "^4.0.18"
|
"vitest": "^4.1.11"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6,6 +6,9 @@
|
|||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "./dist/index.js",
|
"main": "./dist/index.js",
|
||||||
"types": "./dist/index.d.ts",
|
"types": "./dist/index.d.ts",
|
||||||
|
"sideEffects": [
|
||||||
|
"**/*.css"
|
||||||
|
],
|
||||||
"exports": {
|
"exports": {
|
||||||
".": {
|
".": {
|
||||||
"import": "./dist/index.js",
|
"import": "./dist/index.js",
|
||||||
@@ -65,7 +68,7 @@
|
|||||||
"storybook": "^8.6.17",
|
"storybook": "^8.6.17",
|
||||||
"storybook-react-rsbuild": "^1.0.3",
|
"storybook-react-rsbuild": "^1.0.3",
|
||||||
"typescript": "^5.8.3",
|
"typescript": "^5.8.3",
|
||||||
"vitest": "^4.0.18",
|
"vitest": "^4.1.11",
|
||||||
"wait-on": "^8.0.3"
|
"wait-on": "^8.0.3"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
|
|||||||
@@ -12,19 +12,19 @@ describe('PageHead', () => {
|
|||||||
expect(screen.getByText('Test Caption')).toBeInTheDocument();
|
expect(screen.getByText('Test Caption')).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('renders breadcrumbs, addonLeft, and addonRight', () => {
|
it('renders breadcrumbs and addons in both expanded and collapsed views', () => {
|
||||||
render(
|
render(
|
||||||
<PageHead
|
<PageHead
|
||||||
addonLeft={<span>Left Addon</span>}
|
addonLeft={<span>Logo Left</span>}
|
||||||
addonRight={<span>Right Addon</span>}
|
addonRight={<span>Nav Menu</span>}
|
||||||
breadcrumbs={<span>Breadcrumbs Trail</span>}
|
breadcrumbs={<span>Breadcrumbs Trail</span>}
|
||||||
heading="Test Heading"
|
heading="Wanted"
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(screen.getByText('Breadcrumbs Trail')).toBeInTheDocument();
|
expect(screen.getAllByText('Breadcrumbs Trail').length).toBe(2);
|
||||||
expect(screen.getAllByText('Left Addon').length).toBeGreaterThan(0);
|
expect(screen.getAllByText('Nav Menu').length).toBe(2);
|
||||||
expect(screen.getAllByText('Right Addon').length).toBeGreaterThan(0);
|
expect(screen.getAllByText('Logo Left').length).toBe(2);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('renders correctly with always-collapsed-fixed strategy', () => {
|
it('renders correctly with always-collapsed-fixed strategy', () => {
|
||||||
|
|||||||
@@ -76,22 +76,28 @@ export function PageHead({
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isCollapsible) {
|
if (isCollapsible) {
|
||||||
setIsCollapsed(scrollY > 200);
|
setIsCollapsed(scrollY > 150);
|
||||||
}
|
}
|
||||||
}, [scrollY, isCollapsible]);
|
}, [scrollY, isCollapsible]);
|
||||||
|
|
||||||
const rootClasses = cn(pageHeadRootVariants({ strategy }), className);
|
const rootClasses = cn(pageHeadRootVariants({ strategy }), className);
|
||||||
|
|
||||||
|
const hasTopBar = Boolean(addonLeft ?? breadcrumbs ?? addonRight);
|
||||||
|
|
||||||
const expandedContent = (
|
const expandedContent = (
|
||||||
|
<div>
|
||||||
|
{hasTopBar && (
|
||||||
<PageContainer paddingY="none">
|
<PageContainer paddingY="none">
|
||||||
<VStack align="stretch" className="pb-8 sm:pb-12" gap={6}>
|
<HStack align="center" className="min-h-[60px] py-2.5" gap={4} justify="between" wrap="wrap">
|
||||||
<HStack align="center" className="py-2.5" gap={4} justify="between" wrap="wrap">
|
|
||||||
<HStack align="center" className="flex-1" gap={4}>
|
<HStack align="center" className="flex-1" gap={4}>
|
||||||
{addonLeft && <div className="flex-shrink-0 whitespace-nowrap">{addonLeft}</div>}
|
{addonLeft && <div className="flex-shrink-0 whitespace-nowrap">{addonLeft}</div>}
|
||||||
{breadcrumbs && <div className="hidden sm:block">{breadcrumbs}</div>}
|
{breadcrumbs && <div className="hidden sm:block text-label-l [&_ol]:text-label-l">{breadcrumbs}</div>}
|
||||||
</HStack>
|
</HStack>
|
||||||
{addonRight && <div className="flex-shrink-0">{addonRight}</div>}
|
{addonRight && <div className="flex-shrink-0">{addonRight}</div>}
|
||||||
</HStack>
|
</HStack>
|
||||||
|
</PageContainer>
|
||||||
|
)}
|
||||||
|
<PageContainer className={cn(hasTopBar ? 'pt-2.5 pb-8 sm:pt-3.5 sm:pb-12' : 'pt-5 pb-8 sm:pt-9 sm:pb-12')}>
|
||||||
<VStack gap={4}>
|
<VStack gap={4}>
|
||||||
<Header level={1}>{heading}</Header>
|
<Header level={1}>{heading}</Header>
|
||||||
{typeof caption === 'string' ? (
|
{typeof caption === 'string' ? (
|
||||||
@@ -102,16 +108,21 @@ export function PageHead({
|
|||||||
caption
|
caption
|
||||||
)}
|
)}
|
||||||
</VStack>
|
</VStack>
|
||||||
</VStack>
|
|
||||||
</PageContainer>
|
</PageContainer>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
const collapsedContent = (
|
const collapsedContent = (
|
||||||
<PageContainer paddingY="none">
|
<PageContainer paddingY="none">
|
||||||
<HStack align="center" className="py-2.5" gap={4} justify="between" wrap="wrap">
|
<HStack align="center" className="min-h-[60px] py-2.5" gap={4} justify="between" wrap="wrap">
|
||||||
<HStack align="center" className="flex-1" gap={4}>
|
<HStack align="center" className="flex-1" gap={4}>
|
||||||
{addonLeft && <div className="flex-shrink-0 whitespace-nowrap">{addonLeft}</div>}
|
{addonLeft && <div className="flex-shrink-0 whitespace-nowrap">{addonLeft}</div>}
|
||||||
<Header className="min-w-0" level={4} overflow="ellipsis">
|
{breadcrumbs && <div className="hidden sm:block text-label-l [&_ol]:text-label-l">{breadcrumbs}</div>}
|
||||||
|
<Header
|
||||||
|
className={cn('min-w-0', breadcrumbs && 'sm:hidden')}
|
||||||
|
level={4}
|
||||||
|
overflow="ellipsis"
|
||||||
|
>
|
||||||
{heading}
|
{heading}
|
||||||
</Header>
|
</Header>
|
||||||
</HStack>
|
</HStack>
|
||||||
|
|||||||
@@ -7,7 +7,8 @@
|
|||||||
"./testing": "./dist/testing.js"
|
"./testing": "./dist/testing.js"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "tsc"
|
"build": "tsc",
|
||||||
|
"test": "vitest run src"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@rsbuild/plugin-react": "^1.1.1",
|
"@rsbuild/plugin-react": "^1.1.1",
|
||||||
@@ -26,6 +27,6 @@
|
|||||||
"react-dom": "^19.1.0",
|
"react-dom": "^19.1.0",
|
||||||
"typescript": "^5.8.2",
|
"typescript": "^5.8.2",
|
||||||
"vite-tsconfig-paths": "^6.1.1",
|
"vite-tsconfig-paths": "^6.1.1",
|
||||||
"vitest": "^4.0.18"
|
"vitest": "^4.1.11"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,2 +1,3 @@
|
|||||||
export * from './rsbuild.js';
|
export * from './rsbuild.js';
|
||||||
|
export * from './server.js';
|
||||||
export * from './vitest.js';
|
export * from './vitest.js';
|
||||||
@@ -26,9 +26,6 @@ export function defineServiceConfig(config: RsbuildConfig = {}): RsbuildConfig {
|
|||||||
distPath: {
|
distPath: {
|
||||||
font: 'static/font',
|
font: 'static/font',
|
||||||
},
|
},
|
||||||
filename: {
|
|
||||||
font: '[name][ext]',
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
html: {
|
html: {
|
||||||
template: './src/static/index.html',
|
template: './src/static/index.html',
|
||||||
|
|||||||
Loaded 100 of 253 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user