디스코드 포럼에 Github 알림 받기

TL:DR

디스코드에 포럼 기능이 생겼다. 이제 주제별로 글을 쓰고 스레드를 남길 수 있다. 이전에는 깃허브 웹후크을 연동할 때 마다 하나의 채팅방에 여러개의 메시지가 섞이거나 여러개의 채팅방을 만들어야 했는데 이제 주제별로 포스트를 생성해 스레드로 남기면 된다!!!

포럼 채널에 웹후크 만들기

채널 설정 > 연동 > 웹후크에서 웹후크를 추가한다. 웹후크 URL 복사를 클릭한다. 웹후크 URL은 나중에 사용하기 때문에 따로 저장을 해둔다.
Alt text

포스트 작성

알림을 받을 포스트를 작성한다. 그 후 스레드ID 복사하기를 클릭한다. 이 스레드 ID도 나중에 사용하기에 따로 저장을 해둔다.
Alt text

개발자 모드가 활성화 상태여야 합니다.

Github repository에 웹후크 추가하기

Github의 리포지토리로 이동하여 Setting > Webhooks에서 웹후크를 추가한다.
Alt text

  1. Add webhook를 클릭한다.
  2. Payload URL에 WEBHOOK_URL/github?thread_id=POST_ID를 입력한다. 이전에 저장한 값을 이용하면 된다.
    • WEBHOOK_URL : 웹후크 URL
    • POST_ID : 스레드 ID
  3. 콘텐츠 유형으로 application/json을 선택한다.

Which events would you like to trigger this webhook? 에서 Just the push event.를 체크했다. 푸시될 때마다 메시지를 보내고 싶기 때문이다.

완료되면 Add webhook 버튼을 클릭한다.

Finish

Alt text
이제 푸시되면 해당 포스트에 메시지가 날라온다!

나의 WASM 프로젝트 세팅 - embind

TL;DR

이전글 에서 c++ 코드를 웹에서 실행할 수 있게 되었다. 하지만 이전에는 main함수의 내용을 바로 실행했다면 이번에는 c++ 함수나 클래스를 자바스크립트에서 호출하고자 한다!!

embind

embind는 c++ 함수나 클래스를 자바스크립트에 바인딩 하는 기술이다. 위에서 말했듯이 c++ 함수나 클래스를 자바스크립트에서 호출 하거나, c++ 객체를 생성할 수 있다.

embind 사용 방법

EMSCRIPTEN_BINDINGS 매크로를 사용하여 C++ 코드에서 바인딩 할 클래스 및 함수를 정의하면 된다.

1
2
3
4
5
6
7
8
9
#include <emscripten/bind.h>

int Add(int a, int b) {
return a + b;
}

EMSCRIPTEN_BINDINGS(add_binding) {
emscripten::function("Add", &Add);
}

int Add(int, int) 함수를 자바스크립트에서 노출할 수 있도록 했다.

해당 코드를 lembind 옵션을 사용하여 컴파일 하면 된다.

1
emcc -lembind -o add.js add.cpp

웹에서는 다음과 같이 사용하면 된다.

1
2
3
4
5
6
7
8
9
10
11
12
<!doctype html>
<html>
<script>
var Module = {
onRuntimeInitialized: function() {
console.log('lerp result: ' + Module.add(1, 2));
}
};
</script>
<script src="add.js"></script>
</html>

onRuntimeInitialized를 사용하여 런타임이 준비되었을 때 코드를 실행한다.

번들링

물론 c++로 뽑아낸 자바스크립트만 사용하는 경우도 있지만 다른 자바스크립트들과 사용할 경우 묶어서 사용하는 번들링 기술을 사용하는 것도 좋다고 생각해서 번들링을 설정했다.

Rollup

여러가지 번들링 도구 중 Rollup을 사용한 큰 이유는 없다. 그냥 내가 보기에 간단해 보이고 성공했기 때문이다.

Install

필요한 플러그인을 다운받았다.

