Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
42e4d47
releaser logic
3388ShubinPavel Mar 14, 2025
83636d1
add release to resolvers andtypedefs
3388ShubinPavel Mar 14, 2025
c34e2d5
rm release comms
3388ShubinPavel Mar 15, 2025
7a787a9
add logs
3388ShubinPavel Mar 15, 2025
4dcfda0
change db
3388ShubinPavel Mar 15, 2025
0cd1107
Bump version up to 1.1.15
github-actions[bot] Mar 15, 2025
111dc39
add comms in graphql and translate to eng
3388ShubinPavel Mar 15, 2025
f37f071
rm useless
3388ShubinPavel Mar 15, 2025
6c1ea20
Merge branch 'feat-release' of https://github.com/codex-team/hawk.api…
3388ShubinPavel Mar 15, 2025
1e189e9
fix
3388ShubinPavel Mar 15, 2025
94ed684
add project req
3388ShubinPavel Mar 15, 2025
aac5d4d
add releaseId to extract from db
3388ShubinPavel Mar 16, 2025
433a683
rm logs
3388ShubinPavel Mar 16, 2025
982c813
Merge branch 'master' into feat-release
3388ShubinPavel Mar 16, 2025
e15dec2
Bump version up to 1.1.16
github-actions[bot] Mar 16, 2025
7e075c0
merge release with project
3388ShubinPavel Mar 16, 2025
f6e5c26
Update project.js
3388ShubinPavel Mar 16, 2025
6d8ceae
add logic to find filesize
3388ShubinPavel Mar 17, 2025
d331a5e
linter
3388ShubinPavel Mar 17, 2025
d7d6b33
Merge branch 'master' into feat-release
3388ShubinPavel Mar 19, 2025
de5d339
Bump version up to 1.1.17
github-actions[bot] Mar 19, 2025
bb1f812
rm redunant
3388ShubinPavel Mar 19, 2025
e629607
new type release
3388ShubinPavel Mar 19, 2025
a295cf3
rm tralingspace
3388ShubinPavel Mar 19, 2025
10d52ce
rm redunant
3388ShubinPavel Mar 19, 2025
dcbc5b3
rm redunant
3388ShubinPavel Mar 26, 2025
c240521
add grouping
3388ShubinPavel Mar 26, 2025
e75de96
Bump version up to 1.1.18
github-actions[bot] Mar 26, 2025
1147bf8
rm redunant import
3388ShubinPavel Mar 26, 2025
300a877
Update releaseFactory.ts
3388ShubinPavel Mar 26, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "hawk.api",
"version": "1.1.17",
"version": "1.1.18",
"main": "index.ts",
"license": "UNLICENSED",
"scripts": {
Expand Down
5 changes: 5 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import PlansFactory from './models/plansFactory';
import BusinessOperationsFactory from './models/businessOperationsFactory';
import schema from './schema';
import { graphqlUploadExpress } from 'graphql-upload';
import ReleasesFactory from './models/releaseFactory';

/**
* Option to enable playground
Expand Down Expand Up @@ -145,12 +146,16 @@ class HawkAPI {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const businessOperationsFactory = new BusinessOperationsFactory(mongo.databases.hawk!, dataLoaders);

// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const releasesFactory = new ReleasesFactory(mongo.databases.events!, dataLoaders);

return {
usersFactory,
workspacesFactory,
projectsFactory,
plansFactory,
businessOperationsFactory,
releasesFactory,
};
}

Expand Down
92 changes: 92 additions & 0 deletions src/models/releaseFactory.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import { Collection, Db } from 'mongodb';
import { ReleaseDBScheme, SourceMapFileChunk } from '@hawk.so/types';
import DataLoaders from '../dataLoaders';

interface ReleaseWithFileDetails extends ReleaseDBScheme {
fileDetails?: SourceMapFileChunk[];
}

export default class ReleasesFactory {
/**
* Releases collection
*/
private collection: Collection<ReleaseDBScheme>;

/**
* DataLoader for releases
*/
private dataLoaders: DataLoaders;

/**
* Creates an instance of the releases factory
* @param dbConnection - database connection
* @param dataLoaders - DataLoaders instance for request batching
*/
constructor(dbConnection: Db, dataLoaders: DataLoaders) {
this.collection = dbConnection.collection('releases');
this.dataLoaders = dataLoaders;
}

/**
* Get releases by project identifier with file sizes
* @param projectId - project identifier
*/
public async findManyByProjectId(projectId: string): Promise<ReleaseDBScheme[]> {
try {
const releases = await this.collection.aggregate<ReleaseWithFileDetails>([
{
$match: {
projectId: projectId,
},
},
{
$lookup: {
from: 'releases.files',
let: { fileIds: '$files._id' },
pipeline: [
{
$match: {
$expr: {
$in: ['$_id', '$$fileIds'],
},
},
},
{
$project: {
_id: 1,
length: 1,
chunkSize: 1,
},
},
],
as: 'fileDetails',
},
},
]).toArray();

return releases.map(release => this.enrichReleaseWithFileSizes(release));
} catch (error) {
console.error(`[ReleasesFactory] Error in findManyByProjectId:`, error);
throw error;
}
}

/**
* Enriches release with file sizes from file details
* @param release - release with file details
* @returns enriched release
*/
private enrichReleaseWithFileSizes(release: ReleaseWithFileDetails): ReleaseDBScheme {
const fileDetailsMap = new Map(
release.fileDetails?.map(detail => [detail._id.toString(), detail.length]) || []
);

return {
...release,
files: release.files?.map(file => ({
...file,
size: fileDetailsMap.get(file._id?.toString() || '') || 0,
})),
};
}
}
20 changes: 20 additions & 0 deletions src/resolvers/project.js
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,26 @@ module.exports = {
return event;
},

