Skip to content

Commit e5957d6

Browse files
SiyaoIsHidingabsurdfarce
authored andcommitted
CASSNODEJS-3: Public CI after Donation
Patch by Jane He; reviewed by Jorge Bay Gondra, Bret McGuire, and Kavin Gupta
1 parent d3ddcbf commit e5957d6

8 files changed

Lines changed: 263 additions & 75 deletions

File tree

.github/workflows/test.yml

Lines changed: 218 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,218 @@
1+
name: Unit and Integration Tests for Apache Cassandra NodeJS Driver
2+
3+
on:
4+
push:
5+
pull_request:
6+
workflow_dispatch: # allow manual trigger from Actions page
7+
permissions:
8+
contents: read
9+
actions: read
10+
checks: write
11+
jobs:
12+
eslint:
13+
name: Run eslint
14+
runs-on: ubuntu-latest
15+
steps:
16+
- uses: actions/checkout@v4
17+
- uses: actions/setup-node@v4
18+
with:
19+
node-version: 20
20+
cache: "npm"
21+
- run: npm install -g eslint@4
22+
- run: npm run eslint
23+
24+
typescript:
25+
name: TypeScript generation and compilation tests
26+
runs-on: ubuntu-latest
27+
strategy:
28+
matrix:
29+
NODE_VERSION: ["20", "22", "24"]
30+
TSC_VERSION: ["4.9", "5.9", "6.0"]
31+
fail-fast: false
32+
steps:
33+
- uses: actions/checkout@v4
34+
- uses: actions/setup-node@v4
35+
with:
36+
node-version: ${{ matrix.NODE_VERSION }}
37+
cache: "npm"
38+
39+
- run: npm ci
40+
41+
- run: npm install typescript@${{ matrix.TSC_VERSION }} --no-save
42+
43+
- run: |
44+
pushd test/unit/typescript/
45+
npx tsc
46+
node -e "require('./api-generation-test').generate()" > generated.ts
47+
npx tsc --noEmit
48+
49+
unit-integration-tests:
50+
runs-on: ubuntu-latest
51+
strategy:
52+
matrix:
53+
NODE_VERSION: ["20", "22", "24"]
54+
SERVER_VERSION: ["3.11", "4.0", "4.1", "5.0"] # Cassandra minor versions
55+
fail-fast: false
56+
57+
steps:
58+
- name: Checkout
59+
uses: actions/checkout@v4
60+
61+
# ---- Python for ccm ----
62+
- name: Set up Python 3.9.16
63+
uses: actions/setup-python@v5
64+
with:
65+
python-version: "3.9.16"
66+
67+
- name: Install ccm
68+
run: |
69+
python -m pip install --upgrade pip
70+
git clone --depth 1 --single-branch -b cassandra-test https://github.com/apache/cassandra-ccm.git
71+
cd cassandra-ccm
72+
pip install -r requirements.txt
73+
./setup.py install
74+
75+
# ---- Install required Zulu JDKs (8/11/17) and capture their homes ----
76+
- name: Install Zulu 11
77+
id: z11
78+
uses: actions/setup-java@v5
79+
with:
80+
distribution: zulu
81+
java-version: "11"
82+
83+
- name: Install Zulu 17
84+
id: z17
85+
uses: actions/setup-java@v5
86+
with:
87+
distribution: zulu
88+
java-version: "17"
89+
90+
- name: Install Zulu 8
91+
id: z8
92+
uses: actions/setup-java@v5
93+
with:
94+
distribution: zulu
95+
java-version: "8"
96+
97+
- name: Export JAVA*_HOME variables
98+
run: |
99+
echo "JAVA8_HOME=${{ steps.z8.outputs.path }}" >> "$GITHUB_ENV"
100+
echo "JAVA11_HOME=${{ steps.z11.outputs.path }}" >> "$GITHUB_ENV"
101+
echo "JAVA17_HOME=${{ steps.z17.outputs.path }}" >> "$GITHUB_ENV"
102+
echo "JAVA_HOME=${{ steps.z8.outputs.path }}" >> "$GITHUB_ENV"
103+
104+
- name: Generate SSL certificates
105+
run: |
106+
mkdir -p /home/runner/workspace/tools/ccm/ssl/
107+
cd /home/runner/workspace/tools/ccm/ssl/
108+
keytool -genkey \
109+
-keyalg RSA \
110+
-alias cassandra \
111+
-keystore keystore.jks \
112+
-storepass cassandra \
113+
-keypass cassandra \
114+
-validity 364635 \
115+
-dname "CN=Jane He, OU=TE, O=ASF, L=Santa Clara, ST=CA, C=TE"
116+
keytool -export \
117+
-alias cassandra \
118+
-file cassandra.crt \
119+
-keystore keystore.jks \
120+
-storepass cassandra
121+
openssl x509 \
122+
-inform der \
123+
-in cassandra.crt \
124+
-out cassandra.pem
125+
keytool -genkeypair \
126+
-keyalg RSA \
127+
-alias client \
128+
-keystore truststore.jks \
129+
-storepass cassandra \
130+
-keypass cassandra \
131+
-validity 364635 \
132+
-dname "CN=Philip Thompson, OU=TE, O=DataStax, L=Santa Clara, ST=CA, C=TE"
133+
keytool -importkeystore \
134+
-srckeystore truststore.jks \
135+
-destkeystore client.p12 \
136+
-srcstorepass cassandra \
137+
-deststorepass cassandra \
138+
-deststoretype PKCS12
139+
openssl pkcs12 \
140+
-in client.p12 \
141+
-passin pass:cassandra \
142+
-nokeys \
143+
-out client_cert.pem -legacy
144+
openssl pkcs12 \
145+
-in client.p12 \
146+
-passin pass:cassandra \
147+
-nodes \
148+
-nocerts \
149+
-out client_key.pem -legacy
150+
151+
- name: Install Simulacron
152+
run: |
153+
wget https://github.com/datastax/simulacron/releases/download/0.12.0/simulacron-standalone-0.12.0.jar -O /home/runner/simulacron.jar
154+
155+
- name: Set up Node.js
156+
uses: actions/setup-node@v4
157+
with:
158+
node-version: ${{ matrix.NODE_VERSION }}
159+
cache: "npm"
160+
161+
- name: Resolve Cassandra latest patch version
162+
env:
163+
SERVER_VERSION: ${{ matrix.SERVER_VERSION }}
164+
run: |
165+
PATCH_SERVER_VERSION=$(
166+
curl -s https://downloads.apache.org/cassandra/ \
167+
| grep -oP '(?<=href=")[0-9]+\.[0-9]+\.[0-9]+(?=)' \
168+
| sort -rV \
169+
| uniq -w 3 \
170+
| grep "^${SERVER_VERSION}\."
171+
)
172+
echo "Resolved Cassandra ${SERVER_VERSION}.x -> ${PATCH_SERVER_VERSION}"
173+
echo "CCM_VERSION=$PATCH_SERVER_VERSION" >> "$GITHUB_ENV"
174+
175+
- name: Print environment
176+
run: printenv | sort
177+
178+
- name: Run tests
179+
run: |
180+
npm ci
181+
npm install --no-save mocha-multi-reporters mocha-junit-reporter
182+
echo '{
183+
"reporterEnabled": "spec, mocha-junit-reporter",
184+
"mochaJunitReporterReporterOptions": {
185+
"mochaFile": "test-results/results.xml"
186+
}
187+
}' > config.json
188+
189+
npx mocha test/unit test/integration/short --recursive --exit --reporter mocha-multi-reporters \
190+
--reporter-options configFile=config.json
191+
192+
- name: Upload Test Results
193+
if: (!cancelled())
194+
uses: actions/upload-artifact@v4
195+
with:
196+
name: Test Results (Node.js ${{ matrix.NODE_VERSION }}, Cassandra ${{ matrix.SERVER_VERSION }})
197+
path: test-results/**/*
198+
199+
publish-test-results:
200+
name: "Publish Tests Results"
201+
needs: unit-integration-tests
202+
runs-on: ubuntu-latest
203+
permissions:
204+
checks: write
205+
pull-requests: write
206+
207+
if: (!cancelled())
208+
209+
steps:
210+
- name: Download Artifacts
211+
uses: actions/download-artifact@v4
212+
with:
213+
path: artifacts
214+
215+
- name: Publish Test Results
216+
uses: EnricoMi/publish-unit-test-result-action@v2
217+
with:
218+
files: artifacts/**/*.xml

