본문 바로가기
개발/Git, GitHub

깃허브 액션 - Push 될 때 메일 보내기 (Send Email using GitHub Actions)

by 피로물든딸기 2023. 12. 16.
반응형

Git / GitHub 전체 링크

 

참고

- Node JS + jest를 GitHub Actions로 실행하기

- nodemailer로 구글, 네이버, 다음 카카오 메일 보내기

- 메일 알림 설정하기

 

깃허브 액션을 이용하여 repo에 push될 때마다 메일을 보내보자.

 

먼저 링크를 참고하여 아래의 sendEmail.js를 repository에 저장하자.

참고로 gmail의 경우 from을 설정할 필요가 없다.

const nodemailer = require('nodemailer');

async function sendEmail() {
  const transporter = nodemailer.createTransport({
    service: "gmail",
    secure: false,
    auth: {
      user: process.env.NODE_MAIL_USER,
      pass: process.env.NODE_MAIL_PASS,
    },
  });

  const mailOptions = {
    to: process.env.RECEIVER_EMAIL,
    subject: 'GitHub Action Email',
    text: 'This email was sent using GitHub Actions!',
  };

  try {
    const info = await transporter.sendMail(mailOptions);
    console.log('Email sent: ' + info.response);
  } catch (error) {
    console.error('Error occurred while sending email:', error);
  }
}

sendEmail();

 

이 예시에서는 auto-test 저장소의 actions 폴더에 저장하였다.

 

이제 깃허브 액션을 이용해 NODE_MAIL_USER, NODE_MAIL_PASS, RECEIVER_EMAIL를 설정하자.


Actions에서 사용할 Secrets Token 설정하기

 

NODE_MAIL_USERNODE_MAIL_PASS는 외부에 공개되서는 안 되는 중요한 정보다.

따라서 Secrets로 환경변수를 관리해야 한다.

 

저장소 Settings에서 Secrets and variables → Actions로 이동하자.

New repository secret 버튼을 클릭해서 변수와 값을 등록하면 된다.

 

버튼을 누르면 아래와 같이 Name과 Secret(변수)을 등록할 수 있다.

 

위 방법대로 NODE_MAIL_USERNODE_MAIL_PASS를 등록하자.


메일을 받는 사람 목록 관리하기

 

RECEIVER_EMAIL은 메일을 받는 사람인데, Secret으로 관리하는 것 보다, 파일로 관리하는 것이 편하다.

메일을 받는 사람들은 언제든지 변경될 수 있고, 비밀로 할 필요가 없어 보이기 때문이다.

 

아래와 같이 mail_receiver.txt를 actions 폴더 아래에 추가하자.


send-email.yml 파일 만들기

 

링크를 참고하여 send-email.yml 파일을 만들자.

name: Send Email

on:
  push:
    branches:
      - main

jobs:
  send_email:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v3
      
      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '16'

      # 파일을 읽어 메일을 받는 사람(RECEIVER_EMAIL)를 환경변수로 설정 
      - name: Read mail receiver
        id: read-file
        run: echo "RECEIVER_EMAIL=$(cat actions/mail_receiver.txt)" >> $GITHUB_ENV

      # nodemailer 설치
      - name: Install dependencies
        run: npm install nodemailer

      # sendEmail.js 실행
      - name: Send email
        run: |
          node ./actions/sendEmail.js
          
      # Secret에 설정한 변수를 환경 변수로 설정
        env:
          NODE_MAIL_USER: ${{ secrets.NODE_MAIL_USER }}
          NODE_MAIL_PASS: ${{ secrets.NODE_MAIL_PASS }}

 

만약 특정 파일이 변경될 때, 메일을 보내고 싶다면 아래와 같이 설정하면 된다.

on:
  push:
    paths:
      - 'your-directory/your-file.txt'
      
or

    paths:
      - 'your-directory/*' # 특정 디렉토리 내 모든 파일
      - 'your-directory/**/*.txt' # 특정 확장자를 가진 파일

 

이제 repo의 파일을 적절히 수정해서 main에 push하자.

이후 mail_receiver.txt에 등록된 email에 메일이 발송되는 것을 확인해 보자.

 

Actions에서도 결과를 확인할 수 있다.


메일 내용 변경하기

 

push를 할 때, commit의 제목message를 추출하여 메일을 보내보자.

 

yml에는 다음 내용을 추가한다.

message body의 경우, 환경변수에 담기 위해 개행 문자 "\n"로 묶어서 한 줄로 처리한다.

      # 최근 커밋의 제목 추출하여 환경 변수로 설정
      - name: Get commit message subject
        run: |
          COMMIT_MESSAGE_SUBJECT=$(git log -1 --pretty=format:%s)
          echo "COMMIT_MESSAGE_SUBJECT=${COMMIT_MESSAGE_SUBJECT}" >> $GITHUB_ENV
      
      # 최근 커밋의 메시지 추출하여 환경 변수로 설정
      - name: Get commit message body
        run: |
          COMMIT_MESSAGE_BODY=$(git log -1 --pretty=%B | tr '\n' '|' | sed 's/|/\\n/g')
          echo "COMMIT_MESSAGE_BODY=${COMMIT_MESSAGE_BODY}" >> $GITHUB_ENV

 