/**
* Returns project releases
*
* @param {ProjectDBScheme} project - result of parent resolver
* @param {ContextFactories} context - Global GraphQL context with factories
* @returns {Promise<Release[]>}
*/
async releases(project, _, { factories }) {
if (!project._id) {
throw new Error('projectId is required to fetch releases');
}

try {
return await factories.releasesFactory.findManyByProjectId(project._id.toString());
} catch (error) {
console.error('Error fetching releases:', error);
throw new Error('Failed to get the releases');
}
},

/**
* Find project events
*
Expand Down
40 changes: 0 additions & 40 deletions src/typeDefs/event.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,46 +16,6 @@ type SourceCodeLine {
content: String
}

"""
Release commit
"""
type Commit {
"""
Hash of the commit
"""
hash: String!

"""
Commit author
"""
author: String!

"""
Commit title
"""
title: String!

"""
Commit creation date
"""
date: DateTime!
}

"""
Release data of the corresponding event
"""
type Release {
"""
Release name
"""
releaseName: String! @renameFrom(name: "release")

"""
Release commits
"""
commits: [Commit!]!
}

"""
Event backtrace representation
"""
Expand Down
2 changes: 2 additions & 0 deletions src/typeDefs/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import workspaceMutations from './workspaceMutations';
import chart from './chart';
import plans from './plans';
import seed from './seed';
import release from './release';
import isE2E from '../utils/isE2E';

const rootSchema = gql`
Expand Down Expand Up @@ -100,6 +101,7 @@ const typeDefinitions = [
workspaceMutations,
chart,
plans,
release,
projectEventGroupingPattern,
projectEventGroupingPatternMutations,
];
Expand Down
5 changes: 5 additions & 0 deletions src/typeDefs/project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,11 @@ type Project {
skip: Int = 0
): [Event!]

"""
Project releases
"""
releases: [Release!]!
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why releases list is required in project, what if user never sent any releases?


"""
Returns recent events grouped by day
"""
Expand Down
78 changes: 78 additions & 0 deletions src/typeDefs/release.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import { gql } from 'apollo-server-express';

export default gql`
"""
Source map file details
"""
type SourceMapData {
"""
Source map filename
"""
mapFileName: String!

"""
Original source filename
"""
originFileName: String!

"""
File size in bytes
"""
size: Int!
}

"""
Release commit
"""
type Commit {
"""
Hash of the commit
"""
hash: String!

"""
Commit author
"""
author: String!

"""
Commit title
"""
title: String!

"""
Commit creation date
"""
date: DateTime!
}

"""
Release data
"""
type Release {
"""
Release ID
"""
id: ID! @renameFrom(name: "_id")

"""
Release name
"""
releaseName: String! @renameFrom(name: "release")

"""
Project ID associated with the release
"""
projectId: ID!

"""
Release commits
"""
commits: [Commit!]!

"""
Source maps associated with the release
"""
files: [SourceMapData!]!
}
`;
7 changes: 6 additions & 1 deletion src/types/graphql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import UsersFactory from '../models/usersFactory';
import WorkspacesFactory from '../models/workspacesFactory';
import { GraphQLField } from 'graphql';
import ProjectsFactory from '../models/projectsFactory';
// import Accounting from 'codex-accounting-sdk';
import PlansFactory from '../models/plansFactory';
import BusinessOperationsFactory from '../models/businessOperationsFactory';
import ReleasesFactory from '../models/releaseFactory';

/**
* Resolver's Context argument
Expand Down Expand Up @@ -79,6 +79,11 @@ export interface ContextFactories {
* Allows to work with the Business Operations models
*/
businessOperationsFactory: BusinessOperationsFactory;

/**
* Allows to work with releases
*/
releasesFactory: ReleasesFactory;
}

/**
Expand Down
Loading