1
npm install -D rollup @rollup/plugin-commonjs @rollup/plugin-node-resolve rollup-plugin-polyfill-node
  • @rollup/plugin-commonjs : CommonJS 모듈 형식으로 작성된 코드를 ES 모듈 형식으로 변환한다.
  • @rollup/plugin-node-resolve : 외부 모듈(node_modules) 사용 시 사용한다.
  • rollup-plugin-polyfill-node : Node.js 환경에서 사용 가능한 전역 객체나 함수를 브라우저에서 사용할 수 있도록 polyfill을 제공한다.

이러한 용도로 해당 플러그인을 설정했다.

Setting

1
2
3
4
5
6
7
8
9
10
11
12
13
import commonjs from '@rollup/plugin-commonjs';
import {nodeResolve} from '@rollup/plugin-node-resolve';
import nodePolyfills from 'rollup-plugin-polyfill-node';

export default {
input: 'index.js',
output: {
file: './dist/index.js',
format: 'umd',
name: 'Wasm',
},
plugins: [nodeResolve(), commonjs(), nodePolyfills()]
};

index.js를 진입점으로 설정하고 output 설정을 해주었다. format은 umd를 사용하여 모듈 방식을 커버할 수 있도록 했다.

이제 wasm 글루코드를 번들링해보도록 한다.

1
-s WASM=1 -lembind -s MODULARIZE=1 -s 'EXPORT_NAME=\"wasm\"'

옵션은 다음과 같이 지정했다.

MODULARIZE을 추가한 이유는 익스포트한 자바스크립트가 모듈 형태로 되는 것도 있고, 이 모듈이 factory 함수 형태 반환하는데 factory 함수를 호출하면, 생성된 모듈이 다운로드되고 인스턴스화되는 과정이 진행되며 factory 함수가 반환하는 Promise가 resolved가 된다고 한다.

로딩이 완료되는 시점에 c++로 바인딩한 함수를 사용할 수 있게 된다. 로드가 안된 상태에서 불러오는 불상사를 막을 수 있다.

https://emscripten.org/docs/getting_started/FAQ.html#how-can-i-tell-when-the-page-is-fully-loaded-and-it-is-safe-to-call-compiled-functions 해당 링크를 확인하면 된다.

1
2
3
4
5
6
7
8
9
import wasm from './src/EmscriptenProject.js';

async function Init() {
let wasmModule;
await wasm().then(function(Module) { wasmModule = Module });
return wasmModule;
}

export {Init};

롤업의 input인 index.js이다. 간단하게 모듈을 로드를 하고 완료되면 모듈을 반환하도록 만들었다.

1
rollup -c

해당 명령어를 통해 번들링을 진행하면 dist폴더에 번들링된 index.js 파일이 생긴다. 여기서 주의할 점은 dist폴더 안에 .wasm파일도 있어야한다. 이 경로로 .wasm 파일을 옮겨주면 된다.

html 스크립트를 로드하고 사용하면 된다.

1
2
3
4
5
6
7
8
<!doctype html>
<html>
<script src="index.js"></script>
<script type="Module">
var wasmModule = await Wasm.Init();
console.log(wasmModule.Add(1,1));
</script>
</html>

html의 로그를 확인해보면 c++로 바인딩한 Add함수가 실행되는 것을 알 수 있다.

스크립트 작업

현재는 c++ 빌드 -> 번들링하는 작업 이렇게 2가지 작업이 진행된다. 이걸 자동화를 해보자.

이전글 빌드 명령어 스크립트를 실행하면 번들링까지 되도록 하면 된다.

CMakeLists.txt에 다음의 코드를 추가하면 된다.

1
2
3
4
5
set(ROLLUP_OPTS ${CMAKE_CURRENT_SOURCE_DIR}/../web/rollup.config.mjs)
ADD_CUSTOM_COMMAND(TARGET EmscriptenProject
COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR}/../web && npx rollup -c ${ROLLUP_OPTS}
COMMAND ${CMAKE_COMMAND} -E copy ${OUTPUT_DIR}/EmscriptenProject.wasm ${CMAKE_CURRENT_SOURCE_DIR}/../web/dist
)

