Skip to content

Commit 185d1c3

Browse files
committed
Fix #46 make me umami 2.9.0 compatible
1 parent 494726e commit 185d1c3

File tree

673 files changed

+126575
-2178
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

673 files changed

+126575
-2178
lines changed

.github/workflows/daily_umami_report.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ jobs:
1919
steps:
2020
- name: Create Daily Umami report
2121
id: umamiReportStep
22-
uses: boly38/action-umami-report@main
22+
uses: boly38/action-umami-report@umami-server-2.9.0
2323
with:
2424
umami-server: https://${{secrets.UMAMI_SERVER}}
2525
umami-user: ${{secrets.UMAMI_USERNAME}}

.github/workflows/weekly_umami_report.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ jobs:
1515
steps:
1616
- name: Create Weekly Umami report
1717
id: umamiReportStep
18-
uses: boly38/action-umami-report@main
18+
uses: boly38/action-umami-report@umami-server-2.9.0
1919
with:
2020
umami-server: https://${{secrets.UMAMI_SERVER}}
2121
umami-user: ${{secrets.UMAMI_USERNAME}}

README.md

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ jobs:
5454
steps:
5555
- name: Create Umami report
5656
id: umamiReport
57-
uses: boly38/action-umami-report@stable
57+
uses: boly38/action-umami-report@umami-server-2.9.0
5858
with:
5959
umami-server: https://${{secrets.UMAMI_SERVER}}
6060
umami-user: ${{secrets.UMAMI_USERNAME}}
@@ -70,10 +70,20 @@ jobs:
7070
```
7171
Full working sample: cf. [daily_umami_report.yml](.github/workflows/daily_umami_report.yml)
7272
73+
**TIP**: if your umami server version is not compatible with current GithubActions, you could change `umami-server-2.9.0` keyword by one of the [current repository tags](https://github.com/boly38/action-umami-report/tags) with `umami-server-x.y` format.
74+
7375
# See also
7476

7577
## Umami
76-
- Umami [API](https://umami.is/docs/api) ([API client](https://github.com/jakobbouchard/umami-api-client))- [Source](https://github.com/umami-software/umami)
78+
Umami server :
79+
- [API](https://umami.is/docs/api)
80+
- [source](https://github.com/umami-software/umami)
81+
82+
Umami API clients:
83+
- jakobbouchard TS/JS [umami-api-client](https://github.com/jakobbouchard/umami-api-client)
84+
- Import: `import UmamiApiClient from 'umami-api'`
85+
- boly38 JS [umami-api-client](https://github.com/boly38/umami-api-client)
86+
- Import: `import UmamiClient from 'umami-api-client'`
7787

7888
## possible next step
7989
- send the report [by email](https://github.com/marketplace?type=actions&query=mail+), on [discord](https://github.com/marketplace?type=actions&query=discord+), etc..
@@ -91,10 +101,12 @@ cp ./env/initenv.template.sh ./env/initenv.dontpush.sh
91101
```
92102
* Then run manual test
93103
```
94-
git clone https://github.com/boly38y/action-umami-report.git
104+
git clone https://github.com/boly38/action-umami-report.git
95105
cd action-umami-report
96106
npm install
97-
npm manual.js
107+
npm run day
108+
npm run showResults
109+
# check other targets in package.json
98110
```
99111
* you could also fork, feature branch, then submit a pull request.
100112

fetch.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import Manual from './manual.js';
22

33
const manual = new Manual();
44

5-
var options = manual.getOptions()
5+
let options = manual.getOptions()
66
options.period = '1month';
77
options.unit = 'day';
88
manual.fetch(options);

lib/action.js

Lines changed: 148 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -1,142 +1,174 @@
11
import path from 'path';
22
import fs from 'fs';
33
import core from '@actions/core';
4-
import github from '@actions/github';
54

6-
import axios from 'axios'
7-
import UmamiApiClient from 'umami-api'
5+
import UmamiClient from 'umami-api-client'
86

97
import ReportGenerator from './reportGenerator.js';
8+
import axios from "axios";
109

1110
const DEBUG_ACTION = process.env.UMAMI_DEBUG_ACTION === 'true';
1211
const UMAMI_OUTPUT_DIRECTORY = process.env.UMAMI_OUTPUT_DIRECTORY || './umami';
13-
const rethrow = (err) => {throw err;}
12+
const rethrow = (err) => {
13+
throw new Error(err);
14+
}
1415

