본문 바로가기

스터디-ing/Programming

[Electron] 자동 업데이트 electron-updater(with Github)

Electron을 유지보수 및 업데이트 하기 위해서 빌드한 설치 파일을 지속적으로 배포해야 합니다.

이 글에서는 electron-updater와 Github를 이용해 간단한 Electron 자동 업데이트 방식을 공유하려 합니다.

[패키지 설치]

* PS. 테스트를 하면서 패키지 버전따라 원인모를(?) 여러가지 이슈가 있어서 테스트 성공한 버전을 기재 했습니다. 이점 참고하여 프로젝트에 맞는 버전을 사용하시길 바랍니다.

 

1. npm install --save-dev electron electron-builder

   - 개발 단계에서 필요한 electron과 electron-builder 패키지를 설치합니다.

   - 설치가 완료되었다면 package.json에 아래와 같이 확인할 수 있습니다.

"devDependencies": {
  "electron": "^18.0.3",
  "electron-builder": "~22.10.5"
}

2. npm install --save electron-updater

   - 설치파일과 함께 배포해야 하는 패키지를 설치합니다.

   - 설치가 완료되었다면 package.json에 아래와 같이 확인할 수 있습니다.

"dependencies": {
  "electron-updater": "^4.0.0"
}

 

[코드 작성]

* 해당 코드는 electron-updater-example을 참고하여 작성했습니다.

  URL: https://github.com/iffy/electron-updater-example

 

GitHub - iffy/electron-updater-example: A complete example showing how to use `electron-updater`

A complete example showing how to use `electron-updater` - GitHub - iffy/electron-updater-example: A complete example showing how to use `electron-updater`

github.com

1. main.js

const {app,dialog, BrowserWindow} = require('electron');
const {autoUpdater} = require("electron-updater");

/**
 * electron-updater는 신규 버전 설치 파일을 자동으로 다운로드 하고 프로그램이 종료되면 
 * 자동으로 설치 파일이 실행되면서 업데이트 되는데
 * autoInstallOnAppQuite = false 설정으로
 * 프로그램이 종료되더라도 자동으로 업데이트 되지 않도록 설정 가능하다.
 */
autoUpdater.autoInstallOnAppQuit = false;

let updateWin;

// 현재 상태를 화면으로 볼 수 있도록 html로 전달하는 함수
function writeMessageToWindow(text) {
  updateWin.webContents.send("message", text);
}

function createWindow() {
  updateWin = new BrowserWindow({
    webPreferences: { 
      nodeIntegration: true,
      contextIsolation: false, // html <script> 태그에서 require를 호출하기 위함.
    },
  });

  updateWin.webContents.openDevTools();
  updateWin.loadURL(`file://${__dirname}/index.html#v${app.getVersion()}`);
  return updateWin;
}

// 신규 버전 릴리즈 확인 시 호출 됨
autoUpdater.on("checking-for-update", () => {
  writeMessageToWindow("업데이트 확인 중...");
});

// 업데이트 할 신규 버전이 있을 시 호출 됨
autoUpdater.on("update-available", () => {
  writeMessageToWindow("신규 버전 확인 및 업데이트 가능.");
});

// 업데이트 할 신규 버전이 없을 시 호출 됨
autoUpdater.on("update-not-available", () => {
  writeMessageToWindow("신규 버전 없음.");
});

// 업데이트 확인 중 에러 발생 시 호출 됨
autoUpdater.on("error", (err) => {
  writeMessageToWindow("에러 발생 : " + err);
});

// 업데이트 설치 파일 다운로드 상태 수신
// 해당 단계까지 자동으로 진행 됨
autoUpdater.on("download-progress", (progressObj) => {
  let progressMsg = "Downloaded " + progressObj.percent + "%"
  writeMessageToWindow(progressMsg);
});

// 업데이트 설치 파일 다운로드 완료 시 업데이트 진행 여부 선택
autoUpdater.on("update-downloaded", (info) => {
  writeMessageToWindow("신규 버전 설치 파일 다운로드 완료.");

  const option = {
    type: "question",
    buttons: ["Yes", "No"],
    defaultId: 0,
    title: "UPDATER",
    message: "프로그램 업데이트를 진행하시겠습니까?",
  };
  
  dialog.showMessageBox(updateWin, option).then(function(res){
    writeMessageToWindow(res.response.toString());
    
    // 위에 option.buttons의 Index = res.response
    if(res.response == 0){
      writeMessageToWindow('프로그램 종료 및 업데이트');
      autoUpdater.quitAndInstall();
    }
    else{
      writeMessageToWindow('프로그램 업데이트 안함');
    }
  });
});