소스 코드가 빌드 될 때 실행되는 커스텀 명령어를 정의했다. 웹 관련 코드가 저장되어 있는 디렉토리로 작업 디렉토리를 변경하고, 롤업의 설정파일을 실행했다. 그러면 롤업 설정에 따라 dist 디렉토리에 번들링한 index.js가 생성되었을 것이다.
그 다음 코드는 wasm 파일을 dist 파일로 복사한다.

이러면 c++ 빌드할 때 자동으로 번들링까지 진행된다!!!

이제 취향껏 package.json의 scripts에 작성을 추가하면 된다.

여담

자바스크립트나 웹 환경을 잘 모르는 초보 개발자가 해냈습니다. 추후에 라이브러리나 SDK로 배포를 하게 된다면 최종적으로 사용자가 쓰는 부분은 깔끔하게 간단하게 쓰이는 것이 좋다고 생각해서 이것저것 조사해보고 시행착오 끝냈다.

나름 검색해도 정보가 사혼의 조각처럼 흩어졌기 때문에 정리했다!! 이제는 좀 더 작게작게 emscripten의 팁을 올려야겠다.

나의 WASM 프로젝트 세팅

TL;DR

emscripten은 c++을 이용해서 웹프로그래밍을 할 수 있다는 것이 너무 매력적이다.
회사 업무로적이나 개인적으로나 관심이 많아 이것저것 시도해보고 있다. 내가 사용하는 방법을 정리하고자 한다.

기본적인 방법

emscripten 공식 홈페이지에서 안내하는 방법이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# Get the emsdk repo
git clone https://github.com/emscripten-core/emsdk.git

# Enter that directory
cd emsdk

# Fetch the latest version of the emsdk (not needed the first time you clone)
git pull

# Download and install the latest SDK tools.
./emsdk install latest

# Make the "latest" SDK "active" for the current user. (writes .emscripten file)
./emsdk activate latest

# Activate PATH and other environment variables in the current terminal
source ./emsdk_env.sh

git에서 sdk를 설치한 후 원하는 emscripten 버전을 설치. 그 다음 활성화 하는 것이다.

그 후 빌드를 하면 된다. emcc 명령어에 빌드할 파일을 추가시키면 된다.

1
./emcc test/hello_world.c -o hello.html

html 파일도 같이 얻고 싶기 위해서 -o 명령어를 사용해 html을 얻는다.
자세한 내용은 여기서 확인하면 된다.

하지만 파일이 하나라면 이 방법이 편한데 만약 프로젝트가 크다면 불편하다. cmake를 이용해 빌드하는 방법을 주로 사용한다.

CMake

나의 프로젝트 구성은 다음과 같다.

1
2
3
4
5
6
.
|____cpp
| |____CMakeLists.txt
| |____src
| | |____main.cpp
|____web

cpp 폴더에는 c++ 프로젝트에 대한 것을 다 포함 시킨다.web 폴더에는 web에 관한 파일들을 포함 시킬 예정이다.

CMakeFile 내용은 다음과 같다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
cmake_minimum_required(VERSION 3.0.0)
project(EmscriptenProject VERSION 0.1.0)


add_executable(EmscriptenProject src/main.cpp)

if(EMSCRIPTEN)
set(OUTPUT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../web/src)
set_target_properties(EmscriptenProject PROPERTIES
RUNTIME_OUTPUT_DIRECTORY ${OUTPUT_DIR}
SUFFIX ".html"
LINK_FLAGS "-s WASM=1"
)

endif()

OUTPUT_DIR에 export할 .wasm, .js, .html 경로를 설정해준다.
SUFFIX으로 html 파일이 익스포트할 거라고 알리고 LINK_FLAGS에 emscripten 옵션을 추가해주면 된다. 여기서 확인하고 필요한 옵션을 추가하면 된다.

