Skip to content

Commit 34ca164

Browse files
authored
JS-2007 Document release flows and align SQAA workflow (#7469)
1 parent 4175bfb commit 34ca164

8 files changed

Lines changed: 208 additions & 114 deletions

File tree

.github/workflows/automated-release.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,9 @@ jobs:
5353
new-version: ${{ github.event.inputs.new-version }}
5454
sqc-integration: ${{ github.event.inputs.sqc-integration == 'true' }}
5555
sqs-integration: ${{ github.event.inputs.sqs-integration == 'true' }}
56+
# SonarJS SQAA releases are handled manually from the dedicated SQAA workflow
57+
# and then handed off through sonar-analysis-as-a-service.
58+
sqaa-integration: false
5659
create-slvs-ticket: true
5760
create-slvscode-ticket: true
5861
create-sle-ticket: true

.github/workflows/docker-a3s.yml

Lines changed: 0 additions & 109 deletions
This file was deleted.
Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: Build A3S Docker Image (Repox)
1+
name: Build SQAA Docker Image (Repox)
22

33
on:
44
workflow_dispatch:
@@ -12,6 +12,7 @@ on:
1212
env:
1313
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: 'true'
1414
DOCKER_REPOX_BUILDS_REGISTRY: repox-sonarsource-docker-builds.jfrog.io
15+
# The registry repository still uses the historical a3s prefix.
1516
DOCKER_IMAGE: "a3s/analysis/javascript"
1617

1718
concurrency:
@@ -75,9 +76,14 @@ jobs:
7576
- name: Install NPM dependencies
7677
run: npm ci
7778

78-
- name: Build bundle for Docker
79+
- uses: ./.github/actions/rule-api-cache
80+
81+
- name: Refresh RSPEC rule data
7982
env:
8083
GITHUB_TOKEN: ${{ fromJSON(steps.secrets.outputs.vault).RSPEC_GITHUB_TOKEN }}
84+
run: npm run rspec:refresh
85+
86+
- name: Build bundle for Docker
8187
run: npm run grpc:build
8288

8389
- name: Docker login to Repox registry

docs/DEV.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,8 @@ revision to rebuild against. For direct Maven commands that generate rule data,
114114
You can also use Docker container defined in `./.cirrus/nodejs.Dockerfile` which bundles all
115115
required dependencies and is used for our CI pipeline.
116116

117+
For release procedures, see [RELEASE.md](RELEASE.md).
118+
117119
## Build and run unit tests
118120

119121
On a fresh checkout, or whenever you want the latest RSPEC rule data instead of the tracked JSON

docs/RELEASE.md

Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
# Release Guide
2+
3+
SonarJS currently has two distinct release targets:
4+
5+
| Target | Artifact | Main workflow | Notes |
6+
| --------------------------- | ------------------------------------------ | ----------------------------------------- | ---------------------------------------------------- |
7+
| Standard SonarQube analyzer | Maven/JAR release artifacts | `.github/workflows/automated-release.yml` | This is the normal SonarJS release flow. |
8+
| SQAA (previously A3S) | Docker image for `LanguageAnalyzerService` | `.github/workflows/docker-sqaa.yml` | This is separate from the standard analyzer release. |
9+
10+
## Terminology
11+
12+
- `SQAA` is the current name for what older docs and repository names still call `A3S`.
13+
- Some external identifiers still keep the legacy `a3s` name for compatibility. The important ones are:
14+
- the Docker repository path `a3s/analysis/javascript`
15+
- `packages/grpc/src/proto/language_analyzer.proto` with `option java_package = "com.sonarsource.a3s.analyzer.grpc";`
16+
- Do not rename those compatibility-sensitive identifiers as part of a routine release.
17+
18+
## Standard SonarQube Analyzer Release
19+
20+
This is the regular SonarJS analyzer release. It is the release that produces the standard SonarQube analyzer artifacts. It does **not** build or roll out the SQAA Docker image.
21+
22+
### Entry points
23+
24+
1. Start `.github/workflows/automated-release.yml`.
25+
2. That workflow orchestrates the release and then calls `.github/workflows/release.yml` for the actual artifact publication.
26+
3. After the release succeeds, `.github/workflows/bump-versions.yml` opens the next development iteration PR.
27+
28+
### What `.github/workflows/automated-release.yml` does
29+
30+
The SonarJS workflow is a thin wrapper around `SonarSource/release-github-actions/.github/workflows/automated-release.yml@v1` with SonarJS-specific inputs:
31+
32+
- project name `SonarJS`
33+
- plugin name `javascript`
34+
- Jira project `JS`
35+
- optional SQC and SQS integration PRs
36+
- SLVS, SLVSCODE, SLE, and SLI integration tickets enabled
37+
- SQAA integration explicitly disabled in SonarJS, because SQAA is released manually
38+
39+
The reusable workflow performs the following steps:
40+
41+
1. Freeze the target branch.
42+
2. Run the releasability checks with `SonarSource/gh-action_releasability@v3`.
43+
3. Resolve the release version with `get-release-version`.
44+
4. Resolve the Jira version with `get-jira-version`.
45+
5. Generate Jira-based release notes with `get-jira-release-notes` unless explicit notes were provided.
46+
6. Create the REL Jira ticket with `create-jira-release-ticket`.
47+
7. Publish the GitHub release with `publish-github-release`.
48+
8. Unfreeze the branch.
49+
9. Release the Jira version, create the next Jira version, and move the REL ticket to `Technical Release Done`.
50+
10. Create integration tickets.
51+
11. Open analyzer update PRs for SQS and SQC.
52+
53+
### What `publish-github-release` does in practice
54+
55+
`SonarSource/release-github-actions/publish-github-release` is the handoff from orchestration to artifact publication:
56+
57+
1. It creates or reuses a draft GitHub release for the target version.
58+
2. It can attach Repox artifacts to that release if artifact paths were provided.
59+
3. It inspects `.github/workflows/release.yml` and detects that SonarJS uses the `gh-action_release` v7 draft-first flow.
60+
4. It triggers `.github/workflows/release.yml` with `version=<release-version>` and `dryRun=<draft flag>`.
61+
5. It waits for that workflow to finish and fails the orchestration run if the publication workflow fails.
62+
63+
### What `.github/workflows/release.yml` does
64+
65+
`release.yml` is the workflow that actually publishes the standard analyzer release artifacts. It calls `SonarSource/gh-action_release/.github/workflows/main.yaml@7.4.0` with:
66+
67+
- `publishToBinaries: true`
68+
- `mavenCentralSync: true`
69+
- the release version
70+
- the dry-run flag
71+
72+
That reusable workflow follows the v7 draft-first release model:
73+
74+
1. Create or reuse the draft GitHub release.
75+
2. Run releasability checks again inside the publication workflow.
76+
3. Load Vault secrets and execute `./gh-action_release/main`.
77+
4. Publish the release artifacts to the standard release targets.
78+
5. Sync Maven Central.
79+
6. Publish the draft GitHub release.
80+
7. Push release telemetry to Datadog.
81+
82+
Because this is a draft-first flow, failures after the draft release exists are normally retried by rerunning the workflow. You do not create a new release version just because one publication attempt failed.
83+
84+
### What `.github/workflows/bump-versions.yml` does
85+
86+
SonarJS does **not** use the generic `release-github-actions` version bump action. Instead, after the automated release job finishes, SonarJS runs its own reusable workflow:
87+
88+
1. Check out the repository.
89+
2. Update the root `pom.xml` `<revision>` to `${version}-SNAPSHOT`.
90+
3. Open a PR with `peter-evans/create-pull-request@v8` titled `Prepare next development iteration`.
91+
92+
### Standard release checklist
93+
94+
1. Run `.github/workflows/automated-release.yml`, usually from `master`.
95+
2. Monitor the GitHub release publication kicked off through `.github/workflows/release.yml`.
96+
3. Verify the REL ticket and Jira release were updated.
97+
4. Merge the `Prepare next development iteration` PR.
98+
5. Merge the SQS and SQC integration PRs created by the release automation.
99+
6. Do **not** expect a SQAA Docker image from this flow.
100+
101+
## SQAA Release
102+
103+
SQAA (previously A3S) is released separately from the standard analyzer. The SonarJS side only builds and publishes the Docker image to Repox. The deployment handoff happens afterwards in `SonarSource/sonar-analysis-as-a-service`.
104+
105+
### Artifact
106+
107+
The SQAA artifact is the Docker image built from the repository root `Dockerfile`.
108+
109+
Relevant implementation details:
110+
111+
- `npm run grpc:build` runs `bridge:build:fast` and then `grpc:bundle`
112+
- `grpc:bundle` produces `bin/grpc-server.cjs`
113+
- the Docker image copies `bin/` and starts `node ./bin/grpc-server.cjs 50051`
114+
- the published image tag is the SonarJS build number
115+
116+
### SonarJS workflow
117+
118+
Run `.github/workflows/docker-sqaa.yml` manually.
119+
120+
This workflow does the following:
121+
122+
1. Get a SonarJS build number with `SonarSource/ci-github-actions/get-build-number@master`.
123+
2. Check out the requested branch.
124+
3. Install toolchains with `jdx/mise-action@v4.2.0`:
125+
- Java 21
126+
- Maven 3.9
127+
- Node 24.11.0
128+
4. Configure Maven with `SonarSource/ci-github-actions/config-maven@master`.
129+
5. Configure npm with `SonarSource/ci-github-actions/config-npm@v1`.
130+
6. Read Vault secrets:
131+
- Repox QA deployer credentials
132+
- RSPEC GitHub token
133+
7. Run `npm ci`.
134+
8. Refresh RSPEC rule data with `npm run rspec:refresh`.
135+
9. Run `npm run grpc:build`.
136+
10. Log in to `repox-sonarsource-docker-builds.jfrog.io`.
137+
11. Build and push the Docker image with:
138+
139+
```bash
140+
docker buildx build --platform linux/arm64 --tag "${DOCKER_IMAGE_BUILD_NUMBER}" --push .
141+
```
142+
143+
The image is pushed to:
144+
145+
```text
146+
repox-sonarsource-docker-builds.jfrog.io/a3s/analysis/javascript:<build_number>
147+
```
148+
149+
The `a3s` repository segment is still intentional legacy naming. Do not change it during a routine SQAA release.
150+
151+
### Handoff to `sonar-analysis-as-a-service`
152+
153+
After the SonarJS workflow succeeds:
154+
155+
1. Take the SonarJS build number from the SQAA workflow run.
156+
2. Open a PR in `SonarSource/sonar-analysis-as-a-service`.
157+
3. Update only `analysis/js_ts_image_tag` to that new build number.
158+
159+
Example:
160+
161+
- PR title: `SC-51805 Update JSTS analyzer to 42780`
162+
- diff: `analysis/js_ts_image_tag` changed from `39440` to `42780`
163+
164+
### What happens after that PR is merged
165+
166+
In `SonarSource/sonar-analysis-as-a-service`:
167+
168+
1. `.github/workflows/build.yml` reads `analysis/js_ts_image_tag`.
169+
2. It calls `.github/workflows/pull-and-push-analyzer-image.yml`.
170+
3. That reusable workflow pulls:
171+
172+
```text
173+
repox-sonarsource-docker-builds.jfrog.io/a3s/analysis/javascript:${source_tag}
174+
```
175+
176+
4. It re-tags that image with the `sonar-analysis-as-a-service` build number and pushes it to ECR.
177+
5. The merge to `master` also triggers `.github/workflows/master-deployment.yml`, which starts the deployment workflow for the environments.
178+
179+
### Important warning
180+
181+
Do **not** use the generic `SonarSource/release-github-actions/update-analysis-as-a-service` action for the SonarJS SQAA release.
182+
183+
That generic action updates `gradle/sonar-plugins.versions.toml` in `sonar-analysis-as-a-service`. The current JS/TS SQAA rollout does **not** use that file. The real SonarJS handoff is the manual PR that updates `analysis/js_ts_image_tag`.
184+
185+
### SQAA release checklist
186+
187+
1. Run `.github/workflows/docker-sqaa.yml`.
188+
2. Note the SonarJS build number used as the Docker tag.
189+
3. Open a PR in `SonarSource/sonar-analysis-as-a-service`.
190+
4. Update `analysis/js_ts_image_tag` to that build number.
191+
5. Merge the PR to `master`.
192+
6. Let `sonar-analysis-as-a-service` build and deployment workflows roll out the new image.

docs/grpc-analyze-project-migration.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ Move the internal Java -> Node.js analyze-project communication from HTTP/WebSoc
3232
9. No transport backward compatibility is required. HTTP is dropped.
3333
10. HTTP/WebSocket runtime dependencies should be removed in the same change.
3434
11. Worker retention is a design choice, not a compatibility constraint.
35-
12. The protocol should be designed around analyze-project needs, not around the external A3S contract.
35+
12. The protocol should be designed around analyze-project needs, not around the external SQAA (previously A3S) contract.
3636

3737
## Final Protocol Design
3838

packages/analysis/src/common/configuration.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ export type Configuration = {
8787
disableTypeChecking: boolean /* sonar.javascript.disableTypeChecking - whether to completely disable TypeScript type checking */;
8888
skipNodeModuleLookupOutsideBaseDir: boolean /* sonar.internal.analysis.skipNodeModuleLookupOutsideBaseDir - whether to skip node_modules lookups outside baseDir in TS compiler host */;
8989
ecmaScriptVersion?: string /* sonar.javascript.ecmaScriptVersion - explicit ES version override e.g. 'ES2022' */;
90-
reportNclocForTestFiles: boolean /* In gRPC/A3S context, ncloc for test files is computed by the analyzer. In SQ context, ncloc is not computed for tests. */;
90+
reportNclocForTestFiles: boolean /* In gRPC/SQAA (previously A3S) context, ncloc for test files is computed by the analyzer. In SQ context, ncloc is not computed for tests. */;
9191
};
9292

9393
export type ConfigurationInput = {

packages/grpc/src/transformers/request.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ export function transformSourceFilesToRawInputFiles(
5252
} else {
5353
/* TODO: Infer file scope from context when not explicitly provided by the caller
5454
* calling filterPathAndGetFileType(filename, getFilterPathParams(configuration)),
55-
* but we need configuration from the a3s context
55+
* but we need configuration from the SQAA context
5656
* */
5757
}
5858

0 commit comments

Comments
 (0)