Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v2.1.0-beta.6 -> production #43

Merged
merged 13 commits into from
May 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
42 changes: 42 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,48 @@

> All notable changes to this project will be documented in this file

## [2.1.0-beta.6](https://github.com/open-sauced/opengraph.opensauced.pizza/compare/v2.1.0-beta.5...v2.1.0-beta.6) (2023-05-09)


### 🍕 Features

* UI adjustments ([#42](https://github.com/open-sauced/opengraph.opensauced.pizza/issues/42)) ([acbe81a](https://github.com/open-sauced/opengraph.opensauced.pizza/commit/acbe81a39303d7495fd4bebd51306bd3fe8d9d18))

## [2.1.0-beta.5](https://github.com/open-sauced/opengraph.opensauced.pizza/compare/v2.1.0-beta.4...v2.1.0-beta.5) (2023-05-05)


### 🍕 Features

* highlights getting repo name & languages from pr's repo ([#41](https://github.com/open-sauced/opengraph.opensauced.pizza/issues/41)) ([1555a25](https://github.com/open-sauced/opengraph.opensauced.pizza/commit/1555a25a114b0d812c058d1a9728706a63965b44))

## [2.1.0-beta.4](https://github.com/open-sauced/opengraph.opensauced.pizza/compare/v2.1.0-beta.3...v2.1.0-beta.4) (2023-05-04)


### 🍕 Features

* higlight card upload & storage ([#39](https://github.com/open-sauced/opengraph.opensauced.pizza/issues/39)) ([b6abefa](https://github.com/open-sauced/opengraph.opensauced.pizza/commit/b6abefaa364c5c7c3f97e52990808ad6687e989c))

## [2.1.0-beta.3](https://github.com/open-sauced/opengraph.opensauced.pizza/compare/v2.1.0-beta.2...v2.1.0-beta.3) (2023-05-02)


### 🍕 Features

* Highlight Cards UI Generation (frontend-only) ([#36](https://github.com/open-sauced/opengraph.opensauced.pizza/issues/36)) ([138a847](https://github.com/open-sauced/opengraph.opensauced.pizza/commit/138a847bad92eb1f35fafa467720de01646f31cc))

## [2.1.0-beta.2](https://github.com/open-sauced/opengraph.opensauced.pizza/compare/v2.1.0-beta.1...v2.1.0-beta.2) (2023-04-30)


### 🐛 Bug Fixes

* Overflowing language bar fix ([#38](https://github.com/open-sauced/opengraph.opensauced.pizza/issues/38)) ([3dc1a0a](https://github.com/open-sauced/opengraph.opensauced.pizza/commit/3dc1a0add116c1124af6a993e9e843015f3c0d25))

## [2.1.0-beta.1](https://github.com/open-sauced/opengraph.opensauced.pizza/compare/v2.0.1...v2.1.0-beta.1) (2023-04-26)


### 🍕 Features

* adding utilities for cards local generation & testing ([#34](https://github.com/open-sauced/opengraph.opensauced.pizza/issues/34)) ([c5a5fec](https://github.com/open-sauced/opengraph.opensauced.pizza/commit/c5a5fecd3689b11fd3325c7f0fd3228bd368e0f5))

### [2.0.1](https://github.com/open-sauced/opengraph.opensauced.pizza/compare/v2.0.0...v2.0.1) (2023-04-19)


Expand Down
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,18 @@ To start a local copy of the app on port `3001`:
npm run start:dev
```

### Local dev scripts

There are a few scripts that can be used to generate and test the social cards locally without having to deploy to the CDN. This is the way to go when developing & testing the interface for the social cards.

#### Generating user profile cards:

```shell
npm run local-dev:usercards
```

> Generates user cards for all users in the test array inside `test/local-dev/UserCards.ts` and outputs them in `dist/local-dev/` for testing.

### 📝 Environment variables

Some environment variables are required to run the application. You can find them in the `.env.example` file. While most of them are optional, some are required to run the application.
Expand Down
4 changes: 2 additions & 2 deletions npm-shrinkwrap.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@open-sauced/opengraph.opensauced.pizza",
"version": "2.0.1",
"version": "2.1.0-beta.6",
"keywords": [],
"description": "OpenGraph dot Open Sauced is a general purpose social card generator",
"author": "Ahmed Mohamed Atwa <Ahmedatwa866@yahoo.com>",
Expand Down Expand Up @@ -38,6 +38,8 @@
"test:cov": "npm run test --coverage",
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
"test:e2e": "npm run test --config test/jest-e2e.json",
"test:local:user": "npx ts-node test/local-dev/UserCards",
"test:local:highlight": "npx ts-node test/local-dev/HighlightCards",
"docs": "npx compodoc -p tsconfig.json --hideGenerator --disableDependencies -d ./dist/documentation ./src",
"docs:serve": "npm run docs -- --serve"
},
Expand Down
2 changes: 1 addition & 1 deletion public/diagram.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 4 additions & 2 deletions src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ import { clc } from "@nestjs/common/utils/cli-colors.util";
import ApiConfig from "./config/api.config";
import GitHubConfig from "./config/github.config";
import DigitalOceanConfig from "./config/digital-ocean.config";
import { SocialCardModule } from "./social-card/social-card.module";
import { UserCardModule } from "./social-card/user-card/user-card.module";
import { S3FileStorageModule } from "./s3-file-storage/s3-file-storage.module";
import { HighlightCardModule } from "./social-card/highlight-card/highlight-card.module";

@Module({
imports: [
Expand Down Expand Up @@ -46,8 +47,9 @@ import { S3FileStorageModule } from "./s3-file-storage/s3-file-storage.module";
}),
TerminusModule,
HttpModule,
SocialCardModule,
S3FileStorageModule,
UserCardModule,
HighlightCardModule,
],
controllers: [],
providers: [],
Expand Down
11 changes: 10 additions & 1 deletion src/github/github.service.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { Inject, Injectable, Logger } from "@nestjs/common";
import { ConfigType } from "@nestjs/config";
import { graphql } from "@octokit/graphql";
import { RateLimit, User } from "@octokit/graphql-schema";
import { RateLimit, Repository, User } from "@octokit/graphql-schema";

import GithubConfig from "../config/github.config";
import getRepo from "./gql/get-repo";
import getUser from "./gql/get-user";

@Injectable()
Expand All @@ -29,6 +30,14 @@ export class GithubService {
return user;
}

async getRepo (owner: string, repo: string) {
const { query, variables } = getRepo(owner, repo);

const { repository } = await this.graphqlWithAuth<{ repository: Repository }>(query, variables);

return repository;
}

async rateLimit () {
const { rateLimit } = await this.graphqlWithAuth<{ rateLimit: RateLimit }>(`query {
rateLimit {
Expand Down
37 changes: 37 additions & 0 deletions src/github/gql/get-repo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
const getRepo = (owner: string, repo: string) => ({
query: `
query ($owner: String!, $repo: String!) {
repository(
owner: $owner
name: $repo
) {
id
name
databaseId
nameWithOwner
owner {
id
login
avatarUrl
}
languages (first: 100, orderBy: { field: SIZE, direction: DESC }) {
edges {
node {
id
color
name
}
size
}
totalSize
totalCount
}
}
}`,
variables: {
owner,
repo,
},
});

export default getRepo;
21 changes: 21 additions & 0 deletions src/s3-file-storage/s3-file-storage.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,27 @@ export class S3FileStorageService {
}
}

async getFileMeta (hash: string): Promise<Record<string, string> | null> {
try {
const response = await this.s3Client.send(
new HeadObjectCommand({
Bucket: this.config.bucketName,
Key: hash,
}),
);

return response.Metadata ?? null;
} catch (error) {
if (error instanceof Error) {
if (error.name === "NotFound") {
return null;
}
}

throw error;
}
}

async uploadFile (
fileContent: Buffer | Readable,
hash: string,
Expand Down
71 changes: 71 additions & 0 deletions src/social-card/highlight-card/highlight-card.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { Controller, Get, Header, HttpStatus, Param, ParseIntPipe, Redirect, Res, StreamableFile } from "@nestjs/common";
import {
ApiBadRequestResponse,
ApiForbiddenResponse,
ApiNoContentResponse,
ApiNotFoundResponse,
ApiOkResponse,
ApiOperation, ApiResponse,
ApiTags,
} from "@nestjs/swagger";
import { FastifyReply } from "fastify";
import { HighlightCardService } from "./highlight-card.service";


@Controller("highlights")
@ApiTags("Highlight social cards")
export class HighlightCardController {
constructor (
private readonly highlightCardService: HighlightCardService,
) {}

@Get("/:id")
@ApiOperation({
operationId: "generateHighlightSocialCard",
summary: "Gets latest cache aware social card link for :id or generates a new one",
})
@Header("Content-Type", "image/png")
@ApiOkResponse({ type: StreamableFile, description: "Social card image" })
@ApiNotFoundResponse({ description: "Highlight not found" })
@ApiForbiddenResponse({ description: "Rate limit exceeded" })
@ApiBadRequestResponse({ description: "Invalid highlight id" })
@Redirect()
async generateHighlightSocialCard (
@Param("id", ParseIntPipe) id: number,
@Res({ passthrough: true }) res: FastifyReply,
): Promise<void> {
const { fileUrl, hasFile, needsUpdate } = await this.highlightCardService.checkRequiresUpdate(id);

if (hasFile && !needsUpdate) {
return res.status(HttpStatus.FOUND).redirect(fileUrl);
}

const url = await this.highlightCardService.getHighlightCard(id);

return res.status(HttpStatus.FOUND).redirect(url);
}

@Get("/:id/metadata")
@ApiOperation({
operationId: "getHighlightSocialCardMetadata",
summary: "Gets latest cache aware social card metadata for :id",
})
@ApiNoContentResponse({ description: "Highlight social card image is up to date", status: HttpStatus.NO_CONTENT })
@ApiResponse({ description: "Highlight social card image needs regeneration", status: HttpStatus.NOT_MODIFIED })
@ApiNotFoundResponse({ description: "Highlight social card image not found", status: HttpStatus.NOT_FOUND })
@ApiBadRequestResponse({ description: "Invalid highlight id", status: HttpStatus.BAD_REQUEST })
async checkHighlightSocialCard (
@Param("id", ParseIntPipe) id: number,
@Res({ passthrough: true }) res: FastifyReply,
): Promise<void> {
const { fileUrl, hasFile, needsUpdate, lastModified } = await this.highlightCardService.checkRequiresUpdate(id);

return res
.headers({
"x-amz-meta-last-modified": lastModified?.toISOString() ?? "",
"x-amz-meta-location": fileUrl,
})
.status(hasFile ? needsUpdate ? HttpStatus.NOT_MODIFIED : HttpStatus.NO_CONTENT : HttpStatus.NOT_FOUND)
.send();
}
}
13 changes: 13 additions & 0 deletions src/social-card/highlight-card/highlight-card.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Module } from "@nestjs/common";
import { HttpModule } from "@nestjs/axios";
import { GithubModule } from "../../github/github.module";
import { S3FileStorageModule } from "../../s3-file-storage/s3-file-storage.module";
import { HighlightCardService } from "../highlight-card/highlight-card.service";
import { HighlightCardController } from "./highlight-card.controller";

@Module({
imports: [HttpModule, GithubModule, S3FileStorageModule],
providers: [HighlightCardService],
controllers: [HighlightCardController],
})
export class HighlightCardModule {}
Loading
Loading