Skip to content

Commit d46e9b2

Browse files
Merge pull request #38 from project-sunbird/release-8.1.0
Release 8.1.0
2 parents 5f68a04 + f082527 commit d46e9b2

20 files changed

+8874
-671
lines changed

.github/workflows/on_push.yml

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
name: Build and Publish Docker Image
2+
3+
on:
4+
push:
5+
tags:
6+
- '*'
7+
8+
jobs:
9+
build-and-push:
10+
runs-on: ubuntu-latest
11+
12+
permissions:
13+
contents: read
14+
packages: write
15+
16+
steps:
17+
- name: Checkout repository
18+
uses: actions/checkout@v3
19+
20+
- name: Log in to GitHub Container Registry
21+
uses: docker/login-action@v3
22+
with:
23+
registry: ghcr.io
24+
username: ${{ github.actor }}
25+
password: ${{ secrets.GITHUB_TOKEN }}
26+
27+
- name: Get short commit hash
28+
id: vars
29+
run: echo "commit_hash=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
30+
31+
- name: Prepare Docker image name and tag
32+
run: |
33+
REPO_NAME_LOWERCASE=$(echo "${GITHUB_REPOSITORY}" | tr '[:upper:]' '[:lower:]')
34+
TAG_NAME=$(echo "${GITHUB_REF_NAME}" | tr '[:upper:]' '[:lower:]')
35+
BUILD_TAG="${TAG_NAME}_${{ steps.vars.outputs.commit_hash }}_${GITHUB_RUN_NUMBER}"
36+
37+
echo "IMAGE_NAME=ghcr.io/${REPO_NAME_LOWERCASE}" >> $GITHUB_ENV
38+
echo "IMAGE_TAG=${BUILD_TAG}" >> $GITHUB_ENV
39+
40+
- name: Build ZIP file with Dockerfile.Build
41+
run: |
42+
docker build -t telemetry-build -f Dockerfile.Build .
43+
docker run --name telemetry-builder telemetry-build
44+
docker cp telemetry-builder:/opt/telemetry-service.zip ./
45+
docker rm telemetry-builder
46+
47+
- name: Build Docker image
48+
run: docker build -t $IMAGE_NAME:$IMAGE_TAG .
49+
50+
- name: Push Docker image
51+
run: docker push $IMAGE_NAME:$IMAGE_TAG

.github/workflows/pull_request.yml

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
name: PR Check
2+
3+
on:
4+
pull_request:
5+
branches:
6+
- '**'
7+
8+
jobs:
9+
code-quality:
10+
name: Run Code Quality Checks
11+
runs-on: ubuntu-latest
12+
13+
steps:
14+
- name: Checkout code
15+
uses: actions/checkout@v3
16+
17+
- name: Setup Node.js
18+
uses: actions/setup-node@v3
19+
with:
20+
node-version: '22.15'
21+
22+
- name: Restore node_modules cache
23+
id: cache
24+
uses: actions/cache@v3
25+
with:
26+
path: src/node_modules
27+
key: ${{ runner.os }}-node-modules-${{ hashFiles('src/package-lock.json') }}
28+
restore-keys: |
29+
${{ runner.os }}-node-modules-
30+
31+
- name: Install dependencies
32+
run: npm ci
33+
working-directory: ./src
34+
35+
- name: Save node_modules cache
36+
if: steps.cache.outputs.cache-hit != 'true'
37+
uses: actions/cache@v3
38+
with:
39+
path: src/node_modules
40+
key: ${{ runner.os }}-node-modules-${{ hashFiles('src/package-lock.json') }}
41+
42+
- name: Lint
43+
run: npm run lint
44+
working-directory: ./src

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
package-lock.json
21
node_modules
32
.nyc_output
43
coverage

