Skip to content

Commit fa6774f

Browse files
authored
Merge branch 'master' into chore/funnels-delete-confirmation-copy-changelog
2 parents 1f0905c + 272db17 commit fa6774f

File tree

32 files changed

+3104
-617
lines changed

32 files changed

+3104
-617
lines changed

.github/workflows/main.yml

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,13 @@ jobs:
278278
wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb -O /tmp/chrome.deb
279279
apt install -y /tmp/chrome.deb
280280
281+
- name: Install Sharp dependencies for image processing
282+
shell: bash
283+
run: |
284+
export DEBIAN_FRONTEND=noninteractive
285+
apt-get update -y
286+
apt-get install -y libvips-dev
287+
281288
- name: Copy code
282289
shell: bash
283290
run: cp -rf ./* /opt/countly
@@ -331,6 +338,6 @@ jobs:
331338
working-directory: /opt/countly/ui-tests/cypress
332339
run: |
333340
ARTIFACT_ARCHIVE_NAME="$(date '+%Y%m%d-%H.%M')_${GITHUB_REPOSITORY#*/}_CI#${{ github.run_number }}_${{ matrix.test_type }}.tar.gz"
334-
mkdir -p screenshots videos
335-
tar zcvf "$ARTIFACT_ARCHIVE_NAME" screenshots videos
341+
mkdir -p screenshots videos downloads
342+
tar zcvf "$ARTIFACT_ARCHIVE_NAME" screenshots videos downloads
336343
curl -o /tmp/uploader.log -u "${{ secrets.BOX_UPLOAD_AUTH }}" ${{ secrets.BOX_UPLOAD_PATH }} -T "$ARTIFACT_ARCHIVE_NAME"

CHANGELOG.md

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,56 @@
1-
## Version 25.03.XX
1+
## Version 25.03.xx
2+
Fixes:
3+
- [push] Fixed timeout setting
4+
- [security] Fixed injection possibility on res.expose
5+
6+
Enterprise Fixes:
7+
- [groups] Add logs for user updates
8+
- [nps] Sort widgets by internal name and search by name or internal name
9+
- [surveys] Change question map log to debug log
10+
- [surveys] Sort widgets by internal name and search by name or internal name
11+
12+
Enterprise Fixes:
13+
- [data-manager] Fixed bug when merging events with ampersand symbol in the name
14+
15+
Dependencies:
16+
- Bump axios from 1.12.2 to 1.13.1 in /plugins/cognito
17+
- Bump csvtojson from 1.1.12 to 2.0.14
18+
- Bump eslint-plugin-vue from 10.5.0 to 10.5.1
19+
- Bump express-rate-limit from 8.1.0 to 8.2.0
20+
- Bump get-random-values from 4.0.0 to 4.1.0
21+
- Bump lint-staged from 16.2.4 to 16.2.6
22+
- Bump mockttp from 4.2.0 to 4.2.1 in /plugins/crash_symbolication
23+
- Bump nodemailer from 7.0.9 to 7.0.10
24+
- Bump puppeteer from 24.25.0 to 24.27.0
25+
- Bump vite from 7.1.10 to 7.1.12
26+
27+
## Version 25.03.25
28+
Fixes:
29+
- [crashes] Fixed resolving audit log recording
30+
- [location] Fixed updating none gps coordinate location after gps location was used
31+
232
Enterprise Fixes:
33+
- [ab-testing] Add script for fixing variant cohort
34+
- [groups] Fix user permission update after updating user group permission
35+
36+
## Version 25.03.24
37+
Fixes:
38+
- [jobs] Fix condition for scheduling alert job
39+
40+
Enterprise Fixes:
41+
- [compliance-hub] Fixed query patterns
42+
- [data-manager] Fixed bug preventing transformation of events ending in a dot
343
- [data-manager] Fixed segment data deletion
444
- [funnels] Fixed delete confirmation using correct button copy
45+
- [license] Stop sending metric after license expired
546
- [users] Fix add/remove user to profile group
647
- [users] Remove link to profile group page after removing user from group
748