해당 main.cpphello world를 출력하는거라서 많은 옵션을 추가하지 않았다.

빌드 명령어는 다음과 같다.

1
2
cmake -S . -B ./.web-build --toolchain ./emsdk/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake
cmake --build ./.web-build --config Release

CMakeLists.txt 파일이 존재하는 경로에서 실행하면 된다. 여기서 --toolchain 다음 부분에 자신의 emsdk 경로를 추가하면 된다.

빌드 후 파일 구조는 다음과 같다(기타 파일들을 가렸다).

1
2
3
4
5
6
7
8
9
10
11
.
|____web
| |____src
| | |____EmscriptenProject.js
| | |____EmscriptenProject.wasm
| | |____EmscriptenProject.html
|____cpp
| |____CMakeLists.txt
| |____.web-build
| |____src
| | |____main.cpp

web/scr에 파일이 추가된 것을 확인할 수 있다. html을 바로 클릭하면 실행할 수 없다. XHR 요청을 지원하지 않으면 .wasm 파일을 요청할 수 없기 때문이다. 로컬 웹서버를 사용해야한다. 나는 주로 vscodeLive Server를 사용한다.

html을 실행하면 hello world!가 출력되는 것을 확인할 수 있다.

쉘 스크립트 작성

명령어를 일일히 입력하기 귀찮기 때문에 쉘 스크립트를 추가한다. 우선 emscripten을 설치하는 스크립트를 작성했다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# install_emsdk.sh

DIRECTORY="$( cd "$( dirname "$0" )" && pwd -P )"

cd ${DIRECTORY}

# Get the emsdk repo
git clone https://github.com/emscripten-core/emsdk.git

# Enter that directory
cd emsdk

# Fetch the latest version of the emsdk (not needed the first time you clone)
git pull

# Download and install the latest SDK tools.
./emsdk install latest

# Make the "latest" SDK "active" for the current user. (writes .emscripten file)
./emsdk activate latest

최초 1회만 실행하면 된다. 그러면 install_emsdk.sh 가 위치한 곳에 emsdk를 다운받고 설치한다.

그 다음 빌드 명령어도 스크립트로 만든다.

1
2
3
4
5
6
# build_web.sh
CURRENT_DIRECTORY="$( cd "$( dirname "$0" )" && pwd -P )"
EMSDK=${CURRENT_DIRECTORY}/emsdk

cmake -S ${CURRENT_DIRECTORY} -B ${CURRENT_DIRECTORY}/.web-build --toolchain "${EMSDK}/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake"
cmake --build ${CURRENT_DIRECTORY}/.web-build --config Release

쉘 스크립트 실행으로 빌드까지 할 수 있다. 쉘 스크립트 위치는 cpp 폴더에 포함 시켰다.

1
2
3
4
5
6
7
8
9
10
11
12
13
.
|____web
| |____src
| | |____EmscriptenProject.js
| | |____EmscriptenProject.wasm
| | |____EmscriptenProject.html
|____cpp
| |____CMakeLists.txt
| |____build_web.sh
| |____install_emsdk.sh
| |____.web-build
| |____src
| | |____main.cpp

빌드 까지 완료한 파일 구조이다.

샘플 프로젝트

저장소를 만들었으니 여기서 확인하면 된다.
https://github.com/keea/sample-emscripten-project-template

여담

우선 간단한 샘플 만드는 것부터 정리했다. 그 외에 다양한 방법을 연구한 것이 있는데 추후에 문서를 작성하고 여기에 추가하도록 하겠다. 예를 들어 js만 뽑아서 번들링 한다던가… 리엑트와 연동시킨다던가 등등!!

그리고 샘플 저장소의 README는 ChatGPT가 적어줬다.

HackMD 글을 Hugo 형태로 변경

TL;DR