Dockerfile

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
FROM node:22.15-slim
22
MAINTAINER "Mahesh" "mahesh@ilimi.in"
33
RUN useradd -rm -d /home/sunbird -s /bin/bash -g root -G sudo -u 1001 sunbird
4-
RUN apt-get update
5-
RUN apt-get install unzip -y \
6-
&& apt-get install curl -y \
7-
&& apt-get install ca-certificates openssl -y
4+
RUN apt-get update \
5+
&& apt-get install -y unzip curl ca-certificates openssl libsnappy-dev \
6+
&& rm -rf /var/lib/apt/lists/*
87
USER sunbird
98
RUN mkdir -p /home/sunbird/telemetry
109
WORKDIR /home/sunbird/telemetry
11-
COPY ./telemetry-service.zip /home/sunbird/telemetry/
10+
COPY ./telemetry-service.zip /home/sunbird/telemetry/
1211
RUN unzip /home/sunbird/telemetry/telemetry-service.zip
1312
RUN ls -all /home/sunbird/telemetry
1413
WORKDIR /home/sunbird/telemetry/telemetry/

Dockerfile.Build

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
FROM node:22.15-slim
22
MAINTAINER "Mahesh" "mahesh@ilimi.in"
3-
RUN apt-get update
4-
RUN apt-get install zip -y
3+
RUN apt-get update && apt-get install -y \
4+
python3 \
5+
make \
6+
g++ \
7+
libsnappy-dev \
8+
libsnappy1v5 \
9+
zip \
10+
&& rm -rf /var/lib/apt/lists/*
511
RUN mkdir -p /opt/telemetry
612
ADD src /opt/telemetry/
713
WORKDIR /opt/telemetry/

README.md

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,79 @@
33
This is the repository for Sunbird telemetry microservice. It provides APIs for Sunbird telemetry.
44

55
The code in this repository is licensed under MIT License unless otherwise noted. Please see the [LICENSE](https://github.com/project-sunbird/sunbird-telemetry-service/blob/master/LICENSE) file for details.
6+
7+
## Development Setup
8+
9+
### Prerequisites
10+
- Node.js v22.15
11+
- Kafka
12+
13+
### Local Development
14+
To set up the project locally:
15+
16+
1. Fork the repository on GitHub
17+
18+
2. Clone your fork:
19+
```bash
20+
git clone https://github.com/your-username/sunbird-telemetry-service.git
21+
cd sunbird-telemetry-service
22+
cd src
23+
```
24+
25+
3. Install dependencies:
26+
```bash
27+
npm i
28+
```
29+
30+
4. Start the service:
31+
```bash
32+
npm run start
33+
```
34+
35+
5. Run Kafka and Zookeeper
36+
37+
### Code Quality
38+
39+
The project maintains code quality through automated checks that run on every pull request:
40+
41+
1. **Linting**
42+
- ESLint for code style and quality
43+
- Command: `npm run lint`
44+
45+
2. **Dependencies**
46+
- Uses `npm ci` for deterministic installations
47+
- GitHub Actions cache for faster builds
48+
49+
3. **Code Formatting**
50+
- Ensures consistent code formatting
51+
- Can be automatically fixed using `npm run lint:fix`
52+
53+
These checks ensure consistent code style and secure dependency management.
54+
55+
## Container Image Publishing
56+
57+
This repository uses GitHub Actions to automatically build and publish Docker container images to GitHub Container Registry (GHCR) whenever a new tag is pushed to the repository.
58+
59+
### Build and Publish Workflow
60+
61+
The workflow is triggered on:
62+
- creation of any tag
63+
64+
Key features of the workflow:
65+
1. Automatically builds Docker images
66+
2. Tags images with a combination of:
67+
- The tag name (lowercased)
68+
- Short commit hash
69+
- GitHub run number
70+
3. Publishes images to `ghcr.io` using the repository name
71+
4. Uses GitHub Actions for secure authentication to GHCR
72+
73+
### Image Naming Convention
74+
The Docker images follow this naming convention:
75+
- Repository: `ghcr.io/${OWNER_NAME}/${REPO_NAME_LOWERCASE}`
76+
- Tag: `${TAG_NAME}_${COMMIT_HASH}_${RUN_NUMBER}`
77+
78+
For example, if you push a tag `v1.0.0` on commit `abc123`, the resulting image would be:
79+
```
80+
ghcr.io/project-sunbird/sunbird-telemetry-service:v1.0.0_abc123_1
81+
```

src/.eslintignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
/node_modules
2+
coverage/
3+
.nyc_output/
4+
mochawesome-report/
5+
.audit.json
6+
telemetry*.log

src/.eslintrc.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
module.exports = {
2+
env: {
3+
node: true,
4+
es2021: true
5+
},
6+
parserOptions: {
7+
ecmaVersion: 'latest'
8+
},
9+
rules: {
10+
'no-console': 'warn',
11+
'no-debugger': 'error',
12+
'no-unused-vars': 'warn',
13+
'semi': ['error', 'always'],
14+
'quotes': ['error', 'single'],
15+
'indent': ['error', 2]
16+
}
17+
};

src/app.js

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,12 @@ const express = require('express'),
1010
const createAppServer = () => {
1111
const app = express();
1212
app.use((req, res, next) => {
13-
res.header('Access-Control-Allow-Origin', '*')
14-
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,PATCH,DELETE,OPTIONS')
15-
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization,' + 'cid, user-id, x-auth, Cache-Control, X-Requested-With, datatype, *')
16-
if (req.method === 'OPTIONS') res.sendStatus(200)
17-
else next()
18-
})
13+
res.header('Access-Control-Allow-Origin', '*');
14+
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,PATCH,DELETE,OPTIONS');
15+
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization,' + 'cid, user-id, x-auth, Cache-Control, X-Requested-With, datatype, *');
16+
if (req.method === 'OPTIONS') res.sendStatus(200);
17+
else next();
18+
});
1919
app.use(bodyParser.json({ limit: '5mb' }));
2020
app.use(logger('dev'));
2121
app.use(express.json());
@@ -24,7 +24,7 @@ const createAppServer = () => {
2424
app.use('/', require('./routes'));
2525
module.exports = app;
2626
return app;
27-
}
27+
};
2828

2929
if (process.env.node_env !== 'test') {
3030
cluster((worker) => {

src/dispatcher/cassandra-dispatcher.js

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3,37 +3,37 @@ var util = require('util');
33
var Cassandra = require('winston-cassandra');
44

55
Cassandra.prototype._createSchema = function (callback) {
6-
var createQuery = 'CREATE TABLE ' + this.options.table +
6+
var createQuery = 'CREATE TABLE ' + this.options.table +
77
' (key text, mid text, date timestamp, level text, message text, meta text, PRIMARY KEY(key, mid));';
8-
var self = this;
8+
var self = this;
99

10-
this.client.metadata.getTable(this.options.keyspace, this.options.table, function (err, tableInfo) {
11-
if (err) return callback(err);
12-
if (tableInfo) {
13-
//table is already created
14-
self.schemaStatus.created = true;
15-
return callback();
16-
}
10+
this.client.metadata.getTable(this.options.keyspace, this.options.table, function (err, tableInfo) {
11+
if (err) return callback(err);
12+
if (tableInfo) {
13+
//table is already created
14+
self.schemaStatus.created = true;
15+
return callback();
16+
}
1717

18-
return self.client.execute(createQuery, function (err) {
19-
self.schemaStatus.created = !err;
20-
return callback(err);
21-
});
18+
return self.client.execute(createQuery, function (err) {
19+
self.schemaStatus.created = !err;
20+
return callback(err);
2221
});
22+
});
2323
};
2424

2525
Cassandra.prototype._insertLog = function (level, msg, meta, callback) {
26-
var key = this.getKey();
27-
if (!key) {
28-
return callback(new Error('Partition ' + this.options.partitionBy + ' not supported'), false);
29-
}
30-
var query = 'INSERT INTO ' + this.options.table + ' (key, mid, date, level, message, meta) VALUES (?, ?, ?, ?, ?, ?)' + (this.options.cassandraTtl ? (' USING TTL ' + this.options.cassandraTtl) : '');
31-
//execute as a prepared query as it would be executed multiple times
32-
return this.client.execute(
33-
query,
34-
[key, meta.mid, new Date(), level, msg, util.inspect(meta)],
35-
{prepare: true, consistency: this.options.consistency},
36-
callback);
26+
var key = this.getKey();
27+
if (!key) {
28+
return callback(new Error('Partition ' + this.options.partitionBy + ' not supported'), false);
29+
}
30+
var query = 'INSERT INTO ' + this.options.table + ' (key, mid, date, level, message, meta) VALUES (?, ?, ?, ?, ?, ?)' + (this.options.cassandraTtl ? (' USING TTL ' + this.options.cassandraTtl) : '');
31+
//execute as a prepared query as it would be executed multiple times
32+
return this.client.execute(
33+
query,
34+
[key, meta.mid, new Date(), level, msg, util.inspect(meta)],
35+
{prepare: true, consistency: this.options.consistency},
36+
callback);
3737
};
3838

3939
winston.transports.Cassandra = Cassandra;

0 commit comments

Comments
 (0)