849
Dependencies
9-
- Bump lint-staged from 16.2.3 to 16.2.4
1050
- Bump @faker-js/faker from 10.0.0 to 10.1.0 in /ui-tests
11-
- Bump puppeteer from 24.23.0 to 24.24.1
1251
- Bump countly-sdk-nodejs from 24.10.2 to 24.10.3
52+
- Bump lint-staged from 16.2.3 to 16.2.4
53+
- Bump puppeteer from 24.23.0 to 24.24.1
1354

1455
## Version 25.03.23
1556
Fixes:

api/parts/data/usage.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1030,7 +1030,7 @@ plugins.register("/sdk/user_properties", async function(ob) {
10301030

10311031
if (plugins.getConfig('api', params.app && params.app.plugins, true).city_data === true && !userProps.loc && typeof data.lat !== "undefined" && typeof data.lon !== "undefined") {
10321032
// only override lat/lon if no recent gps location exists in user document
1033-
if (!params.app_user.loc || (params.app_user.loc.gps && params.time.mstimestamp - params.app_user.loc.date > 7 * 24 * 3600)) {
1033+
if (!params.app_user.loc || !params.app_user.loc.gps || params.time.mstimestamp - params.app_user.loc.date > 7 * 24 * 3600) {
10341034
userProps.loc = {
10351035
gps: false,
10361036
geo: {
@@ -1061,7 +1061,7 @@ plugins.register("/sdk/user_properties", async function(ob) {
10611061

10621062
if (plugins.getConfig('api', params.app && params.app.plugins, true).city_data === true && !userProps.loc && data.ll && typeof data.ll[0] !== "undefined" && typeof data.ll[1] !== "undefined") {
10631063
// only override lat/lon if no recent gps location exists in user document
1064-
if (!params.app_user.loc || (params.app_user.loc.gps && params.time.mstimestamp - params.app_user.loc.date > 7 * 24 * 3600)) {
1064+
if (!params.app_user.loc || !params.app_user.loc.gps || params.time.mstimestamp - params.app_user.loc.date > 7 * 24 * 3600) {
10651065
userProps.loc = {
10661066
gps: false,
10671067
geo: {

api/parts/jobs/job.js

Lines changed: 25 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -254,32 +254,33 @@ class Job extends EventEmitter {
254254

255255
this._json.next = next.getTime();
256256
}
257-
if (this.name !== "alerts:monitor") {
258-
//check if any job already scheduled or running
259-
let query = {
260-
status: {"$in": [STATUS.SCHEDULED, STATUS.RUNNING]},
261-
name: this.name,
262-
};
263-
if (this._id) {
264-
query._id = {$ne: this._id};
265-
}
266-
var self = this;
267-
return new Promise((resolve, reject) => {
268-
Job.findMany(this.db(), query).then(existing => {
269-
if (existing && existing.length) {
270-
log.d('Job already scheduled or running: %j', existing);
271-
this._json.status = STATUS.CANCELLED; //set this as cancelled now as we have other scheduled
272-
}
273-
else {
274-
self._save().then(resolve, reject);
275-
}
276257

277-
});
278-
});
258+
//check if any job already scheduled or running
259+
let query = {
260+
status: {"$in": [STATUS.SCHEDULED, STATUS.RUNNING]},
261+
name: this.name,
262+
};
263+
264+
if (this.name === 'alerts:monitor' && this.data && Object.keys(this.data).length) {
265+
query.data = this.data;
279266
}
280-
else {
281-
return this._save();
267+
268+
if (this._id) {
269+
query._id = {$ne: this._id};
282270
}
271+
272+
var self = this;
273+
return new Promise((resolve, reject) => {
274+
Job.findMany(this.db(), query).then(existing => {
275+
if (existing && existing.length) {
276+
log.d('Job already scheduled or running: %j', existing);
277+
this._json.status = STATUS.CANCELLED; //set this as cancelled now as we have other scheduled
278+
}
279+
else {
280+
self._save().then(resolve, reject);
281+
}
282+
});
283+
});
283284
}
284285

285286
/**
@@ -1142,4 +1143,4 @@ module.exports = {
11421143
STATUS: STATUS,
11431144
STATUS_MAP: STATUS_MAP,
11441145
debounce: debounce
1145-
};
1146+
};

bin/scripts/device_list/package-lock.json

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

bin/scripts/device_list/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,6 @@
2323
},
2424
"homepage": "https://count.ly/",
2525
"dependencies": {
26-
"csvtojson": "^1.1.9"
26+
"csvtojson": "^2.0.13"
2727
}
2828
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/*
2+
* Sends recalculate request for all ab testing experiment variant cohorts
3+
* Server: countly
4+
* Path: $(countly dir)/bin/scripts/fix-data
5+
* Command: node recalculate_ab_test_cohorts.js
6+
*/
7+
8+
// API key here with permission to update cohorts
9+
const API_KEY = '';
10+
// Countly app id, if not specified will do nothing
11+
const APP_ID = '';
12+
// ab test experiment id, will do nothing if not specified
13+
const EXPERIMENT_ID = '';
14+
// countly instance public url, something like 'https://name.count.ly'
15+
const SERVER_URL = '';
16+
17+
const pluginManager = require('../../../plugins/pluginManager.js');
18+
const request = require('countly-request')(pluginManager.getConfig('security'));
19+
20+
if (API_KEY.length === 0) {
21+
console.warn('Please provide an API_KEY');
22+
process.exit(1);
23+
}
24+
25+
pluginManager.dbConnection('countly_out').then(async(db) => {
26+
let urlObj = {};
27+
try {
28+
urlObj = new URL(SERVER_URL);
29+
}
30+
catch (err) {
31+
urlObj = new URL((process.env.COUNTLY_CONFIG_PROTOCOL || "http") + "://" + (process.env.COUNTLY_CONFIG_HOSTNAME || "localhost"));
32+
}
33+
urlObj.pathname = 'i/cohorts/recalculate';
34+
urlObj.searchParams.append('api_key', API_KEY);
35+
urlObj.searchParams.append('app_id', APP_ID);
36+
37+
console.log(`Finding ab test experiment ${EXPERIMENT_ID} in app ${APP_ID}`);
38+
39+
const experimentCollectionName = `ab_testing_experiments${APP_ID}`;
40+
const experiment = await db.collection(experimentCollectionName).findOne({ _id: db.ObjectID(EXPERIMENT_ID) });
41+
42+
if (experiment?.variants?.length > 0) {
43+
for (let varIdx = 0; varIdx < experiment.variants.length; varIdx += 1) {
44+
const variant = experiment.variants[varIdx];
45+
46+
if (variant?.cohorts && Object.keys(variant.cohorts).length > 0) {
47+
for (let cohIdx = 0; cohIdx < Object.keys(variant.cohorts).length; cohIdx += 1) {
48+
const cohortId = variant.cohorts[Object.keys(variant.cohorts)[cohIdx]];
49+
console.log(`Sending recalculate request for variant ${variant.name}, cohort ${cohortId}`);
50+
51+
urlObj.searchParams.delete('cohort_id');
52+
urlObj.searchParams.append('cohort_id', cohortId);
53+
54+
await new Promise((resolve) => {
55+
request.get(urlObj.href, (err, _, body) => {
56+
if (err) {
57+
console.warn('Request failed ', JSON.stringify(cohortId), err);
58+
}
59+
else {
60+
console.log('Request finished ', JSON.stringify(cohortId), body);
61+
}
62+
resolve();
63+
});
64+
});
65+
}
66+
}
67+
}
68+
}
69+
else {
70+
console.warn(`Experiments ${EXPERIMENT_ID} not found in app ${APP_ID}`);
71+
}
72+
73+
db.close();
74+
});

frontend/express/app.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -438,8 +438,10 @@ Promise.all([plugins.dbConnection(countlyConfig), plugins.dbConnection("countly_
438438
next();
439439
});
440440

441-
app.use('*.svg', function(req, res, next) {
442-
res.setHeader('Content-Type', 'image/svg+xml; charset=UTF-8');
441+
app.use(function(req, res, next) {
442+
if (req.path.endsWith('.svg')) {
443+
res.setHeader('Content-Type', 'image/svg+xml; charset=UTF-8');
444+
}
443445
next();
444446
});
445447

0 commit comments

Comments
 (0)