From 2c18b71969540c87e89050689e7bfd9b30654677 Mon Sep 17 00:00:00 2001 From: Nguyen <87511888+nknguyenhc@users.noreply.github.com> Date: Thu, 8 Feb 2024 08:18:22 +0800 Subject: [PATCH] Set default branch to `main` Previously, image uploads depend on the user's default branch. Now, we set the branch for image upload to be `main`. Images will be uploaded to `main` as a result. --------- Co-authored-by: Chee Hong --- src/app/core/services/github.service.ts | 82 +++++++++++++++++++++++++ src/app/core/services/upload.service.ts | 20 +++++- 2 files changed, 100 insertions(+), 2 deletions(-) diff --git a/src/app/core/services/github.service.ts b/src/app/core/services/github.service.ts index 0e954e113..b88f39b64 100644 --- a/src/app/core/services/github.service.ts +++ b/src/app/core/services/github.service.ts @@ -16,6 +16,7 @@ import { FetchLabelsQuery } from '../../../../graphql/graphql-types'; import { AppConfig } from '../../../environments/environment'; +import { throwIfFalse } from '../../shared/lib/custom-ops'; import { getNumberOfPages } from '../../shared/lib/github-paginator-parser'; import { IssueComment } from '../models/comment.model'; import { GithubUser } from '../models/github-user.model'; @@ -35,7 +36,9 @@ import { LoggingService } from './logging.service'; const { Octokit } = require('@octokit/rest'); const CATCHER_ORG = 'CATcher-org'; const CATCHER_REPO = 'CATcher'; +const BRANCH = 'main'; const UNABLE_TO_OPEN_IN_BROWSER = 'Unable to open this issue in Browser'; +const BRANCH_CREATION_FAILED = `Unable to create ${BRANCH} branch.`; function getSettingsUrl(org: string, repoName: string): string { return `https://raw.githubusercontent.com/${org}/${repoName}/master/settings.json`; } @@ -201,6 +204,84 @@ export class GithubService { octokit.repos.createForAuthenticatedUser({ name: name }); } + /** + * Creates the `main` branch for the current repository. + */ + createBranch() { + return this.getDefaultBranch().pipe( + mergeMap((res) => this.getBranchHeadInfo(res)), + map((res) => res.data.object.sha), + mergeMap((sha: string) => this.createBranchFromCommit(sha)), + mergeMap(() => this.isMainBranchPresent()), + throwIfFalse( + (isBranchPresent: boolean) => isBranchPresent, + () => new Error(BRANCH_CREATION_FAILED) + ) + ); + } + + /** + * Creates the `main` branch for the current repository, + * from the commit with the given SHA. + */ + createBranchFromCommit(commitSha: string) { + return from( + octokit.git.createRef({ + owner: ORG_NAME, + repo: REPO, + ref: `refs/heads/${BRANCH}`, + sha: commitSha + }) + ); + } + + /** + * Get the default branch of the specified repository. + * @param owner The owner of the repository. + * @param repo The name of the repository. + */ + getDefaultBranch(): Observable { + return from( + octokit.repos.get({ + owner: ORG_NAME, + repo: REPO + }) + ).pipe(map((res: any) => res.data.default_branch)); + } + + /** + * Get information of the head of the given branch name, + * in the current repository. + * @param branch The name of the branch. + */ + getBranchHeadInfo(branch: string): Observable { + return from( + octokit.git.getRef({ + owner: ORG_NAME, + repo: REPO, + ref: `heads/${branch}` + }) + ); + } + + /** + * Checks if the repo already has the branch `main`. + */ + isMainBranchPresent(): Observable { + return from( + octokit.git.getRef({ + owner: ORG_NAME, + repo: REPO, + ref: `heads/${BRANCH}` + }) + ).pipe( + map((res: any) => res.status !== ERRORCODE_NOT_FOUND), + catchError(() => { + return of(false); + }) + ); + } + /** * Fetches information about an issue using GraphQL. * @@ -360,6 +441,7 @@ export class GithubService { octokit.repos.createOrUpdateFile({ owner: ORG_NAME, repo: REPO, + branch: BRANCH, path: `files/${filename}`, message: 'upload file', content: base64String diff --git a/src/app/core/services/upload.service.ts b/src/app/core/services/upload.service.ts index 070484039..dc78e5ac3 100644 --- a/src/app/core/services/upload.service.ts +++ b/src/app/core/services/upload.service.ts @@ -1,6 +1,8 @@ import { Injectable } from '@angular/core'; -import { throwError } from 'rxjs'; +import { of, throwError } from 'rxjs'; +import { catchError, mergeMap } from 'rxjs/operators'; import { uuid } from '../../shared/lib/uuid'; +import { ERRORCODE_NOT_FOUND } from './error-handling.service'; import { GithubService } from './github.service'; const SUPPORTED_VIDEO_FILE_TYPES = ['mp4', 'mov']; @@ -49,7 +51,21 @@ export class UploadService { if (SUPPORTED_FILE_TYPES.includes(fileType.toLowerCase())) { base64String = base64String.split(',')[1]; const onlineFilename = uuid(); - return this.githubService.uploadFile(`${onlineFilename}.${fileType}`, base64String); + const attemptUploadFile = () => this.githubService.uploadFile(`${onlineFilename}.${fileType}`, base64String); + return attemptUploadFile().pipe( + catchError((err: any) => { + if (!(err.status === ERRORCODE_NOT_FOUND)) { + return throwError(err); + } + return of(false); + }), + mergeMap((isBranchPresent) => { + if (isBranchPresent) { + return of(isBranchPresent); + } + return this.githubService.createBranch().pipe(mergeMap(attemptUploadFile)); + }) + ); } else { return throwError(FILE_TYPE_SUPPORT_ERROR); }