sendEmail.js의 mailOptions은 다음과 같이 수정한다.

  const mailOptions = {
    to: process.env.RECEIVER_EMAIL,
    subject: process.env.COMMIT_MESSAGE_SUBJECT,
    text: process.env.COMMIT_MESSAGE_BODY.replace(/\\n/g, '\n'),
  };

 

이제 README.md를 수정해보자.

 

정상적으로 메일을 받는다.

 

하지만 git log의 %B 형식에는 제목도 포함되기 때문에 body에도 제목이 포함되고 있다.

$ git log -1 --pretty=%B
Update README.md

- commit
- message
- 수정!!

 

따라서 아래와 같이 message를 변경하여 불필요한 첫 줄을 제거한다.

  let message = process.env.COMMIT_MESSAGE_BODY.replace(/\\n/g, "\n").split("\n");
  let contents = message.slice(2, message.length).join("\n");
  
  const mailOptions = {
    to: process.env.RECEIVER_EMAIL,
    subject: process.env.COMMIT_MESSAGE_SUBJECT,
    text: contents,
  };

 

이제 정상적으로 commit 제목내용이 메일로 전송된다.

 

전체 코드는 다음과 같다

.

actions/sendEmail.js

const nodemailer = require('nodemailer');

async function sendEmail() {
  const transporter = nodemailer.createTransport({
    service: "gmail",
    secure: false,
    auth: {
      user: process.env.NODE_MAIL_USER,
      pass: process.env.NODE_MAIL_PASS,
    },
  });
  
  let message = process.env.COMMIT_MESSAGE_BODY.replace(/\\n/g, "\n").split("\n");
  let contents = message.slice(2, message.length).join("\n");
  
  const mailOptions = {
    to: process.env.RECEIVER_EMAIL,
    subject: process.env.COMMIT_MESSAGE_SUBJECT,
    text: contents,
  };

  try {
    const info = await transporter.sendMail(mailOptions);
    console.log('Email sent: ' + info.response);
  } catch (error) {
    console.error('Error occurred while sending email:', error);
  }
}

sendEmail();

 

.github/workflows/send-email.yml

name: Send Email

on:
  push:
    branches:
      - main

jobs:
  send_email:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v3
      
      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '16'

      # 파일을 읽어 메일을 받는 사람(RECEIVER_EMAIL)를 환경변수로 설정 
      - name: Read mail receiver
        id: read-file
        run: echo "RECEIVER_EMAIL=$(cat actions/mail_receiver.txt)" >> $GITHUB_ENV

      # 최근 커밋의 제목 추출하여 환경 변수로 설정
      - name: Get commit message subject
        run: |
          COMMIT_MESSAGE_SUBJECT=$(git log -1 --pretty=format:%s)
          echo "COMMIT_MESSAGE_SUBJECT=${COMMIT_MESSAGE_SUBJECT}" >> $GITHUB_ENV
      
      # 최근 커밋의 메시지 추출하여 환경 변수로 설정
      - name: Get commit message body
        run: |
          COMMIT_MESSAGE_BODY=$(git log -1 --pretty=%B | tr '\n' '|' | sed 's/|/\\n/g')
          echo "COMMIT_MESSAGE_BODY=${COMMIT_MESSAGE_BODY}" >> $GITHUB_ENV

      # nodemailer 설치
      - name: Install dependencies
        run: npm install nodemailer

      # sendEmail.js 실행
      - name: Send email
        run: |
          node ./actions/sendEmail.js
          
      # Secret에 설정한 변수를 환경 변수로 설정
        env:
          NODE_MAIL_USER: ${{ secrets.NODE_MAIL_USER }}
          NODE_MAIL_PASS: ${{ secrets.NODE_MAIL_PASS }}
          COMMIT_MESSAGE_SUBJECT: ${{ env.COMMIT_MESSAGE_SUBJECT }}
          COMMIT_MESSAGE_BODY: ${{ env.COMMIT_MESSAGE_BODY }}

참고

 

yml에서 mail_receiver.txt를 읽지 않고, Node에서 fs 모듈을 이용하여 읽어도 된다.

const fs = require('fs'); // fs 모듈 추가
const nodemailer = require('nodemailer');

async function sendEmail() {
  ...
  
  let message = process.env.COMMIT_MESSAGE_BODY.replace(/\\n/g, "\n").split("\n");
  let contents = message.slice(2, message.length).join("\n");
  
  // mail_receiver를 직접 읽기
  let address = fs.readFileSync("actions/mail_receiver.txt", "utf8");
  
  const mailOptions = {
    to: address,
    subject: process.env.COMMIT_MESSAGE_SUBJECT,
    text: contents,
  };

  ...
}

sendEmail();
반응형

댓글