HackMD라는 마크다운 에디터를 찾았다. 에디터도 마음에 들지만 깃허브로 푸시하여 문서들을 관리할 수 있다. 그렇다면 해당 문서들을 정적 블로그의 포스트로 사용하는 것이 좋다고 생각했고 이 부분을 자동화하고자 했다.

그래서 현재 HackMD에서 작성한 문서를 레파지토리에 푸시하면 hugo 포스트 형식으로 변환하여 hugo 홈페이지에 적용했다.

date 추가하기

최초 레파지토리에 푸시할 때 자동적으로 date를 추가했다. 이것은 아래와 같이 진행했다.

이 부분은 https://fatihkalifa.com/twitter-github-actions 해당 글을 참고하여 작업했다.

1
git diff --name-status HEAD~1 | grep ".md$" | grep "^A" | cut -c 3-

git diff 명령어를 사용하면 파일의 어떤 내용이 변경되는지 알 수 있다. HEAD~1로 가장 최신의 변경 사항을 가져온다.

  • git diff --name-status HEAD~1 다음과 같은 결과를 얻을 수 있다.

    1
    2
    M       test34567.md
    A test555.md

여기서 원하는 것은 새로 추가된 test555.md이다. 그래서 grepcut 명령어를 통해 원하는 것을 파싱을 했다.

  • grep ".md$" : md 파일 찾는다.
  • grep "^A" : A로 시작한 것을 찾는다. git diff로 확인하면 맨 처음에 A(Add), M(Modify) 등으로 표시한다.
  • cut -c 3- : 불필요한 명령어들을 삭제해버린다.

위의 명령어를 실행 시 다음과 같은 결과를 얻었다.

1
test555.md

새로 추가된 마크다운 문서의 파일명을 구했으니 date를 추가하면 된다.

1
sed -i "/^date:/s/.*/date: `date "+%Y-%m-%d %H:%M:%S"`/g" test555.md

sed 명령어를 통해 파일의 내용을 변경하도록 했다. date: 라는 부분을 찾아 date: {현재날짜}로 변경한다. 이걸 하기 위해서는 해당 문서 안에 date: 부분이 있어야한다.

뭐 이 정도는 HackMD의 템플릿 기능을 사용해 자동으로 추가했다.

현재 날짜는 date명령어를 통해 구했다. date "+%Y-%m-%d %H:%M:%S" 를 사용하여 hugo 형식인 “년-월-일 시간” 포맷을 취할 수 있다.

그 후 변경된 내용을 커밋하면 되는 것이다!!

hugo 형태의 파일 트리 만들기

이제 날짜를 추가했으니 hugo 홈페이지에 보일 수 있게 파일 구조도 신경써야한다.

1
2
3
4
5
./content
|____posts
| |____start
| | |____feature.jpg
| | |____index.md

내가 사용하는 템플릿 콘텐츠 파일 구조에는 블로그 포스트들을 저장하는 posts라는 폴더가 있으며 각 포스트별로 제목(ex:start) 폴더 안에 실제 포스트인 index.md와 썸네일인 feature.jpg로 구성되어 있다.

마크다운 파일 이름을 구해 폴더를 만들고 해당 마크다운의 이름을 index.md로 만들면 된다고 생각했다.
파일명은 위에서 같이 구하면 되고 이름은 basename 이라는 명령어를 사용하면 구할 수가 있다고 해서 바로 시작했다.

1
title=$(basename ${{ steps.push-file.outputs.file }} .md)

basename으로 파일명을 구하고 .md명령어로 확장자를 제거해버렸다. 어차피 위에서 md파일만 구하기 때문에 상관 없었다.

이름 변경하는 것이나 파일 위치 변경하는 것은 mv 명령어를 사용하면 된다.

이후 나는 hugo라는 브런치를 만들어서 따로 관리하고 싶었다. hugo 같은 경우도 빌드한 후 빌드의 산출물을 다른 브런치에다가 다 저장하는 것이다. 나도 이걸 하고 싶었다!!