.travis.yml

Lines changed: 0 additions & 45 deletions
This file was deleted.

package-lock.json

Lines changed: 10 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
"license": "Apache-2.0",
2121
"types": "./index.d.ts",
2222
"dependencies": {
23-
"@types/node": "^18.11.18",
23+
"@types/node": "^20.14.8",
2424
"adm-zip": "~0.5.10",
2525
"long": "~5.2.3"
2626
},

test/integration/short/metadata-tests.js

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -184,14 +184,20 @@ describe('metadata @SERVER_API', function () {
184184
});
185185
});
186186
describe('#getTokenRanges()', function () {
187-
it('should return 512 ranges', function (done) {
188-
// as vnodes are enabled and there are 2 nodes, expect 512 (2* 256) ranges.
187+
it('should return the correct number of ranges', function (done) {
189188
const client = newInstance();
190189
utils.series([
191190
client.connect.bind(client),
192-
function getRanges(next) {
191+
async function getRanges(next) {
192+
// Query system tables to get actual tokens
193+
const localRs = await client.execute('SELECT tokens FROM system.local');
194+
let tokenCount = localRs.rows[0].tokens.length;
195+
const peersRs = await client.execute('SELECT tokens FROM system.peers');
196+
peersRs.rows.forEach(row => {
197+
if (row.tokens) {tokenCount += row.tokens.length;}
198+
});
193199
const ranges = client.metadata.getTokenRanges();
194-
assert.strictEqual(ranges.size, 512);
200+
assert.strictEqual(ranges.size, tokenCount);
195201
next();
196202
},
197203
client.shutdown.bind(client)
@@ -206,18 +212,24 @@ describe('metadata @SERVER_API', function () {
206212
helper.toTask(client.execute, client, "CREATE KEYSPACE ksrf1 WITH replication = {'class': 'SimpleStrategy', 'replication_factor' : 1}"),
207213
helper.toTask(client.execute, client, "CREATE KEYSPACE ksrf2 WITH replication = {'class': 'SimpleStrategy', 'replication_factor' : 2}"),
208214
helper.toTask(client.execute, client, "CREATE KEYSPACE ksntsrf2 WITH replication = {'class': 'NetworkTopologyStrategy', 'dc1' : 2}"),
209-
function getRanges(next) {
215+
async function getRanges(next) {
216+
// Query system tables to get actual tokens
217+
const localRs = await client.execute('SELECT tokens FROM system.local');
218+
let tokenCount = localRs.rows[0].tokens.length;
219+
const peersRs = await client.execute('SELECT tokens FROM system.peers');
220+
peersRs.rows.forEach(row => {
221+
if (row.tokens) {tokenCount += row.tokens.length;}
222+
});
210223
const host1 = helper.findHost(client, 1);
211224
const host2 = helper.findHost(client, 2);
212225
// the sum of ranges between host1 and host2 should be the total number of tokens.
213-
// we can't make an exact assertion here because token assignment is not exact.
214226
const rf1Ranges = client.metadata.getTokenRangesForHost('ksrf1', host1).size + client.metadata.getTokenRangesForHost('ksrf1', host2).size;
215-
assert.strictEqual(rf1Ranges, 512);
216-
// expect 512 ranges for each host (2 replica = 512 tokens)
217-
assert.strictEqual(client.metadata.getTokenRangesForHost('ksrf2', host1).size, 512);
218-
assert.strictEqual(client.metadata.getTokenRangesForHost('ksrf2', host2).size, 512);
219-
assert.strictEqual(client.metadata.getTokenRangesForHost('ksntsrf2', host1).size, 512);
220-
assert.strictEqual(client.metadata.getTokenRangesForHost('ksntsrf2', host2).size, 512);
227+
assert.strictEqual(rf1Ranges, tokenCount);
228+
// expect tokenCount ranges for each host (2 replica = tokenCount tokens)
229+
assert.strictEqual(client.metadata.getTokenRangesForHost('ksrf2', host1).size, tokenCount);
230+
assert.strictEqual(client.metadata.getTokenRangesForHost('ksrf2', host2).size, tokenCount);
231+
assert.strictEqual(client.metadata.getTokenRangesForHost('ksntsrf2', host1).size, tokenCount);
232+
assert.strictEqual(client.metadata.getTokenRangesForHost('ksntsrf2', host2).size, tokenCount);
221233
next();
222234
},
223235
client.shutdown.bind(client)

0 commit comments

Comments
 (0)