Use this template when the repository has multiple frontend modules such as `web` and `admin`.
## Replace these placeholders
-`__RUNNER_TAG__`
-`__BUILD_IMAGE__`
-`__RELEASE_IMAGE__`
-`__WEB_PACKAGE_DIR__`
-`__WEB_INSTALL_COMMAND__`
-`__WEB_BUILD_COMMAND__`
-`__WEB_DIST_SUBDIR__`
-`__WEB_OSS_NAME__`
-`__WEB_TAG_PREFIX__`
-`__ADMIN_PACKAGE_DIR__`
-`__ADMIN_INSTALL_COMMAND__`
-`__ADMIN_BUILD_COMMAND__`
-`__ADMIN_DIST_SUBDIR__`
-`__ADMIN_OSS_NAME__`
-`__ADMIN_TAG_PREFIX__`
## Default behavior
1.`build_web` and `build_admin` compile independently.
2. Each module writes its output to its own transfer directory.
3.`release_web` and `release_admin` package and upload independently.
4. Dist directories are normalized to `/cache/transfer/${CI_PIPELINE_ID}/web/dist` and `/cache/transfer/${CI_PIPELINE_ID}/admin/dist`.
5. Only tags matching the configured module prefix trigger that module pair.
6. Prefer an official Node image such as `node:16-alpine` or `node:24-alpine`, selected from project evidence.
## Package manager rule
Choose each module's install and build commands from the checked-in repository:
- npm module: `__WEB_INSTALL_COMMAND__` could be `npm install`, `__WEB_BUILD_COMMAND__` could be `npm run build`
- pnpm module: `__ADMIN_INSTALL_COMMAND__` could be `pnpm install --frozen-lockfile`, `__ADMIN_BUILD_COMMAND__` could be `pnpm run build --filter=@vben/web-antdv-next`
- yarn module: use `yarn install --frozen-lockfile` plus the module's real build command
Do not assume all modules use `pnpm` just because one copied project note mentions it.
Do not use `npm ci` as the default npm install command in this template.
## Prefix design rule
On older GitLab versions, use simple non-overlapping prefixes.
3. Verify whether any copied “项目级说明” block is factual for this repo or only a reusable example; do not assume it is true without checking.
4. Map each environment to a concrete build command.
5. Detect the Node major version from primary evidence and prefer an official `node:X-alpine` image with the matching major version.
6. Decide whether helper scripts under `ci/` reduce repetition.
7. Generate `build_x + release_x` pairs only for active environments.
8. If the user wants one tag to run only one pair, assign unique tag prefixes per pair.
9. Remove paused environments completely, including matching release jobs and documentation references.
10. If the repository or user provides a release snippet, preserve its release image, script signature, uploader contract, and variable names unless explicitly asked to migrate.
11. Validate YAML and shell syntax.
12. Update usage docs if you changed active jobs, file names, or release behavior.
If you need per-environment selective triggering on GitLab 11.x, prefer `only: refs + variables` with disjoint prefixes.
Good: `demo-default-*` and `demo-bingo-*`
Bad: `demo-*` and `demo-bingo-*` together, because the first pattern also matches the second.
## Recommended prefix conventions
Use prefixes that are:
1. Human-readable
2. Mutually exclusive
3. Stable across time
Recommended patterns:
- Single environment only: keep one explicit prefix such as `release-*`
- Default plus variant: `demo-default-*`, `demo-bingo-*`
- Many environments: `dev-bingo-*`, `qsh-bingo-*`, `demo-bingo-*`
- Many modules: `web-*`, `admin-*`
- Run all pairs intentionally: `all-*`
Avoid designing prefixes that need complex regex subtraction to distinguish them.
Avoid these on old GitLab unless verified:
-`extends`
-`needs`
-`rules`
-`workflow`
-`parallel:matrix`
- child pipeline syntax
- negative lookahead or other advanced regex features that older GitLab variable expressions may reject
## Default file set
When the request is to build a reusable CI setup, create these files when useful:
-`.gitlab-ci.yml`
-`ci/build-dist.sh`
-`ci/release-dist.sh`
-`CI_USAGE.md`
If the repository follows the common frontend release pattern, start from the bundled asset template in `assets/gitlab-tag-release-template/` and then trim or expand jobs to match only the active environments.
If the repository has two or more frontend modules, start from `assets/gitlab-multi-frontend-template/` and replace the module-specific placeholders before adding or removing pairs.
## Default build script behavior
`ci/build-dist.sh` usually should:
1. Read build target and build command name from arguments.
2. Install dependencies with the repository package manager.
3. Enter the module directory.
4. Run the specific build command.
5. Copy `dist` to `$TRANSFER_BASE_DIR/<target>/dist`.
Pick the install command from real repository evidence:
-`pnpm install --frozen-lockfile` when the repo actually uses `pnpm`
-`npm install` when the repo actually uses `npm`
-`yarn install --frozen-lockfile` when the repo actually uses `yarn`
Do not force `pnpm` because a copied comment block says so if the checked-in repository does not support it.
Do not use `npm ci` in this skill. For npm-based repositories, use `npm install`.
## Default release script behavior
`ci/release-dist.sh` usually should:
1. Read build target and publish name from arguments.
2. Load dist from `$TRANSFER_BASE_DIR/<target>/dist`.
3. Generate dated and latest zip files.
4. If uploader only accepts directories, copy each zip into a dedicated upload directory.
5. Call the uploader for the dated package and latest package.
Default to OSS-oriented release logic. Only switch to server-directory deployment when the repository already uses that model and the user wants to preserve it.
If the repository or the user already established a release contract such as `springjk/ci-helper:latest` and `OSS_DEPLOY_NAME`, preserve that contract exactly unless the user explicitly requests a migration.
## Common failure patterns
### `unknown keys: extends`
The GitLab instance is too old for the chosen syntax.
Replace `extends` with YAML anchors and merge keys.
### `unknown keys: needs`
Use stage ordering only.
Do not add `needs` on GitLab 11.1.4.
### `only 变量 invalid expression syntax`
The GitLab instance may reject advanced regex syntax.
Replace complex expressions with simple prefix matches and redesign prefixes so they do not overlap.
Example: replace `demo-*` plus `demo-bingo-*` with `demo-default-*` plus `demo-bingo-*`.
### Tag can’t trigger any job
The configured prefixes may not match the tag the user is actually creating, or the CI may have been rewritten from selective routing to all-tags or vice versa without confirming intent.
Re-check the real build-script-to-prefix mapping and ensure the selected tag format matches one concrete `build_x + release_x` pair.
### Skill copied a sample project section as if it were real
The “第二部分:项目级说明” may be a reusable example rather than a description of the current repository.
Treat it as a hint, then confirm against `package.json`, root scripts, and existing CI before applying it.
### Custom repository image drift
Using a project-specific custom image can hide the actual Node version decision and make CI less portable.
Prefer official images such as `node:16-alpine` or `node:24-alpine`, selected from project evidence.
### `npm ci` breaks the build setup
Some repositories or runner environments fail on `npm ci` even though `npm install` works normally.
For npm-based repositories in this skill, always use `npm install`.
### Uploader says source path not found
The uploader may expect a directory instead of a file.
Stage the zip file inside an upload directory, then pass the directory path to the uploader.
### Release template lost the required OSS contract
The skill may have simplified release into `artifacts`, a generic Alpine image, or a different script signature and accidentally removed the real uploader flow.
Re-check whether the repository or the user already specified a release image, `oss-deploy`, `OSS_DEPLOY_NAME`, or a fixed `ci/release-dist.sh` call shape.
When those exist, they are not optional hints. Restore them and align every `release_x` job to the same contract.
### UI shows jobs the user no longer wants
Remove the matching `build_x` and `release_x` jobs together.
Also remove outdated references in usage docs and sample paths.
## Anti-patterns
Do not do these unless the user explicitly wants them:
- Do not replace the standard `build_x + release_x` OSS flow with server-directory deployment.
- Do not replace an existing or user-specified OSS release template such as `springjk/ci-helper:latest` plus `sh ci/release-dist.sh "$BUILD_TARGET" "$OSS_DEPLOY_NAME"` with a generic image, `artifacts`, or another release contract.
- Do not use custom repository-specific Node images when an official `node:X-alpine` image can be selected from project evidence.
- Do not treat copied “项目级说明” sections as proven facts without checking the repository.
- Do not use `npm ci` as the default npm install command.
- Do not leave only `build_x` without `release_x` when the default OSS release pattern is expected.