// 윈도우 로드
app.on("ready", async () => {
  createWindow();
  autoUpdater.checkForUpdates();
});

2. index.html

<!DOCTYPE html>
<html>
  <head>
    <title>Electron Updater Example</title>
  </head>
  <body>
    <h1>hihi latest version update link update</h1>
    Current version: <span id="version">vX.Y.Z</span>
    <div id="messages"></div>
    
    <script>
      // Display the current version
      let version = window.location.hash.substring(1);
      document.getElementById('version').innerText = version;

      // Listen for messages
      const {ipcRenderer} = require('electron');
      ipcRenderer.on('message', function(event, text) {
        var container = document.getElementById('messages');
        var message = document.createElement('div');
        message.innerHTML = text;
        container.appendChild(message);
      })
    </script>
  </body>
</html>

 

[github repository 작성]

1. package.json에 github repository를 추가합니다.

"repository": {
    "type": "git",
    "url": "Github HTTPS 주소"
 }

 

[personal access token 설정]

* github release를 사용하기 위해서는 personal access token를 발급 받아 deploy 해야 합니다.

1. github에서 personal access token 발급 받기

  - Settings > Developer settings > Personal access tokens > Generate new token

 

2. personal access token 사용

 * personal access token을 사용하는 방법은 여러가지 방법이 있어 보는 듯 한데 이 글에서는 두가지 방법을 제시 드립니다. 해당 글에서는 시스템 환경변수로 설정하여 진행하였습니다.

  - 시스템 환경 변수로 설정하여 사용(설정 후 PC 리부팅 필요)

    변수 이름 : GH_TOKEN

    변수 값 : personal access token

  - package.json에 scripts 명령어에 설정

"scripts": {
    "start": "electron .",
    "deploy": "electron-builder GH_TOKEN={personal access token} build --win --publish always"
},

 

[Deploy 스크립트 작성]

* 해당 글에서는 github personal access token 시스템 환경변수로 설정하여 진행하였습니다.

1. package.json에 scripts 작성

"scripts": {
    "start": "electron .",
    "deploy": "electron-builder build --win --publish always"
}

 

[Release]

1. 프로젝트 Terminal을 이용해 github에 빌드파일을 배포합니다.

$ npm run deploy

> electron-quick-start@1.0.15 deploy E:\kmlee\dev\test\update_test
> electron-builder build --win --publish always

  • electron-builder  version=22.10.5 os=10.0.19041
  • writing effective config  file=dist\builder-effective-config.yaml
  • packaging       platform=win32 arch=x64 electron=18.0.3 appOutDir=dist\win-unpacked
  • Unpacking electron zip  zipPath=undefined
  • default Electron icon is used  reason=application icon is not set
  • signing         file=dist\win-unpacked\electron-quick-start.exe certificateFile=E:\kmlee\DOF\publish_keyfile\dof-lab.com.pfx
  • building        target=nsis file=dist\electron-quick-start Setup 1.0.15.exe archs=x64 oneClick=true perMachine=false
  • signing         file=dist\win-unpacked\resources\elevate.exe certificateFile=E:\kmlee\DOF\publish_keyfile\dof-lab.com.pfx
  •   Signing NSIS uninstaller  file=dist\__uninstaller-nsis-electron-quick-start.exe certificateFile=E:\kmlee\DOF\publish_keyfile\dof-lab.com.pfx
  • signing         file=dist\electron-quick-start Setup 1.0.15.exe certificateFile=E:\kmlee\DOF\publish_keyfile\dof-lab.com.pfx
  • building block map  blockMapFile=dist\electron-quick-start Setup 1.0.15.exe.blockmap
  • publishing      publisher=Github (owner: lkm101, project: auto_update, version: 1.0.15)
  • uploading       file=electron-quick-start-Setup-1.0.15.exe.blockmap provider=GitHub
  • uploading       file=electron-quick-start-Setup-1.0.15.exe provider=GitHub
  • creating GitHub release  reason=release doesn't exist tag=v1.0.15 version=1.0.15
    [====================] 100% 0.0s | electron-quick-start-Setup-1.0.15.exe to GitHub

 

2. Github Release에 Draft로 등록 되었는지 확인 합니다.

3. 최종적으로 Release 하기 위해 Publish release를 합니다.

 

[자동 업데이트 확인]

1. 신규버전 없을 시

2. 신규버전 있을 시

 - '예'를 선택하면 업데이트가 진행됩니다.