Compare commits
4
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d0da0432af
|
||
|
|
dd527c1443
|
||
|
|
d586e6bb7d
|
||
|
|
7edac8b639
|
No files matched your search
@@ -2,21 +2,12 @@
|
|||||||
#/ 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:BE65d5I9m1jrHGVNKDmfGL3Cjb7LjhB4tVWyNzSPU1Zu5Y00+R8NXgqSBrzBnXVj3vVinibjihVt3fStegyiqI52GtSycX1NlFSVJlRFWadUJ6SVK+SYfB7sFKSJ2jKGfwRaXKMzaKCdPWY+ni685oPXU9Rp"
|
COM_ERMNVLDMR_STATIC_S3_BUCKET="encrypted:BL1vJLB9uPSvsUvrJah4UegRU8uPdFjE7sya+Fae3rwOmVzWsK5+TP4z4YzigTAuwit4FANvANvhRV46se+ZgprYplU8Cw1tZ5mHKO4rWAjif2sJCnsGXUKp8GZ2J7PrMH35MY0YrXX4NVqe18b2NEv2B9K7"
|
||||||
COM_ERMNVLDMR_STATIC_S3_REGION="encrypted:BPQ2+ms76A+PLFUeKL1Cnz8bdOcsJou03e8AyGwzdhozpcAwhP5yWXSqhTK8ZccAvmfjJcM4NK+x2a2r4g0ALd/UaQDa9xy2eZ6QnXwkoHXu2ce+F86/HuFnzX0qWqYTWi4q+N4="
|
COM_ERMNVLDMR_STATIC_S3_REGION="encrypted:BAj3iuo7tWWNR2V4yQ+LHnFCB4JcZp7TTfUtvv+2FPntNhwc/fV95IeFWz6S0z6aPRkDG+UQzPXNwdMz7y8ZbTHbduDDrgydHu1fST1NfQd2s1Bbpf+yJTG7dPBSc5RSNKZkkpB4v55qg/UC"
|
||||||
COM_ERMNVLDMR_STATIC_S3_ENDPOINT_URL="encrypted:BCcK2ih1QrABMImpUj31KIQYlbp9zhnafzrXINAwvyCaCjbOst6UGnhhi5M3LtQ+Fhgpx52ZKGjmke1oVxnvU6BBGz/lAbSD5euhHNbJ6EIoSqc25XpcmgucIQGx1cfiJxsL4sDR95FyR3fNaS9KGr005DwQaIRKGg86gALUCPhaLekq/Sd6Nn+TDoqmigLJPozdxp33AFpmWF+EwayYae2u"
|
COM_ERMNVLDMR_STATIC_S3_ENDPOINT_URL="encrypted:BNkQrgsrxtz544vuJbgwWUh5cPjHG5wbmHNcxTUWrzbFJJsdncaAitviCvIrS7Q41w+FiWkssv3D05Tu8Inn2P62E6G3PU4gNxO2oLdmGEdrzUqB/xvxOvLvos42j54QOZf7lOqMPKH6SL2/rheCAo10gSCicCqkfh4xsCAbYpyL"
|
||||||
COM_ERMNVLDMR_STATIC_AWS_ACCESS_KEY_ID="encrypted:BPaBvzNo1eH3Z2ro+NFq4zLi4krZQT48h20r0etBfVFLDNS01gh5Uosy70Ip29rC8sa1JoP4Q8isJ2Xz0pr5Vxxa62vVFOJ9wJ6LkXbYF2bUm+UNyjfsIztJsMyiVZfPEEPEEKcniXZ3faqePwgLwCZSTa/Qry6znNmMV5FshSsP"
|
COM_ERMNVLDMR_STATIC_AWS_ACCESS_KEY_ID="encrypted:BCsp8p4bp3cB+9grxHo634isRUaFGU3MOc1lr8ClSFRYLjqjqukyrbJCTZWV2Xdo8iQ33EylmbzUltbwzTWMQcjJSvIskesVLyV93q60o/Mu9L9jg/apwHuBgHv4zVuHstJ0zkHWgapbNTIlWD3RCm0ujeX/H1gBH3U="
|
||||||
COM_ERMNVLDMR_STATIC_AWS_SECRET_ACCESS_KEY="encrypted:BFiOxOo/TNvSIMOjyeOswLcl+9AVdqp4axW+I46c1CL0ckSucQS+7CLpO8fNfakmW2bSibqru+xfWUbQT7FDH1YB3CPXUc0qPm1PsG0FiLixDefQuDrC/JHuA0Z3/dOAkn/e94BBuPtyJXxcLRP1v517MijPa0MuNqhI9BS3jFHKjWivqc9AVPs2ybglo14b/nEO1GqlM0TYflPoDhHoWjM="
|
COM_ERMNVLDMR_STATIC_AWS_SECRET_ACCESS_KEY="encrypted:BM7aPliOyiPrqFPZMfqpn534Nu+Y0Nbh/YRoxv2KY6XAi2dNO0LSEf97DqSUQYdsnu9iibZmVNktF2K/D6mtHr9+gumF6KsmaLH65KE7c9ly7NdFQHL9I26wxRq1Sr3Zgrfs954J6oURSlBRKqJFdcTsBltuuupGuqJHyLS9+DE0jD+bl0Qg0lA="
|
||||||
SOPS_AGE_KEY="encrypted:BKiJVxKYhiadu0kNCw8wVLYdaEWZreAVu2PaujxhvcXeCowCGjivEuQD/uhduAy/CwwDWyQkgQJ2FJMEKA47e7QDjS9TMdPCXO19/teR7LThgqTf6AbSM3sebln5zalgyplay4A/7cVytPXuOvVkaYyoh9CgzTVsPJKXRq5yMaDEx/9/91Yo8zUMF3z1vq3/preI5baK4/1xXewR3OwfZqnNGyd7LXkdqyT5"
|
SOPS_AGE_KEY="encrypted:BOJ7q79Tws4DMxpFuSymgv//IC4f+j713Bd7mNlUCEaUYVSfJMayMVPzks0FcsYo12XvlbH6gQ+tCf3t9yj/LcKKJzl3wtxlSVjvCRr0hasEBohcoxkLnFZ73DFQGzWcVC5Jf5IMK7qdYdNVzW0dVY/sn/NlTgl+A3YB6/08XYPhljl9993ky76zQqWDJQ66bKJ7YxWvst2TUNoT0lJEL0M4pg9ztRsuGqNZ"
|
||||||
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="
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
[git.ermnvldmr.com]:22222,[45.150.33.239]:22222 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBXcvf3Lds3AKfGHGh00IWR9tSRbBBqrV/CC6JBGmcrD
|
|
||||||
@@ -1,70 +0,0 @@
|
|||||||
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 }}
|
|
||||||
@@ -1,332 +0,0 @@
|
|||||||
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
|
|
||||||
@@ -1,332 +0,0 @@
|
|||||||
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
|
|
||||||
@@ -1,133 +0,0 @@
|
|||||||
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
|
|
||||||
@@ -1,133 +0,0 @@
|
|||||||
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
|
|
||||||
@@ -1,156 +0,0 @@
|
|||||||
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
|
|
||||||
@@ -1,157 +0,0 @@
|
|||||||
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
|
|
||||||
@@ -1,284 +0,0 @@
|
|||||||
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
|
|
||||||
@@ -1,293 +0,0 @@
|
|||||||
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
|
|
||||||
@@ -1,129 +0,0 @@
|
|||||||
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
|
|
||||||
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: 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=sha,format=short
|
|
||||||
SOURCE_SHA: ${{ github.sha }}
|
|
||||||
- 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
|
|
||||||
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/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="sha-$(echo ${{ github.sha }} | cut -c1-7)"
|
|
||||||
bash ci/scripts/deploy-gitops.sh docs "${DOCS_TAG}"
|
|
||||||
env:
|
|
||||||
GIT_WRITE_KEY: ${{ secrets.DOCS_DEPLOY_KEY }}
|
|
||||||
|
|
||||||
verify-rollout:
|
|
||||||
name: Verify - Production Rollout
|
|
||||||
needs: 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="sha-$(echo ${{ github.sha }} | cut -c1-7)"
|
|
||||||
bash ci/scripts/await-rollout.sh docs "${DOCS_TAG}"
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
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
|
|
||||||
@@ -1,195 +0,0 @@
|
|||||||
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
|
|
||||||
|
|
||||||
'
|
|
||||||
@@ -1,166 +0,0 @@
|
|||||||
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
|
|
||||||
@@ -1,76 +0,0 @@
|
|||||||
name: services/www - manual deploy
|
|
||||||
'on':
|
|
||||||
workflow_dispatch:
|
|
||||||
inputs:
|
|
||||||
tested_sha:
|
|
||||||
description: Full tested source commit
|
|
||||||
required: true
|
|
||||||
type: string
|
|
||||||
tested_digest:
|
|
||||||
description: OCI sha256 digest from the successful build
|
|
||||||
required: true
|
|
||||||
type: string
|
|
||||||
build_run_id:
|
|
||||||
description: Successful WWW build run ID
|
|
||||||
required: true
|
|
||||||
type: string
|
|
||||||
release_tag:
|
|
||||||
description: Previously approved release tag
|
|
||||||
required: true
|
|
||||||
type: string
|
|
||||||
release_run_id:
|
|
||||||
description: Successful manually approved release run ID
|
|
||||||
required: true
|
|
||||||
type: string
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
actions: read
|
|
||||||
jobs:
|
|
||||||
deploy:
|
|
||||||
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
|
|
||||||
- name: Authenticate local registry
|
|
||||||
run: python3 ci/scripts/docker.py login
|
|
||||||
env:
|
|
||||||
REGISTRY: git.ermnvldmr.com
|
|
||||||
REGISTRY_USER: deytenit
|
|
||||||
REGISTRY_TOKEN: ${{ secrets.DEPLOY_REGISTRY_READ_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 }}
|
|
||||||
RELEASE_RUN_ID: ${{ inputs.release_run_id }}
|
|
||||||
RELEASE_TAG: ${{ inputs.release_tag }}
|
|
||||||
- name: Verify approved release and deploy digest
|
|
||||||
env:
|
|
||||||
TESTED_SHA: ${{ inputs.tested_sha }}
|
|
||||||
TESTED_DIGEST: ${{ inputs.tested_digest }}
|
|
||||||
BUILD_RUN_ID: ${{ inputs.build_run_id }}
|
|
||||||
PROVENANCE_TOKEN: ${{ github.token }}
|
|
||||||
RELEASE_RUN_ID: ${{ inputs.release_run_id }}
|
|
||||||
RELEASE_TAG: ${{ inputs.release_tag }}
|
|
||||||
GIT_WRITE_KEY: ${{ secrets.WWW_DEPLOY_KEY }}
|
|
||||||
run: 'set -euo pipefail
|
|
||||||
|
|
||||||
[[ "$RELEASE_TAG" =~ ^[A-Za-z0-9][A-Za-z0-9._-]*$ ]]
|
|
||||||
|
|
||||||
test "$(git rev-parse "$RELEASE_TAG^{commit}")" = "$TESTED_SHA"
|
|
||||||
|
|
||||||
test "$(docker buildx imagetools inspect "git.ermnvldmr.com/deytenit/ermnvldmr.com/www:$RELEASE_TAG"
|
|
||||||
--format ''{{.Manifest.Digest}}'')" = "$TESTED_DIGEST"
|
|
||||||
|
|
||||||
bash ci/scripts/deploy-gitops.sh www "$TESTED_DIGEST"
|
|
||||||
|
|
||||||
'
|
|
||||||
- name: Await production rollout
|
|
||||||
run: bash ci/scripts/await-rollout.sh https://www.ermnvldmr.com/version.json "sha-${TESTED_SHA:0:7}"
|
|
||||||
env:
|
|
||||||
TESTED_SHA: ${{ inputs.tested_sha }}
|
|
||||||
@@ -1,381 +0,0 @@
|
|||||||
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 GitHub 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: Set up Docker Buildx
|
|
||||||
run: 'docker buildx version
|
|
||||||
|
|
||||||
docker buildx create --name apex-ci --driver docker-container --use
|
|
||||||
|
|
||||||
docker buildx inspect --bootstrap'
|
|
||||||
- name: Build and push Docker image
|
|
||||||
run: python3 ci/scripts/docker.py build
|
|
||||||
env:
|
|
||||||
TAGS: git.ermnvldmr.com/${{ github.repository }}/www:${{ steps.vars.outputs.short_sha
|
|
||||||
}}
|
|
||||||
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
|
|
||||||
@@ -1,302 +0,0 @@
|
|||||||
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
|
|
||||||
@@ -1,88 +0,0 @@
|
|||||||
name: services/www - manual release
|
|
||||||
'on':
|
|
||||||
workflow_dispatch:
|
|
||||||
inputs:
|
|
||||||
tested_sha:
|
|
||||||
description: Full tested source commit
|
|
||||||
required: true
|
|
||||||
type: string
|
|
||||||
tested_digest:
|
|
||||||
description: OCI sha256 digest from the successful build
|
|
||||||
required: true
|
|
||||||
type: string
|
|
||||||
build_run_id:
|
|
||||||
description: Successful WWW build run ID
|
|
||||||
required: true
|
|
||||||
type: string
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
actions: read
|
|
||||||
jobs:
|
|
||||||
release:
|
|
||||||
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
|
|
||||||
- name: Authenticate local registry
|
|
||||||
run: python3 ci/scripts/docker.py login
|
|
||||||
env:
|
|
||||||
REGISTRY: git.ermnvldmr.com
|
|
||||||
REGISTRY_USER: deytenit
|
|
||||||
REGISTRY_TOKEN: ${{ secrets.RELEASE_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: ${{ inputs.tested_sha }}
|
|
||||||
TESTED_DIGEST: ${{ inputs.tested_digest }}
|
|
||||||
BUILD_RUN_ID: ${{ inputs.build_run_id }}
|
|
||||||
PROVENANCE_TOKEN: ${{ github.token }}
|
|
||||||
GIT_WRITE_KEY: ${{ secrets.WWW_RELEASE_KEY }}
|
|
||||||
run: 'set -euo pipefail
|
|
||||||
|
|
||||||
VERSION=$(bash ci/scripts/calver-release.sh)
|
|
||||||
|
|
||||||
[[ "$VERSION" =~ ^[A-Za-z0-9][A-Za-z0-9._-]*$ ]]
|
|
||||||
|
|
||||||
if git show-ref --verify --quiet "refs/tags/$VERSION"; then exit 1; fi
|
|
||||||
|
|
||||||
docker buildx imagetools create --prefer-index=false "git.ermnvldmr.com/deytenit/ermnvldmr.com/www@$TESTED_DIGEST"
|
|
||||||
--tag "git.ermnvldmr.com/deytenit/ermnvldmr.com/www:$VERSION"
|
|
||||||
|
|
||||||
test "$(docker buildx imagetools inspect "git.ermnvldmr.com/deytenit/ermnvldmr.com/www:$VERSION"
|
|
||||||
--format ''{{.Manifest.Digest}}'')" = "$TESTED_DIGEST"
|
|
||||||
|
|
||||||
git tag "$VERSION" "$TESTED_SHA"
|
|
||||||
|
|
||||||
python3 ci/scripts/git_write.py "refs/tags/$VERSION"
|
|
||||||
|
|
||||||
export VERSION
|
|
||||||
|
|
||||||
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'': ''deytenit/ermnvldmr.com'', ''release_tag'': os.environ[''VERSION'']}))
|
|
||||||
|
|
||||||
RELEASE_PROVENANCE
|
|
||||||
|
|
||||||
'
|
|
||||||
- uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: www-release-provenance
|
|
||||||
path: .ci/www-release.json
|
|
||||||
retention-days: 30
|
|
||||||
@@ -0,0 +1,134 @@
|
|||||||
|
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
|
||||||
@@ -14,7 +14,7 @@ permissions:
|
|||||||
contents: write
|
contents: write
|
||||||
issues: write
|
issues: write
|
||||||
pull-requests: write
|
pull-requests: write
|
||||||
actions: write
|
actions: read
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
agent-dispatch:
|
agent-dispatch:
|
||||||
@@ -26,15 +26,7 @@ jobs:
|
|||||||
(contains(github.event.comment.body, '/plan') ||
|
(contains(github.event.comment.body, '/plan') ||
|
||||||
contains(github.event.comment.body, '/implement') ||
|
contains(github.event.comment.body, '/implement') ||
|
||||||
contains(github.event.comment.body, '/fix'))
|
contains(github.event.comment.body, '/fix'))
|
||||||
runs-on: [self-hosted, eliza]
|
runs-on: ubuntu-latest
|
||||||
container:
|
|
||||||
image: node:20-bookworm
|
|
||||||
options: --add-host host.docker.internal:host-gateway
|
|
||||||
env:
|
|
||||||
HTTP_PROXY: http://host.docker.internal:1080
|
|
||||||
HTTPS_PROXY: http://host.docker.internal:1080
|
|
||||||
ALL_PROXY: http://host.docker.internal:1080
|
|
||||||
NO_PROXY: localhost,127.0.0.1
|
|
||||||
timeout-minutes: 30
|
timeout-minutes: 30
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
@@ -48,13 +40,6 @@ jobs:
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
- name: Ensure GitHub CLI is Installed
|
|
||||||
run: |
|
|
||||||
if ! command -v gh &> /dev/null; then
|
|
||||||
echo "Installing GitHub CLI..."
|
|
||||||
curl -fsSL https://github.com/cli/cli/releases/download/v2.67.0/gh_2.67.0_linux_amd64.tar.gz | tar -xz -C /usr/local --strip-components=1
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Acknowledge Command (Add Eyes Reaction)
|
- name: Acknowledge Command (Add Eyes Reaction)
|
||||||
if: success()
|
if: success()
|
||||||
env:
|
env:
|
||||||
@@ -98,48 +83,19 @@ jobs:
|
|||||||
|
|
||||||
- name: Setup Antigravity CLI & Credentials
|
- name: Setup Antigravity CLI & Credentials
|
||||||
env:
|
env:
|
||||||
GH_TOKEN: ${{ secrets.GITOPS_TOKEN || secrets.GITHUB_TOKEN }}
|
|
||||||
AGY_AUTH_TOKEN: ${{ secrets.AGY_AUTH_TOKEN }}
|
AGY_AUTH_TOKEN: ${{ secrets.AGY_AUTH_TOKEN }}
|
||||||
run: |
|
run: |
|
||||||
# 1. Download official Antigravity CLI binary from google-antigravity/antigravity-cli
|
# 1. Install Antigravity CLI (agy) if not present
|
||||||
mkdir -p "$HOME/.local/bin"
|
|
||||||
if ! command -v agy &> /dev/null; then
|
if ! command -v agy &> /dev/null; then
|
||||||
echo "Fetching Antigravity CLI from google-antigravity/antigravity-cli..."
|
echo "Installing Antigravity CLI (agy)..."
|
||||||
gh release download --repo google-antigravity/antigravity-cli -p "agy_cli_linux_x64.tar.gz" -O - | tar -xz -C "$HOME/.local/bin"
|
curl -fsSL https://antigravity.google/install.sh | bash || true
|
||||||
if [ -f "$HOME/.local/bin/antigravity" ] && [ ! -f "$HOME/.local/bin/agy" ]; then
|
mkdir -p "$HOME/.local/bin"
|
||||||
mv "$HOME/.local/bin/antigravity" "$HOME/.local/bin/agy"
|
echo "$HOME/.local/bin" >> $GITHUB_PATH
|
||||||
fi
|
echo "$HOME/.gemini/antigravity-cli/bin" >> $GITHUB_PATH
|
||||||
ln -sf "$HOME/.local/bin/agy" "$HOME/.local/bin/antigravity"
|
export PATH="$HOME/.local/bin:$HOME/.gemini/antigravity-cli/bin:$PATH"
|
||||||
chmod +x "$HOME/.local/bin/agy" "$HOME/.local/bin/antigravity"
|
|
||||||
fi
|
fi
|
||||||
echo "$HOME/.local/bin" >> $GITHUB_PATH
|
|
||||||
echo "$HOME/.gemini/antigravity-cli/bin" >> $GITHUB_PATH
|
|
||||||
export PATH="$HOME/.local/bin:$HOME/.gemini/antigravity-cli/bin:$PATH"
|
|
||||||
|
|
||||||
# 2. Patch location eligibility check (open-antigravity-patcher CLI_GATE_X64)
|
# 2. Inject OAuth Token
|
||||||
node -e '
|
|
||||||
const fs = require("fs");
|
|
||||||
const file = process.env.HOME + "/.local/bin/agy";
|
|
||||||
if (!fs.existsSync(file)) process.exit(0);
|
|
||||||
const buf = fs.readFileSync(file);
|
|
||||||
let count = 0;
|
|
||||||
for (let i = 0; i < buf.length - 18; i++) {
|
|
||||||
if (buf[i] === 0x48 && buf[i+1] === 0x85 && buf[i+2] === 0xc0 && buf[i+3] === 0x0f && buf[i+4] === 0x84 &&
|
|
||||||
buf[i+9] === 0x80 && buf[i+10] === 0x78 && buf[i+11] === 0x08 && buf[i+12] === 0x00 &&
|
|
||||||
buf[i+13] === 0x0f && buf[i+14] === 0x85) {
|
|
||||||
buf[i+9] = 0x48; buf[i+10] = 0x85; buf[i+11] = 0xc0; buf[i+12] = 0x90;
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (count > 0) {
|
|
||||||
fs.writeFileSync(file, buf);
|
|
||||||
console.log(`Applied open-antigravity-patcher: ${count} gates patched.`);
|
|
||||||
} else {
|
|
||||||
console.log("Antigravity CLI is already patched or signature not found.");
|
|
||||||
}
|
|
||||||
'
|
|
||||||
|
|
||||||
# 3. Inject OAuth Token
|
|
||||||
mkdir -p ~/.gemini/antigravity-cli
|
mkdir -p ~/.gemini/antigravity-cli
|
||||||
if [ -n "$AGY_AUTH_TOKEN" ]; then
|
if [ -n "$AGY_AUTH_TOKEN" ]; then
|
||||||
if echo "$AGY_AUTH_TOKEN" | base64 --decode >/dev/null 2>&1; then
|
if echo "$AGY_AUTH_TOKEN" | base64 --decode >/dev/null 2>&1; then
|
||||||
@@ -154,9 +110,8 @@ jobs:
|
|||||||
|
|
||||||
- name: Configure Git Bot Identity
|
- name: Configure Git Bot Identity
|
||||||
run: |
|
run: |
|
||||||
git config --global user.name "Adam Jensen [bot]"
|
git config --global user.name "AI Assistant Bot"
|
||||||
git config --global user.email "adam@ermnvldmr.com"
|
git config --global user.email "bot@users.noreply.github.com"
|
||||||
git config --global --add safe.directory "$GITHUB_WORKSPACE"
|
|
||||||
|
|
||||||
# --- COMMAND: /plan ---
|
# --- COMMAND: /plan ---
|
||||||
- name: Handle /plan (Issue Planning)
|
- name: Handle /plan (Issue Planning)
|
||||||
@@ -174,9 +129,9 @@ jobs:
|
|||||||
CONTINUE_FLAG="--continue"
|
CONTINUE_FLAG="--continue"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
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 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 --dangerously-skip-permissions --print-timeout 20m -p "$PROMPT" || echo "Agent encountered an error generating the plan.")
|
PLAN_OUTPUT=$(agy $CONTINUE_FLAG --mode plan -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}"
|
||||||
@@ -199,8 +154,8 @@ jobs:
|
|||||||
CONTINUE_FLAG="--continue"
|
CONTINUE_FLAG="--continue"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
PROMPT="You are operating via GitHub Actions in non-interactive headless mode to implement Issue #${ISSUE_NUMBER}.\n\nContext:\n${ISSUE_DATA}\n\nLatest instruction:\n${COMMENT_BODY}\n\nTask: Inspect relevant files, implement the necessary code changes directly in the workspace adhering to GEMINI.md rules, and verify them. Do not exit or stop before applying edits to the source code."
|
PROMPT="You are operating via GitHub Actions to implement Issue #${ISSUE_NUMBER}.\n\nContext:\n${ISSUE_DATA}\n\nLatest instruction:\n${COMMENT_BODY}\n\nImplement the changes cleanly in the repository according to GEMINI.md rules."
|
||||||
agy $CONTINUE_FLAG --dangerously-skip-permissions --print-timeout 25m -p "$PROMPT"
|
agy $CONTINUE_FLAG --dangerously-skip-permissions -p "$PROMPT"
|
||||||
|
|
||||||
echo "Running repository verification gates..."
|
echo "Running repository verification gates..."
|
||||||
pnpm typecheck
|
pnpm typecheck
|
||||||
@@ -235,7 +190,6 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
IS_PR="${{ github.event.issue.pull_request != null }}"
|
IS_PR="${{ github.event.issue.pull_request != null }}"
|
||||||
if [ "$IS_PR" = "true" ]; then
|
if [ "$IS_PR" = "true" ]; then
|
||||||
# Verify PR is not from an untrusted cross-repository fork
|
|
||||||
IS_CROSS_REPO=$(gh pr view "$ISSUE_OR_PR_NUMBER" --json isCrossRepository -q .isCrossRepository)
|
IS_CROSS_REPO=$(gh pr view "$ISSUE_OR_PR_NUMBER" --json isCrossRepository -q .isCrossRepository)
|
||||||
if [ "$IS_CROSS_REPO" = "true" ]; then
|
if [ "$IS_CROSS_REPO" = "true" ]; then
|
||||||
echo "::error::Cross-repository fork PRs cannot be automatically processed in privileged context."
|
echo "::error::Cross-repository fork PRs cannot be automatically processed in privileged context."
|
||||||
@@ -258,8 +212,8 @@ jobs:
|
|||||||
CONTINUE_FLAG="--continue"
|
CONTINUE_FLAG="--continue"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
PROMPT="You are operating via GitHub Actions in non-interactive headless mode to fix/adjust PR #${ISSUE_OR_PR_NUMBER} on branch ${BRANCH_NAME}.\n\nFeedback / Comment:\n${COMMENT_BODY}\n\nPR Diff:\n${PR_DIFF}\n\nFailed CI Logs (if any):\n${CI_LOGS}\n\nTask: Apply the necessary fixes directly to the files, ensuring all lint, typecheck, and test checks pass. Do not exit without applying the changes."
|
PROMPT="You are operating via GitHub Actions to fix/adjust PR #${ISSUE_OR_PR_NUMBER} on branch ${BRANCH_NAME}.\n\nFeedback / Comment:\n${COMMENT_BODY}\n\nPR Diff:\n${PR_DIFF}\n\nFailed CI Logs (if any):\n${CI_LOGS}\n\nApply the necessary fixes, making sure all lint, typecheck, and test checks pass."
|
||||||
agy $CONTINUE_FLAG --dangerously-skip-permissions --print-timeout 25m -p "$PROMPT"
|
agy $CONTINUE_FLAG --dangerously-skip-permissions -p "$PROMPT"
|
||||||
|
|
||||||
echo "Running repository verification gates..."
|
echo "Running repository verification gates..."
|
||||||
pnpm typecheck
|
pnpm typecheck
|
||||||
@@ -283,8 +237,8 @@ jobs:
|
|||||||
git checkout -b "$BRANCH_NAME"
|
git checkout -b "$BRANCH_NAME"
|
||||||
|
|
||||||
ISSUE_DATA=$(gh issue view "$ISSUE_OR_PR_NUMBER" --comments --json title,body,comments)
|
ISSUE_DATA=$(gh issue view "$ISSUE_OR_PR_NUMBER" --comments --json title,body,comments)
|
||||||
PROMPT="You are operating via GitHub Actions in non-interactive headless mode to fix issue #${ISSUE_OR_PR_NUMBER}.\n\nContext:\n${ISSUE_DATA}\n\nInstruction:\n${COMMENT_BODY}\n\nTask: Apply the necessary fixes directly to the files adhering to GEMINI.md rules."
|
PROMPT="Fix issue #${ISSUE_OR_PR_NUMBER}.\n\nContext:\n${ISSUE_DATA}\n\nInstruction:\n${COMMENT_BODY}"
|
||||||
agy --dangerously-skip-permissions --print-timeout 25m -p "$PROMPT"
|
agy --dangerously-skip-permissions -p "$PROMPT"
|
||||||
|
|
||||||
pnpm typecheck
|
pnpm typecheck
|
||||||
pnpm lint
|
pnpm lint
|
||||||
@@ -0,0 +1,361 @@
|
|||||||
|
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
|
||||||
@@ -0,0 +1,361 @@
|
|||||||
|
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
|
||||||
@@ -0,0 +1,145 @@
|
|||||||
|
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
|
||||||
@@ -0,0 +1,145 @@
|
|||||||
|
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
|
||||||
@@ -0,0 +1,176 @@
|
|||||||
|
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
|
||||||
@@ -0,0 +1,176 @@
|
|||||||
|
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
|
||||||
@@ -0,0 +1,313 @@
|
|||||||
|
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
|
||||||
@@ -0,0 +1,322 @@
|
|||||||
|
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
|
||||||
@@ -0,0 +1,166 @@
|
|||||||
|
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
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
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
|
||||||
@@ -0,0 +1,204 @@
|
|||||||
|
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
|
||||||
@@ -0,0 +1,177 @@
|
|||||||
|
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
|
||||||
@@ -0,0 +1,486 @@
|
|||||||
|
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
|
||||||
@@ -0,0 +1,331 @@
|
|||||||
|
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,9 +25,6 @@ playwright-report/
|
|||||||
.env
|
.env
|
||||||
.env.keys
|
.env.keys
|
||||||
|
|
||||||
# local development certificates
|
|
||||||
.certs/
|
|
||||||
|
|
||||||
# macOS-specific files
|
# macOS-specific files
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|
||||||
@@ -46,9 +43,3 @@ 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: "age15zq3cje3ttmx2fhqp9cpeght6feq2w8e5m38799stjetj8urcccs36r4rc,age1jpa7hqyzzdfq7lvnw3l8qy6648mtjgpcqnljl5jz92dcqjrnsqfsn7m0fl"
|
age: "age1jpa7hqyzzdfq7lvnw3l8qy6648mtjgpcqnljl5jz92dcqjrnsqfsn7m0fl"
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
# [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
|
||||||
|
|
||||||
@@ -57,7 +58,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`
|
- **Testing**: `pnpm test` or `pnpm test:coverage` (View results on [Codecov](https://app.codecov.io/github/deytenit/ermnvldmr.com))
|
||||||
- **Code Quality**: `pnpm lint` and `pnpm typecheck`
|
- **Code Quality**: `pnpm lint` and `pnpm typecheck`
|
||||||
|
|
||||||
### Designer
|
### Designer
|
||||||
|
|||||||
@@ -35,8 +35,186 @@ write_files:
|
|||||||
# public key: age1jpa7hqyzzdfq7lvnw3l8qy6648mtjgpcqnljl5jz92dcqjrnsqfsn7m0fl
|
# public key: age1jpa7hqyzzdfq7lvnw3l8qy6648mtjgpcqnljl5jz92dcqjrnsqfsn7m0fl
|
||||||
AGE-SECRET-KEY-1PLACEHOLDERFORYOURPRIVATEAGEKEY
|
AGE-SECRET-KEY-1PLACEHOLDERFORYOURPRIVATEAGEKEY
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ----------------------------------------------------------------------------
|
||||||
# 3. Bootstrap Cluster (Pre-baked script mounts disk, starts K3s, and syncs Flux)
|
# 3. Security Hardening Configuration
|
||||||
# ------------------------------------------------------------------------------
|
# ----------------------------------------------------------------------------
|
||||||
|
- 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,16 +5,6 @@ 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;
|
||||||
@@ -35,15 +25,13 @@ 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" always;
|
add_header Cache-Control "public, immutable";
|
||||||
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" always;
|
add_header Cache-Control "public, no-transform";
|
||||||
add_header Access-Control-Allow-Origin "*" always;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# English locale — SPA fallback for non-asset routes
|
# English locale — SPA fallback for non-asset routes
|
||||||
@@ -60,7 +48,6 @@ 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: git.ermnvldmr.com/deytenit/ermnvldmr.com/docs:sha-91f5245
|
image: ghcr.io/deytenit/ermnvldmr.com/docs:sha-91f5245
|
||||||
imagePullPolicy: IfNotPresent
|
imagePullPolicy: IfNotPresent
|
||||||
ports:
|
ports:
|
||||||
- name: http
|
- name: http
|
||||||
|
|||||||
@@ -5,6 +5,5 @@ resources:
|
|||||||
- deployment.yaml
|
- deployment.yaml
|
||||||
- service.yaml
|
- service.yaml
|
||||||
images:
|
images:
|
||||||
- name: git.ermnvldmr.com/deytenit/ermnvldmr.com/docs
|
- name: ghcr.io/deytenit/ermnvldmr.com/docs
|
||||||
newName: git.ermnvldmr.com/deytenit/ermnvldmr.com/docs
|
newTag: sha-ea805c7
|
||||||
newTag: sha-4e0bb72
|
|
||||||
@@ -12,20 +12,11 @@ sops:
|
|||||||
age:
|
age:
|
||||||
- enc: |
|
- enc: |
|
||||||
-----BEGIN AGE ENCRYPTED FILE-----
|
-----BEGIN AGE ENCRYPTED FILE-----
|
||||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBRWFNtaHhPbmlodUZXSFgy
|
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAxRXIvMEpaWU1XNjV2OFpp
|
||||||
S1YwUjc4ZnZWdy9TM1NiejdrRHJuZnR5aG5rCjJrMWY2OXExZkpmUHpUNTE1T05x
|
Z1lYb25kOFVVaXlRYkdzSmxWbmxqaXR6TEhRCnF0M2ovRVNmdTU3WnNOcy82OExV
|
||||||
dzBYbmI3ZmVHRlhXaHk5dFFEMjIxUUUKLS0tIEd0L2N4TUsxV0tjWm81cUQ4dVdS
|
YXNjZVJrbTdXQWJxMjQvNEdZNlBwcjAKLS0tIEEzczNmZjFwT1d2aXVKV1Bvdm1Q
|
||||||
WDVuSGxuNVAxeVk2UUdhQnFDV1FZOW8K4Fc8T/XM+E6F0iOqpSMbh/pOAI2vq3am
|
UnZoNVNCYjJiYWd6WlNobGEyUGh5NmMKkUTDkYlNkXH8DegvBT7ymkL7h1B9x77N
|
||||||
9rMDxzwfIL9hwNDoy5LVPdnBfOXlCoZ8OnMR9Euj8FBW6pHErkmBUA==
|
IxeZI5mp8vc347/620+cbMMr2+aELlgs9/bJhUcLRm0Bv8UDVLOleg==
|
||||||
-----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,4 +6,3 @@ 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,8 +17,6 @@ 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,20 +11,11 @@ sops:
|
|||||||
age:
|
age:
|
||||||
- enc: |
|
- enc: |
|
||||||
-----BEGIN AGE ENCRYPTED FILE-----
|
-----BEGIN AGE ENCRYPTED FILE-----
|
||||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA4SHJWSm54SHorbTZBOGtF
|
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBGZ2h6THNGTnY2ay9Tc2Q3
|
||||||
VkRrQlpHbTgxSkh3L2ljZW42emEzQlBHa0hvCmxuQ3VjR2hQNzVlZ3FVS2Q3THp4
|
S0xxU3NEZGx2TS9MRFdqZDV6aEtUalBWRFVJCjZMd1VCdkg1cjIxSlliZXNRQnU0
|
||||||
SEZGa09EM1BYSlUxWEtuMGp0Tld3R3cKLS0tIEcwcUd6ZkdDdTAvMDFtSGpCZ3ls
|
YnMzTXJOSGdsUDUwNkdDdWZWcmRaZjgKLS0tIDdEOFoyOWtvZytITys4bk9ra082
|
||||||
TVJYdHRDMXlWVmx4WStsT2hGUUZkeEkK26wJbgH0yvKPFXR4TC2rdeBD0axAs4WU
|
WmFIREJMS1BVU0o1VnZHby9ZSHN4cGcKReBW7hdTPH8eGqPzEYkOdrIUYm9a1jOi
|
||||||
rfJ8MWet6AbEAyOmiAjigNbM9bJwGlDW1UThnGQ/fFQfJW6U4T1Tgw==
|
du/1fhAyhjimbbCNdOSuSjrSP8QX6mxwPoDb1dVlKi0Rah5VGW+HWw==
|
||||||
-----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: git.ermnvldmr.com/deytenit/ermnvldmr.com/www:sha-6d33b71
|
image: ghcr.io/deytenit/ermnvldmr.com/www:sha-6d33b71
|
||||||
imagePullPolicy: IfNotPresent
|
imagePullPolicy: IfNotPresent
|
||||||
ports:
|
ports:
|
||||||
- name: http
|
- name: http
|
||||||
|
|||||||
@@ -5,6 +5,5 @@ resources:
|
|||||||
- deployment.yaml
|
- deployment.yaml
|
||||||
- service.yaml
|
- service.yaml
|
||||||
images:
|
images:
|
||||||
- name: git.ermnvldmr.com/deytenit/ermnvldmr.com/www
|
- name: ghcr.io/deytenit/ermnvldmr.com/www
|
||||||
newName: git.ermnvldmr.com/deytenit/ermnvldmr.com/www
|
newTag: sha-a60b095
|
||||||
newTag: sha-4e0bb72
|
|
||||||
@@ -5,7 +5,7 @@ metadata:
|
|||||||
namespace: flux-system
|
namespace: flux-system
|
||||||
spec:
|
spec:
|
||||||
interval: 1m
|
interval: 1m
|
||||||
url: https://git.ermnvldmr.com/deytenit/ermnvldmr.com.git
|
url: https://github.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:
|
||||||
- install.yaml
|
- https://github.com/cert-manager/cert-manager/releases/download/v1.17.0/cert-manager.yaml
|
||||||
- cluster-issuer.yaml
|
- cluster-issuer.yaml
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
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,18 +1,23 @@
|
|||||||
apiVersion: networking.k8s.io/v1
|
apiVersion: networking.k8s.io/v1
|
||||||
kind: Ingress
|
kind: Ingress
|
||||||
metadata:
|
metadata:
|
||||||
name: www-ingress
|
name: main-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:
|
||||||
@@ -24,23 +29,6 @@ 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:
|
||||||
@@ -51,23 +39,6 @@ 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,9 +2,3 @@ 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
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
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=()"
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
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;"
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
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;"
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
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;"
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
apiVersion: traefik.io/v1alpha1
|
|
||||||
kind: Middleware
|
|
||||||
metadata:
|
|
||||||
name: strip-beacon
|
|
||||||
namespace: com-ermnvldmr
|
|
||||||
spec:
|
|
||||||
stripPrefix:
|
|
||||||
prefixes:
|
|
||||||
- /trace
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
[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-genericcloud-amd64.qcow2"
|
default = "https://cloud.debian.org/images/cloud/bookworm/latest/debian-12-nocloud-amd64.qcow2"
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "debian_cloud_image_checksum" {
|
variable "debian_cloud_image_checksum" {
|
||||||
@@ -42,8 +42,6 @@ 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,45 +85,4 @@ 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,8 +9,7 @@ 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
|
||||||
install -m 0755 /tmp/scripts/k3s /usr/local/bin/k3s
|
curl -sfL https://get.k3s.io | sh -
|
||||||
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
|
||||||
@@ -20,117 +19,7 @@ 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 and default config
|
# Create configuration directory
|
||||||
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,21 +4,6 @@ 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
|
||||||
|
|||||||
@@ -1,63 +0,0 @@
|
|||||||
#!/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)
|
|
||||||
echo " Live commit: ${LIVE_COMMIT:-<none>}"
|
|
||||||
|
|
||||||
if [ "$LIVE_COMMIT" = "$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
|
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
#!/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."
|
|
||||||
@@ -1,87 +0,0 @@
|
|||||||
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()
|
|
||||||
@@ -19,25 +19,17 @@ 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"
|
||||||
IMAGE="git.ermnvldmr.com/deytenit/ermnvldmr.com/${SERVICE}"
|
kustomize edit set image "ghcr.io/deytenit/ermnvldmr.com/${SERVICE}:${TAG}"
|
||||||
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 "APEX CI"
|
git config user.name "adam-at-deytenit"
|
||||||
git config user.email "adam@ermnvldmr.com"
|
git config user.email "221188529+adam-at-deytenit@users.noreply.github.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 --no-gpg-sign -m "chore(release): deploy ${SERVICE} ${TAG} [skip ci]"
|
git commit -m "chore(release): deploy ${SERVICE} ${TAG} [skip ci]"
|
||||||
python3 "$ROOT_DIR/ci/scripts/git_write.py" HEAD:next
|
git push origin next
|
||||||
echo "Successfully deployed $SERVICE ($TAG) via GitOps."
|
echo "Successfully deployed $SERVICE ($TAG) via GitOps."
|
||||||
fi
|
fi
|
||||||
@@ -29,23 +29,14 @@ 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"
|
||||||
|
|
||||||
# Set S3 max_concurrent_requests to 1 to prevent race conditions on S3-compatible endpoints
|
# Upload all static files
|
||||||
aws configure set default.s3.max_concurrent_requests 1
|
|
||||||
|
|
||||||
# Upload all static files with retry
|
|
||||||
echo "Uploading static files..."
|
echo "Uploading static files..."
|
||||||
for attempt in 1 2 3; do
|
aws s3 cp "$DIST_DIR/" "s3://$S3_BUCKET/" \
|
||||||
echo "Attempt $attempt/3: syncing static files..."
|
--recursive \
|
||||||
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 "Error: Failed to upload static files after 3 attempts."
|
echo "Static files deployed successfully!"
|
||||||
exit 1
|
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
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()
|
|
||||||
@@ -1,334 +0,0 @@
|
|||||||
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}`);
|
|
||||||
}
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
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._-]*',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="${1:-$SCRIPT_DIR/../../services/www/public/static}"
|
STATIC_DIR="$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."
|
||||||
|
|||||||
@@ -1,113 +0,0 @@
|
|||||||
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('Full source SHA required')
|
|
||||||
if not re.fullmatch(r'sha256:[0-9a-f]{64}', digest):
|
|
||||||
raise ValueError('OCI sha256 digest required')
|
|
||||||
if not re.fullmatch(r'[1-9][0-9]*', run_id):
|
|
||||||
raise ValueError('Numeric build run ID required')
|
|
||||||
|
|
||||||
|
|
||||||
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') != run_id:
|
|
||||||
raise ValueError('Immutable image provenance mismatch')
|
|
||||||
|
|
||||||
|
|
||||||
def validate_manifest(manifest, sha, digest, run_id):
|
|
||||||
expected = {'sha': sha, 'digest': digest, 'run_id': run_id, 'repository': REPO}
|
|
||||||
if manifest != expected:
|
|
||||||
raise ValueError('Build artifact does not attest requested image digest')
|
|
||||||
|
|
||||||
|
|
||||||
def artifact_manifest(run_id, name='www-provenance', filename='www-provenance.json'):
|
|
||||||
artifacts = api('/actions/runs/' + 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('Exactly one unexpired build provenance artifact required')
|
|
||||||
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, digest, run_id = os.environ['TESTED_SHA'], os.environ['TESTED_DIGEST'], os.environ['BUILD_RUN_ID']
|
|
||||||
validate_input(sha, digest, run_id)
|
|
||||||
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')
|
|
||||||
validate_run(api('/actions/runs/' + run_id), sha)
|
|
||||||
validate_manifest(artifact_manifest(run_id), sha, digest, run_id)
|
|
||||||
if os.environ.get('RELEASE_RUN_ID'):
|
|
||||||
release_id = os.environ['RELEASE_RUN_ID']
|
|
||||||
if not re.fullmatch(r'[1-9][0-9]*', release_id):
|
|
||||||
raise ValueError('Numeric release run ID required')
|
|
||||||
release = api('/actions/runs/' + release_id)
|
|
||||||
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 actor.get('login') != 'deytenit':
|
|
||||||
raise ValueError('Successful independently approved release required')
|
|
||||||
manifest = artifact_manifest(release_id, 'www-release-provenance', 'www-release.json')
|
|
||||||
expected = {'sha': sha, 'digest': digest, 'run_id': run_id, 'repository': REPO, 'release_tag': os.environ['RELEASE_TAG']}
|
|
||||||
if manifest != expected:
|
|
||||||
raise ValueError('Release approval does not match requested artifact')
|
|
||||||
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('short_sha=sha-' + sha[:7] + '\n')
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
#!/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
|
|
||||||
@@ -1,130 +0,0 @@
|
|||||||
#!/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 "=========================================================================="
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
#!/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
@@ -0,0 +1,53 @@
|
|||||||
|
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
|
||||||
+1
-4
@@ -14,10 +14,7 @@ export default [
|
|||||||
// Additional ignores for monorepo
|
// Additional ignores for monorepo
|
||||||
{
|
{
|
||||||
ignores: [
|
ignores: [
|
||||||
'services/docs/public/**',
|
'services/docs/**/*', // Hugo content, no linting needed
|
||||||
'services/docs/resources/**',
|
|
||||||
'services/docs/assets/**',
|
|
||||||
'services/docs/archetypes/**',
|
|
||||||
'**/node_modules/**',
|
'**/node_modules/**',
|
||||||
'**/dist/**',
|
'**/dist/**',
|
||||||
'**/build/**',
|
'**/build/**',
|
||||||
|
|||||||
@@ -32,7 +32,6 @@
|
|||||||
"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",
|
||||||
@@ -42,7 +41,6 @@
|
|||||||
"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.1.11"
|
"vitest": "^4.0.18"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -297,112 +297,4 @@ 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,7 +53,6 @@ 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;
|
||||||
|
|
||||||
@@ -150,13 +149,6 @@ 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}`;
|
||||||
@@ -164,17 +156,12 @@ 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 configured pattern or default `src/**/*.{ts,tsx,css,md,mdx}`
|
// Find workspace source files matching `src/**/*.{ts,tsx,css,md,mdx}`
|
||||||
const filePattern = cmd.sourceFilesPattern ?? 'src/**/*.{ts,tsx,css,md,mdx}';
|
const sourceFiles = await fg('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
|
||||||
@@ -183,38 +170,28 @@ 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 (!hasMatchingPrefix(content)) {
|
if (!content.includes('/static/')) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const originalContent = content;
|
let modified = false;
|
||||||
|
|
||||||
for (const asset of sortedAssets) {
|
for (const asset of sortedAssets) {
|
||||||
const namesToSearch =
|
let searchName = asset.originalName;
|
||||||
asset.finalName !== asset.originalName
|
if (searchName.startsWith('static/')) {
|
||||||
? [asset.originalName, asset.finalName]
|
searchName = searchName.substring('static/'.length);
|
||||||
: [asset.originalName];
|
} else if (searchName.startsWith('/static/')) {
|
||||||
|
searchName = searchName.substring('/static/'.length);
|
||||||
|
}
|
||||||
|
const searchStr = `/static/${searchName}`;
|
||||||
|
const assetUrl = getS3Url(asset.finalName);
|
||||||
|
|
||||||
for (const prefix of urlPrefixes) {
|
if (content.includes(searchStr)) {
|
||||||
const cleanPrefix = prefix.replace(/^\/+|\/+$/g, '');
|
content = content.split(searchStr).join(assetUrl);
|
||||||
|
modified = true;
|
||||||
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 = `/${cleanPrefix}/${searchName}`;
|
|
||||||
const assetUrl = getS3Url(asset.finalName);
|
|
||||||
const escaped = searchStr.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
||||||
const regex = new RegExp('(?<!https?:\\/\\/[^\\s"\'`()]*)' + escaped, 'g');
|
|
||||||
|
|
||||||
content = content.replace(regex, assetUrl);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (content !== originalContent) {
|
if (modified) {
|
||||||
await fs.promises.writeFile(sourceFile, content, 'utf-8');
|
await fs.promises.writeFile(sourceFile, content, 'utf-8');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -106,10 +106,6 @@ 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 */
|
||||||
@@ -118,8 +114,6 @@ 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,9 +10,6 @@
|
|||||||
"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",
|
||||||
|
|||||||
@@ -1,31 +0,0 @@
|
|||||||
// @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,7 +6,6 @@ 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.
|
||||||
@@ -39,9 +38,6 @@ export function defineBaseConfig(rootDir) {
|
|||||||
...jsdocConfig,
|
...jsdocConfig,
|
||||||
...testingConfig,
|
...testingConfig,
|
||||||
...toolingConfig,
|
...toolingConfig,
|
||||||
...i18nConfig,
|
|
||||||
...defineMonorepoRestrictedImports(rootDir),
|
...defineMonorepoRestrictedImports(rootDir),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
export { i18nConfig };
|
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
// @ts-check
|
// @ts-check
|
||||||
import path from 'node:path';
|
import path from 'node:path';
|
||||||
import { defineBaseConfig, i18nConfig } from './config/index.js';
|
import { defineBaseConfig } 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, '../../../../');
|
||||||
@@ -11,4 +10,4 @@ const rootDir = path.resolve(import.meta.dirname, '../../../../');
|
|||||||
*/
|
*/
|
||||||
export const baseConfig = defineBaseConfig(rootDir);
|
export const baseConfig = defineBaseConfig(rootDir);
|
||||||
|
|
||||||
export { defineBaseConfig, i18nConfig, i18nPlugin };
|
export { defineBaseConfig };
|
||||||
@@ -1,61 +0,0 @@
|
|||||||
// @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: [],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
};
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
// @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,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
@@ -1,310 +0,0 @@
|
|||||||
// @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,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
};
|
|
||||||
@@ -1,251 +0,0 @@
|
|||||||
// @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,7 +5,6 @@
|
|||||||
"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",
|
||||||
@@ -45,6 +44,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.1.11"
|
"vitest": "^4.0.18"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6,9 +6,6 @@
|
|||||||
"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",
|
||||||
@@ -68,7 +65,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.1.11",
|
"vitest": "^4.0.18",
|
||||||
"wait-on": "^8.0.3"
|
"wait-on": "^8.0.3"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
|
|||||||
@@ -11,33 +11,4 @@ describe('PageHead', () => {
|
|||||||
expect(screen.getAllByText('Test Heading').length).toBeGreaterThan(0);
|
expect(screen.getAllByText('Test Heading').length).toBeGreaterThan(0);
|
||||||
expect(screen.getByText('Test Caption')).toBeInTheDocument();
|
expect(screen.getByText('Test Caption')).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('renders breadcrumbs and addons in both expanded and collapsed views', () => {
|
|
||||||
render(
|
|
||||||
<PageHead
|
|
||||||
addonLeft={<span>Logo Left</span>}
|
|
||||||
addonRight={<span>Nav Menu</span>}
|
|
||||||
breadcrumbs={<span>Breadcrumbs Trail</span>}
|
|
||||||
heading="Wanted"
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(screen.getAllByText('Breadcrumbs Trail').length).toBe(2);
|
|
||||||
expect(screen.getAllByText('Nav Menu').length).toBe(2);
|
|
||||||
expect(screen.getAllByText('Logo Left').length).toBe(2);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('renders correctly with always-collapsed-fixed strategy', () => {
|
|
||||||
render(
|
|
||||||
<PageHead
|
|
||||||
addonLeft={<span>Brand Logo</span>}
|
|
||||||
addonRight={<nav>Nav Links</nav>}
|
|
||||||
heading="Home Page"
|
|
||||||
strategy="always-collapsed-fixed"
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(screen.getAllByText('Brand Logo').length).toBeGreaterThan(0);
|
|
||||||
expect(screen.getAllByText('Nav Links').length).toBeGreaterThan(0);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
@@ -76,28 +76,22 @@ export function PageHead({
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isCollapsible) {
|
if (isCollapsible) {
|
||||||
setIsCollapsed(scrollY > 150);
|
setIsCollapsed(scrollY > 200);
|
||||||
}
|
}
|
||||||
}, [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>
|
<PageContainer paddingY="medium">
|
||||||
{hasTopBar && (
|
<VStack align="stretch" gap={6}>
|
||||||
<PageContainer paddingY="none">
|
<HStack align="center" justify="between">
|
||||||
<HStack align="center" className="min-h-[60px] py-2.5" gap={4} justify="between" wrap="wrap">
|
<HStack align="center" gap={4}>
|
||||||
<HStack align="center" className="flex-1" gap={4}>
|
{addonLeft && <div>{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>
|
|
||||||
{addonRight && <div className="flex-shrink-0">{addonRight}</div>}
|
|
||||||
</HStack>
|
</HStack>
|
||||||
</PageContainer>
|
{addonRight && <div>{addonRight}</div>}
|
||||||
)}
|
</HStack>
|
||||||
<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' ? (
|
||||||
@@ -108,21 +102,16 @@ export function PageHead({
|
|||||||
caption
|
caption
|
||||||
)}
|
)}
|
||||||
</VStack>
|
</VStack>
|
||||||
</PageContainer>
|
</VStack>
|
||||||
</div>
|
</PageContainer>
|
||||||
);
|
);
|
||||||
|
|
||||||
const collapsedContent = (
|
const collapsedContent = (
|
||||||
<PageContainer paddingY="none">
|
<PageContainer paddingY="none">
|
||||||
<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 text-label-l [&_ol]:text-label-l">{breadcrumbs}</div>}
|
<Header className="min-w-0" level={4} overflow="ellipsis">
|
||||||
<Header
|
|
||||||
className={cn('min-w-0', breadcrumbs && 'sm:hidden')}
|
|
||||||
level={4}
|
|
||||||
overflow="ellipsis"
|
|
||||||
>
|
|
||||||
{heading}
|
{heading}
|
||||||
</Header>
|
</Header>
|
||||||
</HStack>
|
</HStack>
|
||||||
|
|||||||
@@ -7,8 +7,7 @@
|
|||||||
"./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",
|
||||||
@@ -27,6 +26,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.1.11"
|
"vitest": "^4.0.18"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,3 +1,2 @@
|
|||||||
export * from './rsbuild.js';
|
export * from './rsbuild.js';
|
||||||
export * from './server.js';
|
|
||||||
export * from './vitest.js';
|
export * from './vitest.js';
|
||||||
@@ -26,6 +26,9 @@ 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',
|
||||||
|
|||||||
@@ -1,135 +0,0 @@
|
|||||||
import { existsSync, readFileSync, unlinkSync, writeFileSync } from 'node:fs';
|
|
||||||
import { tmpdir } from 'node:os';
|
|
||||||
import { join } from 'node:path';
|
|
||||||
import { describe, expect, it } from 'vitest';
|
|
||||||
|
|
||||||
import {
|
|
||||||
ensureDevCertificates,
|
|
||||||
ensureHostsEntry,
|
|
||||||
findWorkspaceRoot,
|
|
||||||
hasHostsEntry,
|
|
||||||
loadDevRootCaKey,
|
|
||||||
localDevServer,
|
|
||||||
} from './server.js';
|
|
||||||
|
|
||||||
describe('server dev configuration', () => {
|
|
||||||
it('locates the workspace root with pnpm-workspace.yaml', () => {
|
|
||||||
const root = findWorkspaceRoot();
|
|
||||||
expect(existsSync(`${root}/pnpm-workspace.yaml`)).toBe(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('ensures dev certificates exist and returns existing paths', () => {
|
|
||||||
const certs = ensureDevCertificates();
|
|
||||||
expect(existsSync(certs.certPath)).toBe(true);
|
|
||||||
expect(existsSync(certs.keyPath)).toBe(true);
|
|
||||||
expect(certs.caCertPath).toBeDefined();
|
|
||||||
if (certs.caCertPath) {
|
|
||||||
expect(existsSync(certs.caCertPath)).toBe(true);
|
|
||||||
expect(certs.caCertPath).toContain('ErmnvldmrDevelopmentRootCA.pem');
|
|
||||||
}
|
|
||||||
expect(certs.certPath).toContain('.certs/localhost.ermnvldmr.com.pem');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('loads dev root CA key from environment variable when present', () => {
|
|
||||||
const prevKey = process.env.COM_ERMNVLDMR_DEV_ROOT_CA_KEY;
|
|
||||||
try {
|
|
||||||
process.env.COM_ERMNVLDMR_DEV_ROOT_CA_KEY = 'mock-key-value\\nwith-newline';
|
|
||||||
const key = loadDevRootCaKey();
|
|
||||||
expect(key).toBe('mock-key-value\nwith-newline');
|
|
||||||
} finally {
|
|
||||||
if (prevKey !== undefined) {
|
|
||||||
process.env.COM_ERMNVLDMR_DEV_ROOT_CA_KEY = prevKey;
|
|
||||||
} else {
|
|
||||||
delete process.env.COM_ERMNVLDMR_DEV_ROOT_CA_KEY;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('loads dev root CA key from .env.dev when available', () => {
|
|
||||||
const prevKey = process.env.COM_ERMNVLDMR_DEV_ROOT_CA_KEY;
|
|
||||||
delete process.env.COM_ERMNVLDMR_DEV_ROOT_CA_KEY;
|
|
||||||
try {
|
|
||||||
const key = loadDevRootCaKey();
|
|
||||||
expect(key).toBeDefined();
|
|
||||||
if (key) {
|
|
||||||
expect(key).toContain('BEGIN PRIVATE KEY');
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
if (prevKey !== undefined) {
|
|
||||||
process.env.COM_ERMNVLDMR_DEV_ROOT_CA_KEY = prevKey;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('returns production configuration without https when NODE_ENV is production', () => {
|
|
||||||
const prevEnv = process.env.NODE_ENV;
|
|
||||||
try {
|
|
||||||
process.env.NODE_ENV = 'production';
|
|
||||||
const config = localDevServer({ port: 3000 });
|
|
||||||
expect(config.port).toBe(3000);
|
|
||||||
expect(config.https).toBeUndefined();
|
|
||||||
} finally {
|
|
||||||
process.env.NODE_ENV = prevEnv;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('configures dev server with https and formatted urls for localhost.ermnvldmr.com', () => {
|
|
||||||
const prevEnv = process.env.NODE_ENV;
|
|
||||||
try {
|
|
||||||
process.env.NODE_ENV = 'development';
|
|
||||||
const config = localDevServer({ port: 3000 });
|
|
||||||
expect(config.host).toBe('0.0.0.0');
|
|
||||||
expect(config.port).toBe(3000);
|
|
||||||
expect(config.cors).toBe(true);
|
|
||||||
expect(config.https).toBeDefined();
|
|
||||||
|
|
||||||
if (typeof config.printUrls === 'function') {
|
|
||||||
const urls = config.printUrls({
|
|
||||||
protocol: 'https',
|
|
||||||
port: 3000,
|
|
||||||
urls: [],
|
|
||||||
routes: [],
|
|
||||||
});
|
|
||||||
expect(urls).toEqual(['https://localhost.ermnvldmr.com:3000']);
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
process.env.NODE_ENV = prevEnv;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('detects entries correctly in hosts file', () => {
|
|
||||||
const mockHostsPath = join(tmpdir(), `hosts-test-${Date.now()}`);
|
|
||||||
try {
|
|
||||||
writeFileSync(mockHostsPath, '127.0.0.1 localhost\n# 127.0.0.1 localhost.ermnvldmr.com\n');
|
|
||||||
expect(hasHostsEntry('localhost.ermnvldmr.com', mockHostsPath)).toBe(false);
|
|
||||||
|
|
||||||
writeFileSync(
|
|
||||||
mockHostsPath,
|
|
||||||
'127.0.0.1 localhost\n127.0.0.1 localhost.ermnvldmr.com other.domain\n'
|
|
||||||
);
|
|
||||||
expect(hasHostsEntry('localhost.ermnvldmr.com', mockHostsPath)).toBe(true);
|
|
||||||
} finally {
|
|
||||||
if (existsSync(mockHostsPath)) unlinkSync(mockHostsPath);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('appends missing entry to writable hosts file', () => {
|
|
||||||
const mockHostsPath = join(tmpdir(), `hosts-test-${Date.now()}`);
|
|
||||||
try {
|
|
||||||
writeFileSync(mockHostsPath, '127.0.0.1 localhost\n');
|
|
||||||
const added = ensureHostsEntry('localhost.ermnvldmr.com', '127.0.0.1', mockHostsPath);
|
|
||||||
expect(added).toBe(true);
|
|
||||||
|
|
||||||
const content = readFileSync(mockHostsPath, 'utf8');
|
|
||||||
expect(content).toContain('127.0.0.1 localhost.ermnvldmr.com');
|
|
||||||
expect(hasHostsEntry('localhost.ermnvldmr.com', mockHostsPath)).toBe(true);
|
|
||||||
} finally {
|
|
||||||
if (existsSync(mockHostsPath)) unlinkSync(mockHostsPath);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('rejects invalid domain or ip in ensureHostsEntry', () => {
|
|
||||||
expect(ensureHostsEntry('invalid domain with spaces', '127.0.0.1')).toBe(false);
|
|
||||||
expect(ensureHostsEntry('localhost.ermnvldmr.com', 'invalid-ip-format')).toBe(false);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
Loaded 100 of 252 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user