대충 생각한 플로우는 다음과 같다.

  1. hugo 사이트에서 content/post에 hackmd 저장소를 서브모듈로 등록.
  2. hackmd에서 문서 작성 후 푸시.
  3. hackmd 저장한 레파지토리에서 hugo 형식에 맞게 변경.
  4. 변경 후 hugo 레파지토리도 같이 업데이트.

브런치 작업

우선 빈 브런치부터 만들었다. 이런 것을 고아브런치라고 하는 것을 알았다. https://blog.naver.com/writer0713/221611414098 글을 참고해서 hugo-content 고아 브런치를 만들었다.

1
2
3
4
git checkout --orphan hugo-content
git rm -rf .
git commit --allow-empty -m "init hugo content"
git push origin hugo-content

그 후 위에 작업한 것을 커밋을 하기 위해 새로운 폴더를 만들고 github action 안에서 커밋을 했지만 맘에 들지 않았다. content/post/start 로 되어있는 것보다 post 폴더 안에 있는 내용물만 푸시하고 싶기 때문이다. 그래서 peaceiris/actions-gh-pages@v3 소스코드를 까봤다.

여기서 해결하는 방법은 푸시하고 싶은 내용물이 든 폴더에 .git 폴더를 복사해 넣고 커밋한 후 푸시하는 것이다!! 나는 해당 폴더에 git init로 초기화 해 다시 다 설정해야하나 생각했는데 .git폴더를 복사하면 설정을 다시 안해도 되기 때문에 좋다!!

1
2
3
4
5
6
7
8
9
10
11
mkdir -p ${dir}/${content}/${title}
cp -r ${dir}/.git ${dir}/${content}
cd ${dir}/${content}
git fetch origin
git checkout hugo-content
mv ${{ steps.push-file.outputs.file }} ${dir}/${content}/${title}/${filename}
git add --all
git config --global user.email ${{ secrets.EMAIL }}
git config --global user.name ${{ secrets.USER_NAME }}
git commit -am "[POST] Add Hugo Post"
git push origin hugo-content

폴더 만들고 .git파일 복사하고 커밋할 파일 옮기고 커밋하고 푸시하는 것까지 완료했다. 이제 hugo-content 브런치에는 hugo 형태의 포스터 파일만 남아있게 되었다!!

썸네일 추가하기

간지나게 썸네일도 추가하고 싶었다. 썸네일이 없으니 심심해서 추가하고 싶었다. 근데 썸네일을 찾아서 추가하고 싶지는 않았다. 자동으로 그리는 프로그램을 만들어야 하나??? 아니면 좀 더 빠르게 할 수 있는 방법이 있지 않나 생각보다가 NASA에서 매일마다 우주 사진을 업로드를 해준다는 것이 생각났다.

