Firebase 클라우드 함수: Git 명령 및 GitHub GraphQL API
향상된 웹 응용 프로그램으로 프레젠테이션을 온라인으로 배포할 수 있을 뿐 아니라, Dell 웹 소스 편집기는 현재 소스 코드를 GitHub으로 푸시할 수 있습니다.🎉.
이 새 함수는 Firebase Cloud Functions에서 실행됩니다.우리는 우리의 발견을 공유하는 것을 좋아하기 때문에 다음은 우리가 이러한 통합을 개발할 때 배운 관건적인 요소이다.
액세스 토큰
GitHub과 상호작용을 하려면 영패가 필요합니다.
개인 토큰
계정을 통해 GitHub과 상호 작용하려면 personal access token을 사용하십시오.Firebase 함수를 만든 후 구성을 설정할 수 있습니다.이렇게 하면 코드에서 혼동될 것입니다.
#!/bin/sh
firebase functions:config:set github.token="4a686......."
Firebase 인증 및 GitHub 토큰
사용자의 행동으로 GitHub과 상호작용하는 것에 관심이 있다면 Firebase UI과 Firebase Authentication을 사용할 수 있습니다.
제가 알기로는 이런 조합이 생겨서 불행히도 Firebase 클라우드에서 사용자의 GitHub 영패를 얻을 수 없습니다.인증 events에 연결하려고 했지만 트리거 대상에서 관련 정보를 찾지 못했습니다.
제가 뭘 놓쳤는지 이 상황에서 빨리 알려주세요(!),그러나 이러한 정보가 없으면 Firebase UI 구성의
signInSuccessWithAuthResult 콜백을 통해 찾아야 합니다.callbacks: {
  signInSuccessWithAuthResult: 
    (authResult: firebase.auth.UserCredential, _redirectUrl) => {
    const token: string =
      (userCred.credential as 
               firebase.auth.OAuthCredential).accessToken;
    return true;
  },
},
OAuthCredential의 변환은 answer으로 제공됩니다.*파일 시스템
진일보한 토론을 하기 전에, 당신은 우리가 클라우드에서 Git 명령을 어떻게 집행할 것인지를 스스로에게 물어볼 수 있습니다.나도 실제로 같은 질문을 했는데 Firebase 함수가 file system의 임시 폴더에 접근할 수 있다는 것이 증명되었다.
The only writeable part of the filesystem is the
/tmpdirectory, which you can use to store temporary files in a function instance. This is a local disk mount point known as a "tmpfs" volume in which data written to the volume is stored in memory. Note that it will consume memory resources provisioned for the function.
또한 임시 디렉터리는 기능 간에 공유할 수 없다.예를 들어, 이것은 이러한 폴더를 사용하여 데이터를 공유할 수 없다는 것을 의미한다.
tmp 주문서는 하드코딩이 필요하지 않습니다.대신 Node.js OS module을 사용하여 임시 폴더를 검색할 수 있습니다.만약 어떤 원인 때문 에 그것 이 미래 에 변화 를 일으킬 것 이라면, 너 는 영원히 모를 것 이다. 그것 은 더욱 편리할 것 이다😉.import * as os from 'os';
console.log(os.tmpdir()); // -> /tmp
import * as path from 'path';
import * as os from 'os';
export function getFilePath(...files: string[]): string {
  return path.join(os.tmpdir(), ...files);
}
console.log(getFilePath('yo', 'david.txt'); // -> /tmp/yo/david.txt
Git 명령
리포를 복제하거나 일반적으로commit,pull,push 등 Git 명령을 실행하기 위해서, Node에 simple-git 인터페이스를 사용하는 것을 권장합니다.js는 Steve King에서 개발(npm에 매주 150만 회 다운로드).이것은 정말 모든 일을 경감시켰다.
npm i simple-git --save
클론 복제
구체적으로 클론 기능은 다음과 같습니다.
import * as path from 'path';
import * as os from 'os';
import simpleGit, {SimpleGit} from 'simple-git';
export async function clone(repoUrl: string, repoName: string) {
  const localPath: string = path.join(os.tmpdir(), repoName);
  await deleteDir(localPath);
  const git: SimpleGit = simpleGit();
  await git.clone(repoUrl, localPath);
}
// Demo:
(async () => {
 await clone('https://github.com/deckgo/deckdeckgo/', 'deckdeckgo'); 
})();
deleteDir을 호출한 이유다.import * as rimraf from 'rimraf';
export function deleteDir(localPath: string): Promise<void> {
  return new Promise<void>((resolve) => {
    rimraf(localPath, () => {
      resolve();
    });
  });
}
npm i rimraf --save && npm i @types/rimraf --save-dev
밀다
Git 명령의 또 다른 흥미로운 예는 Push 요청입니다. 왜냐하면 우리는 영패를 사용하여 요청을 검증해야 하기 때문입니다.
토큰을 사용하는 해결 방안을 찾은 후에 나는 Stackoverflow 문답을 읽는 데 시간이 좀 걸렸고 토큰이 노출되지 않도록 함수에서 상호작용을 하더라도 가장 좋은 결과를 주는 해결 방안은 Git URI에서 사용하는 것이라고 결론을 내렸다.
영패는 잠재적인 오류 메시지에 노출될 수 있으니 주의하십시오. 이것이 바로 내가 이 소식을 정확하게 포착하는 것도 좋다고 생각하는 이유입니다.
기호화폐를 제외하고 GitHub 계정의
username(예를 들어 peterpeterparker)과 email을 제공해야 할 수도 있습니다.이러한 정보는 우리의 기능 설정을 통해 관리할 수 있다.import * as functions from 'firebase-functions';
import * as path from 'path';
import * as os from 'os';
import simpleGit, {SimpleGit} from 'simple-git';
export async function push(project: string,
                           branch: string) {
  try {
    const localPath: string = path.join(os.tmpdir(), repoName);
    // Git needs to know where is has to run, that's why we pass
    // the pass to the constructor of simple-git
    const git: SimpleGit = getSimpleGit(localPath);
    // Configure Git with the username and email
    const username: string = functions.config().github.username;
    const email: string = functions.config().github.email;
    await git.addConfig('user.name', username);
    await git.addConfig('user.email', email);
    // Finally Git push
    const token: string = functions.config().github.token;
    await git.push(`https://${username}:${token}@github.com/${username}/${project}.git`, branch);
  } catch (err) {
    throw new Error(`Error pushing.`);
  }
}
// Demo:
(async () => {
 await push('deckdeckgo', 'my-branch'); 
})();
GitHub GraphQL API
마지막 버전이나 새로운 버전은 관점에 따라 GitHub API 버전(v4)은GraphQL 조회에 사용할 수 있습니다.그것의 documentation은 검색 정보를 상대적으로 쉽게 하지만 explorer과 그의 자동 완성 기능은 조회를 신속하고 유연하게 조합하는 데 더욱 편리할 것이다.
묻다
나는 조회를 실행하기 위해 GraphQL 클라이언트 (예: Apollo) 를 사용하지 않았다.대신 HTTPS 요청을 수행하기 위해 함수를 개발했습니다.
import fetch, {Response} from 'node-fetch';
async function queryGitHub(githubToken: string, 
                           query: string): Promise<Response> {
  const githubApiV4: string = 'https://api.github.com/graphql';
  const rawResponse: Response = await fetch(`${githubApiV4}`, {
    method: 'POST',
    headers: {
      Accept: 'application/json',
      'Content-Type': 'application/json',
      Authorization: `token ${githubToken}`,
    },
    body: JSON.stringify({query}),
  });
  if (!rawResponse || !rawResponse.ok) {
    throw new Error('Cannot perform GitHub query.');
  }
  return rawResponse;
}
fetch을 제공할 수 없기 때문에 저는 node-fetch(npm을 매주 1600만 번 다운로드)을 사용했습니다.npm i node-fetch --save && npm i @types/node-fetch --save-dev
질의:사용자 정보
다음은 상대적으로 기본적인 조회 예이다.이러한 함수에서 GitHub
login ("사용자 이름") 과 id (각각 currently authenticated user) 의 정보를 검색하려고 합니다.export interface GitHubUser {
  id: string;
  login: string;
}
export function getUser(githubToken: string): Promise<GitHubUser> {
  return new Promise<GitHubUser>(async (resolve, reject) => {
    try {
      const query = `
        query {
          viewer {
            id,
            login
          }
        }
      `;
      const response: Response = 
            await queryGitHub(githubToken, query);
      const result = await response.json();
      resolve(result.data.viewer);
    } catch (err) {
      reject(err);
    }
  });
}
// Demo:
(async () => {
 const token: string = functions.config().github.token;
 const user = await getUser(token); 
 console.log(user); // -> {login: 'peterpeterparker', id: '123'}
})();
변이: 당김 요청
Pull 요청은 GraphQL 쿼리가 아니라 mutation 쿼리입니다.이전의 검색에 비해 더 많은 정보를 필요로 하지만, 배후의 논리는 같다. GraphQL 검색/변이를 작성하여 HTTPS를 통해 요청을 보내고 결과를 얻는 것이다😁.
주목할 점은 PR을 만들기 위해서는 돌연변이에
repositoryId이 필요하다는 점이다.repository 정보를 요청할 때 제공하는 쿼리와 같은 다른 GraphQL 쿼리를 통해 이 정보를 찾을 수 있습니다.export function createPR(githubToken: string,
                         repositoryId: string,
                         branch: string): Promise<void> {
  return new Promise<void>(async (resolve, reject) => {
    try {
      const title: string = 'feat: my title';
            const body: string = `# The Pull Request body.
      It supports *Markdown*.`;
     // We want to provide a PR from a branch to master
     const query = `
             mutation CreatePullRequest {
               createPullRequest(input:{baseRefName:"master",body:"${body}",headRefName:"${branch}",repositoryId:"${repositoryId}",title:"${title}"}) {
                 pullRequest {
                   id
                 }
               }
             }
           `;
      const response: Response = 
            await queryGitHub(githubToken, query);
      const result = await response.json();
      if (!result || !result.data || 
          !result.data.createPullRequest || result.errors) {
        resolve(undefined);
        return;
      }
      resolve();
    } catch (err) {
      reject(err);
    }
  });
}
// Demo:
(async () => {
 const token: string = functions.config().github.token;
 await createPR(token, '6789', 'my-branch');
})();
요약
이 기능을 개발하는 과정에서 저는 새로운 것을 많이 배웠습니다. 저는 이 블로그의 도움으로 제 주요 경험을 나눌 수 있기를 바랍니다.
그 밖에 우리는 원본을 만들었습니다. 당신은 언제든지 우리 repo의 원본 코드를 보거나 우리 프로젝트에 공헌할 수 있습니다.
다음 강연에서 DeckDeckGo을 사용해 보시는 것도 환영합니다.
저도 계산을 기대하고 슬라이드 소스 코드가 포함된 GitHub repos를 시도해 보겠습니다.😉.
무한원까지!
다윗
Lukas Blazek의 표지 배경 사진
Reference
이 문제에 관하여(Firebase 클라우드 함수: Git 명령 및 GitHub GraphQL API), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/daviddalbusco/firebase-cloud-functions-git-commands-github-graphql-api-1560텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
                                
                                
                                
                                
                                
                                우수한 개발자 콘텐츠 발견에 전념
                                (Collection and Share based on the CC Protocol.)