1516
class Action {
1617

17-
static async fetchUmamiServerApi(server, timeoutMs = 50000) {
18-
const username = 'abc';
19-
const password = 'abc';
20-
console.log(`fetchUmamiServerApi`);
21-
for (var i = 1 ; i < 10 ; i++) {
22-
var expectedResult = [];
23-
const action = "post " + i;
24-
console.time(action);
25-
const client = axios.create({ baseURL: `${server}/api`, timeout: timeoutMs });
26-
const loginResult = await client.post("/auth/login", { username, password }).catch(error => {
27-
console.timeEnd(action);
28-
const message = typeof error.response !== "undefined" ? error.response.data : error.message;
29-
const status = typeof error.response !== "undefined" ? `${error.response.status} ${error.response.statusText}`:'';
30-
const logMessage = status !== message ? `[${status}] ${message}` : message;
31-
if (logMessage !== '401 Unauthorized') {
32-
console.log(`Login failed: ${logMessage}`);
33-
} else {
34-
expectedResult.push(error);
18+
/**
19+
* fetch umami api to understand flaky results
20+
* cf. https://github.com/boly38/action-umami-report/issues/37
21+
* @param server
22+
* @param timeoutMs
23+
* @returns {Promise<unknown>}
24+
*/
25+
static async fetchUmamiServerApi(server, timeoutMs = 50000) {
26+
return new Promise(async (resolve, reject) => {
27+
const username = 'admin';
28+
const password = '075827845F';
29+
console.log(`fetchUmamiServerApi`);
30+
let fetchResults = [];
31+
for (let i = 1; i < 10; i++) {
32+
const action = "post " + i;
33+
console.time(action);
34+
const client = axios.create({baseURL: `${server}/api`, timeout: timeoutMs});
35+
const loginResult = await client.post("/auth/login", {username, password}).catch(error => {
36+
console.timeEnd(action);
37+
const message = typeof error.response !== "undefined" ? error.response.data : error.message;
38+
const status = typeof error.response !== "undefined" ? `${error.response.status} ${error.response.statusText}` : '';
39+
const logMessage = status !== message ? `[${status}] ${message}` : message;
40+
if (logMessage !== '401 Unauthorized') {
41+
console.log(`Login failed: ${logMessage}`);
42+
}
43+
fetchResults.push(status);
44+
});
45+
if (loginResult !== undefined) {
46+
fetchResults.push(`OK ${JSON.stringify(loginResult.status)}`);
47+
}
3548
}
49+
resolve(fetchResults);
3650
});
37-
if (loginResult !== undefined || expectedResult.length > 0) {
38-
return;
39-
}
40-
}
41-
}
42-
43-
static async produceActionResult(resultName, resultValue, outputFile = null) {
44-
const outFileAddition = outputFile !== null ? `file:${outputFile}` : '';
45-
console.info(`produce action result (output): ${resultName} ${outFileAddition}`);
46-
core.setOutput(resultName, resultValue);// core action output: to be declared as outputs by current job and used by another job
47-
// disabled by #12 // core.exportVariable(resultName, resultValue);// core action env: to be used by current job by another step
48-
49-
var targetFile = null;
50-
if (isSet(UMAMI_OUTPUT_DIRECTORY) && isSet(outputFile)) {
51-
targetFile = `${UMAMI_OUTPUT_DIRECTORY}/${outputFile}`;
52-
try {
53-
ensureDirectoryExistence(targetFile);
54-
fs.writeFileSync(targetFile, resultValue);
55-
} catch (error) {
56-
console.error(`ERROR: unable to write to ${targetFile} : ${error}`);
57-
targetFile = null;
58-
}
59-
}
60-
return { targetFile };
61-
}
62-
63-
64-
static async produceReport(umamiSite, umamiSiteStats, sitePageViews = null, siteEvents = null, siteMetricsUrl = null,
65-
outputFile = null, reportContent = 'pageviews|events|urls', period = '24h', unit = 'hour') {
66-
//~~ generate umami report content
67-
const generator = new ReportGenerator(umamiSite, reportContent, period, unit, umamiSiteStats, sitePageViews, siteEvents, siteMetricsUrl);
68-
const umamiOneLineReport = generator.oneLineReport();
69-
const umamiReport = generator.detailedReport();
70-
71-
//~~ produce github actions results (output)
72-
Action.produceActionResult("pageViews", umamiSiteStats.pageviews.value, null);
73-
Action.produceActionResult("umamiOneLineReport", umamiOneLineReport);
74-
const { targetFile } = await Action.produceActionResult("umamiReport", umamiReport, outputFile);
75-
Action.produceActionResult("umamiReportLength", umamiReport.length, null);// #14
76-
if ( isSet(targetFile) ) {
77-
Action.produceActionResult("umamiReportFile", targetFile, null);
78-
return targetFile;
79-
}
80-
return null;
81-
}
82-
83-
/**
84-
* @deprecated : please use umamiReport(...)
85-
*/
86-
static async umamiDailyReportV0(server, user, password, domain = '', outputFile = null, reportContent = 'pageviews|events|urls') {
87-
var options = { server, user, password, domain, outputFile, reportContent };
88-
return await Action.umamiReport(options);
89-
}
90-
91-
static async umamiReport(options) {
92-
// options
93-
var { server, user, password, domain, outputFile, reportContent, period, unit, tz } = options;
94-
// default options
95-
if (!isSet(user)) {
96-
user = 'admin';
9751
}
98-
if (!isSet(outputFile)) {
99-
outputFile = null;
100-
}
101-
if (!isSet(reportContent)) {
102-
reportContent = 'pageviews|events|urls';
103-
}
104-
if (!isSet(period)) {
105-
period = '24h';
106-
}
107-
if (!isSet(unit)) {
108-
unit = 'hour';
52+
53+
static async produceActionResult(resultName, resultValue, outputFile = null) {
54+
const outFileAddition = outputFile !== null ? `file:${outputFile}` : '';
55+
console.info(`produce action result (output): ${resultName} ${outFileAddition}`);
56+
core.setOutput(resultName, resultValue);// core action output: to be declared as outputs by current job and used by another job
57+
// disabled by #12 // core.exportVariable(resultName, resultValue);// core action env: to be used by current job by another step
58+
59+
let targetFile = null;
60+
if (isSet(UMAMI_OUTPUT_DIRECTORY) && isSet(outputFile)) {
61+
targetFile = `${UMAMI_OUTPUT_DIRECTORY}/${outputFile}`;
62+
try {
63+
ensureDirectoryExistence(targetFile);
64+
fs.writeFileSync(targetFile, resultValue);
65+
} catch (error) {
66+
console.info(`ERROR: unable to write to ${targetFile} : ${error}`);
67+
targetFile = null;
68+
}
69+
}
70+
if (isSet(targetFile)) {
71+
console.info(`produce action result (targetFile): ${targetFile}`);
72+
return {targetFile};
73+
}
74+
return {};
10975
}
110-
if (!isSet(tz)) {
111-
tz = 'Europe/Paris';
76+
77+
78+
static async produceReport(umamiSite, umamiSiteStats, sitePageViews = null, siteEvents = null, siteMetricsUrl = null,
79+
outputFile = null, reportContent = 'pageviews|events|urls', period = '24h', unit = 'hour') {
80+
//~~ generate umami report content
81+
const generator = new ReportGenerator(umamiSite, reportContent, period, unit, umamiSiteStats, sitePageViews, siteEvents, siteMetricsUrl);
82+
const umamiOneLineReport = generator.oneLineReport();
83+
const umamiReport = generator.detailedReport();
84+
85+
//~~ produce github actions results (output)
86+
await Action.produceActionResult("pageViews", umamiSiteStats.pageviews.value, null);
87+
await Action.produceActionResult("umamiOneLineReport", umamiOneLineReport);
88+
const {targetFile} = await Action.produceActionResult("umamiReport", umamiReport, outputFile);
89+
await Action.produceActionResult("umamiReportLength", umamiReport.length, null);// #14
90+
if (isSet(targetFile)) {
91+
await Action.produceActionResult("umamiReportFile", targetFile, null);
92+
return targetFile;
93+
}
94+
return null;
11295
}
11396

114-
const umami = new UmamiApiClient(server, user, password);
115-
const site = isSet(domain) ? await umami.getWebsiteBy("domain", domain).catch(rethrow) : await umami.getWebsite().catch(rethrow);
116-
const siteStats = await site.getStats({ period }).catch(rethrow);
117-
const sitePageViews = await site.getPageviews({ period, unit, tz }).catch(rethrow);
118-
const siteEvents = await site.getEvents({ period, unit, tz }).catch(rethrow);
119-
const siteMetricsUrl = await site.getMetrics({ period }).catch(rethrow);
120-
121-
DEBUG_ACTION && console.log(site);
122-
DEBUG_ACTION && console.log(siteStats);
123-
const targetFile = await Action.produceReport(site, siteStats, sitePageViews, siteEvents, siteMetricsUrl,
124-
outputFile, reportContent, period);
125-
if (targetFile != null) {
126-
return { site, siteStats, targetFile }
97+
static async umamiReport(options) {
98+
return new Promise(async (resolve, reject) => {
99+
try {
100+
// options
101+
let {server, user, password, domain, outputFile, reportContent, period, unit, tz} = options;
102+
// default options
103+
if (!isSet(user)) {
104+
user = 'admin';
105+
}
106+
if (!isSet(outputFile)) {
107+
outputFile = null;
108+
}
109+
if (!isSet(reportContent)) {
110+
reportContent = 'pageviews|events|urls';
111+
}
112+
if (!isSet(period)) {
113+
period = '24h';
114+
}
115+
if (!isSet(unit)) {
116+
unit = 'hour';
117+
}
118+
if (!isSet(tz)) {
119+
tz = 'Europe/Paris';
120+
}
121+
122+
DEBUG_ACTION && console.log("options : " + JSON.stringify({
123+
server,
124+
user,
125+
password,
126+
domain,
127+
outputFile,
128+
reportContent,
129+
period,
130+
unit,
131+
tz
132+
}));
133+
134+
const umamiClient = new UmamiClient({server});
135+
const authData = await umamiClient.login(user, password).catch(rethrow);
136+
137+
const sites = await umamiClient.getSites(authData).catch(err => {
138+
console.error("errBX" + err);
139+
throw new Error(err);
140+
})
141+
const site = umamiClient.selectSiteByDomain(sites, domain);
142+
DEBUG_ACTION && console.log(site);
143+
const siteStats = await umamiClient.getStats(authData, site, period).catch(rethrow);
144+
const sitePageViews = await umamiClient.getPageViews(authData, site, {unit, tz}, period).catch(rethrow);
145+
const siteEvents = await umamiClient.getEvents(authData, site, {unit, tz}, period).catch(rethrow);
146+
const siteMetricsUrl = await umamiClient.getMetrics(authData, site, {type: 'url'}, period).catch(rethrow);
147+
148+
DEBUG_ACTION && console.log(siteStats);
149+
const targetFile = await Action.produceReport(site, siteStats, sitePageViews, siteEvents, siteMetricsUrl,
150+
outputFile, reportContent, period);
151+
if (isSet(targetFile)) {
152+
resolve({site, siteStats, targetFile});
153+
} else {
154+
resolve({site, siteStats});
155+
}
156+
} catch (err) {
157+
console.error("err" + err);
158+
reject(err);
159+
}
160+
});
127161
}
128-
return { site, siteStats };
129-
}
130162
}
131163

132164
export default Action;
133165

134166
const isSet = (value) => value !== null && value !== undefined && value !== '';
135167
const ensureDirectoryExistence = (filePath) => {
136-
var dirname = path.dirname(filePath);
137-
if (fs.existsSync(dirname)) {
138-
return true;
139-
}
140-
ensureDirectoryExistence(dirname);
141-
fs.mkdirSync(dirname);
168+
const dirname = path.dirname(filePath);
169+
if (fs.existsSync(dirname)) {
170+
return true;
171+
}
172+
ensureDirectoryExistence(dirname);
173+
fs.mkdirSync(dirname);
142174
};

main.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@ const printContext = () => {
2222
const actionUmamiReport = async function() {
2323
try {
2424
if (umamiServer === null || umamiServer === undefined) {
25-
throw "please setup your environment"
25+
throw new Error("please setup your environment");
2626
}
27-
var options = {};
27+
let options = {};
2828
options.server = umamiServer;
2929
options.user = umamiUser;
3030
options.password = umamiPassword;

0 commit comments

Comments
 (0)