Astronomy Picture of the Day(https://apod.nasa.gov/apod/astropix.html) 일명 APOD로 우주 사진과 우주에 대한 설명을 해준다. 썸네일로도 괜찮은 것 같고 블로그 스킨에도 잘 어울렸다.

‘아 이걸 사용하면 되겠다’ 생각하며 좀 더 API(https://api.nasa.gov/)도 제공해준다는 것이다. 이런 것은 빠르게 작성할 수 있는 Python을 이용해서 만들어보았다.

1
2
3
4
5
6
7
8
9
def fetch_apod(date):
apod_url = "https://api.nasa.gov/planetary/apod"
params = {
'api_key':os.environ.get('APOD_API_KEY'),
'date':date,
'hd':'True'
}
response = requests.get(apod_url, params=params, timeout=5).json()
return response["hdurl"]

api를 요청하여 이미지 주소를 가져온다. git action 환경변수로 api키를 등록하기 때문에 os.environ.get('APOD_API_KEY')를 사용했다.

1
2
3
4
5
6
7
def random_date():
start_date = datetime.today().replace(day=1, month=1, year=2015).toordinal()
end_date = datetime.today().toordinal()
return datetime.fromordinal(random.randint(start_date, end_date)).strftime("%Y-%m-%d")

def download_image(url, file_path):
os.system("curl " + url + " > " + file_path)

날짜는 2015년 1월 1일 부터 현재까지의 날짜를 받기로 했다. 같은 날 같은 썸네일은 좀 그래서 랜덤으로 했다. 이미지 다운로드는 그냥 curl명령어를 호출 하는 형태로 했다.

git action에서는 다음과 같이 호출하면 된다.

1
python3 ../apod/apod.py ${dir}/${content}/${title}/feature.jpg

apod.py로 실행하고 인자값은 저장할 파일 경로로 했다. 당연히 인자 값을 넣기 때문에 python에서 해당 부분을 처리를 해주도록 했다.

1
file_path = " ".join(sys.argv[1:len(sys.argv)])

풀 소스코드는 다음과 같다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
"""Module providingFunction printing python version."""
import random
from datetime import datetime
import os
import requests
import sys

def random_date():
"""
"random" to get one date from 2015-01-01 to today
Returns:
date(str)
"""
start_date = datetime.today().replace(day=1, month=1, year=2015).toordinal()
end_date = datetime.today().toordinal()
return datetime.fromordinal(random.randint(start_date, end_date)).strftime("%Y-%m-%d")

def download_image(url, file_path):
"""
Image Download
Args:
url(str): image url
file_path(str): path to save
"""
os.system("curl " + url + " > " + file_path)

def fetch_apod(date):
"""
Call APOD API
Args:
date(str) : date
"""
apod_url = "https://api.nasa.gov/planetary/apod"
params = {
'api_key':os.environ.get('APOD_API_KEY'),
'date':date,
'hd':'True'
}
response = requests.get(apod_url, params=params, timeout=5).json()
return response["hdurl"]


def main():
"""
Main function
"""
file_path = " ".join(sys.argv[1:len(sys.argv)])
hdurl = fetch_apod(random_date())
download_image(hdurl, file_path)

if __name__ == "__main__":
main()

서브모듈 업데이트

이제 푸시되면 hugo사이트에서 자동으로 업데이트를 하게하면 글쓰는 것 외에 아무것도 신경 안써도 된다!!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Update:
needs: hugo-format-setting
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
repository: ${{ github.repository_owner }}/keea.github.io
token: ${{ secrets.PRIVATE_TOKEN_GITHUB }}
- name: Pull & update submodules recursively
run: |
git submodule update --init --recursive
git submodule update --recursive --remote
- name: Commit
run: |
git config user.email ${{ secrets.EMAIL }}
git config user.name ${{ secrets.USER_NAME }}
git add --all
git commit -m "📝 Update Post" || echo "No changes to commit"
git push

hugo 포맷 설정하는 것이 끝나면 hugo 사이트의 레파지토리를 체크아웃해서 서브모듈 업데이트하고 푸시하면 된다. 아쉽게도 템플릿도 서브모듈로 등록되었기 때문에 같이 업데이트 해줄 것이다.
PRIVATE_TOKEN_GITHUBhttps://github.com/settings/tokens 에서 토큰 만들고 Repository secrets 에 등록하면 된다.

마지막으로..

이렇게 HackMD에서 작성한 글을 자동으로 hugo 사이트의 포스트로 만들도록 했다. 생각보다 github action 다루는 것이 어려워 엄청 많은 시도를 했다. 물론 테스트 레파지토리에서… 아직 몇 가지 더 많이 남았지만 우선 이 정도로 마무리 짓고 더 업그레이드 할 것이다.

예를 들어 gist 포맷을 자동으로 바꿔준다던가… 등등

사실 글을 쓰고 날짜 맞춰서 추가해주고 폴더도 만들어서 추가해주는 것이 이걸 만드는 것보다 시간 소모가 덜 될 수도 있다고 생각이 들기는 하지만 이런 것도 신경써야하기 때문에 그냥 자동화 해버렸다.

이제 글 쓰는 것에 집중해야겠다!!!