Membuat cadangan gambar dari WordPress ke GitHub secara otomatis
Menggunakan Webhook dan GitHub API v3
Sebelum memulai bahasan saya asumsikan kalian punya pengetahuan dasar mengenai:
- WordPress
- Node.js
- Git
- Konsep Restful API
- Konsep webhook
Jika kalian masih belum mengerti tapi penasaran, Silakan lanjut.
Daftar Isi:
- Motivasi
- Menyiapkan Git repository dan Personal access token
- Menyiapkan API webhook di Node.js
- Deploy dan jalankan API webhook di Pipedream
- Pasang plugin wp-webhook
- Integrasi wp-webhook dengan target server
- Uji coba
- Penutup
Motivasi
Sebenarnya motivasi awal itu menjadikan GitHub sebagai image CDN (Content Delivery Network). Ini berguna ketika implementasi headless CMS di Wordpress. Nah, untuk mengurangi kompleksitas bahasan maka saya membuat judul ini. Karena memang intinya itu menyimpan gambar di GitHub melalui Rest API.
Dokumentasi GitHub sendiri tidak ada bahasan mengenai ini, bisa jadi, mereka tidak ingin kalian menggunakannya. Namun, pepatah mengatakan, selalu ada jalan menuju Roma. Beberapa implementasi, contohnya github-image-upload, pustaka ini memberikan solusi scrapping GitHub issues dan unggah gambar disana. Namun Saya tidak suka solusinya, saya ingin gambar tetap bisa di-track setiap perubahannya, tidak cuma penambahan saja. Secara teknis bisa, karena Git adalah version control, dan beberapa kali saya mengerjakan project itu bisa sekaligus unggah gambar melalui Git CLI.
Di implementasi yang lain, seperti potongan kode di github gist ini, bagaimana membuat commit dan push kontennya ke GitHub melalui API. Saya pun mencoba dan bisa, pertanyaannya bagaimana Saya unggah gambar. Saya tidak mau terlalu banyak ubah kodenya, yang mana itu bahasa Ruby. Akhirnya setelah saya cari di Google, Github punya pustaka dan dokumentasi resmi. Cuma kalau kalian baca dokumentasinya, pasti bingung bagaimana memulainya. terlalu abstrak penjelasannya. Tada 🎉, kalian telah menemukan tutorial ini, langsung saja tanpa harus menguras waktu trial and error.
Menyiapkan Git repository dan Personal access token
Pertama kalian buat repository di GitHub dan pastikan sudah ada Readme. Atau bisa menggunakan repository yang sudah ada. Contoh, kita membuat repository:
Kedua, kita harus menyiapkan Personal access token, Token ini adalah kredensial ketika kalian menggunakan GitHub API v3 tanpa harus menggunakan password utama.
Ingat! token ini cuma sekali muncul saat pertama kali dibuat maka kalian harus simpan dulu di tempat yang aman ya!
Menyiapkan API webhook di Node.js
Kita menggunakan pustaka @octokit/request untuk berinteraksi dengan GitHub API v3. Pustaka lain yang akan kita gunakan adalah node-fetch. Yuk kita buat fungsi-fungsinya dulu.
- Konversi URL sumber gambar ke base64
let fetch = require('node-fetch');
async function getImageAsBase64(imageUrl) {
let result = await fetch(imageUrl);
let data = await result.buffer();
return data.toString('base64');
}
- Inisialisasi @octokit/request dengan default settings
let { request } = require("@octokit/request");
let requestWithAuth = request.defaults({
headers: {
authorization: 'token ' + process.env.GITHUB_TOKEN,
},
});
- Mengambil commit-an terakhir dari target repo dan branch utama (main)
async function getLastCommitSha() {
let result = await requestWithAuth('GET /repos/{owner}/{repo}/git/matching-refs/{ref}', {
owner: process.env.GITHUB_USERNAME,
repo: process.env.GITHUB_REPO,
ref: process.env.GITHUB_REF,
});
return result.data.length ? result.data[0].object.sha : '';
}
- Mengunggah gambar base64 ke Git blob (objek binari)
async function createBlob(base64Image) {
const result = await requestWithAuth('POST /repos/{owner}/{repo}/git/blobs', {
owner: process.env.GITHUB_USERNAME,
repo: process.env.GITHUB_REPO,
content: base64Image,
encoding: 'base64',
});
return result.data;
}
- Membuat commit baru
async function createCommit(fileName, data, lastCommitSha) {
let tree = await requestWithAuth('POST /repos/{owner}/{repo}/git/trees', {
owner: process.env.GITHUB_USERNAME,
repo: process.env.GITHUB_REPO,
tree: [
{
path: 'public/' + fileName,
mode: '100644', // mode untuk file blob
type: 'blob',
sha: data.sha,
},
],
base_tree: lastCommitSha,
});
let result = await requestWithAuth('POST /repos/{owner}/{repo}/git/commits', {
owner: process.env.GITHUB_USERNAME,
repo: process.env.GITHUB_REPO,
message: 'add new image ' + fileName,
tree: tree.data.sha,
parents: [lastCommitSha],
});
return result.data;
}
- Push commit baru tadi ke repository GitHub kalian
async function pushCommit(data) {
let result = await requestWithAuth('PATCH /repos/{owner}/{repo}/git/refs/{ref}', {
owner: process.env.GITHUB_USERNAME,
repo: process.env.GITHUB_REPO,
ref: process.env.GITHUB_REF,
sha: data.sha,
});
return result.data;
}
- Cek validitas URL gambar
let { URL } = require('url');
function isValidURL(targetUrl) {
try {
let url = new URL(targetUrl);
return url.protocol === 'http:' || url.protocol === 'https:';
}
catch (error) {
return false;
}
}
Catatan: Disini kalian menggunakan environment variables. Saya akan jelaskan setiap variablenya.
- GITHUB_TOKEN adalah personal access token yang tadi kalian buat.
- GITHUB_USERNAME adalah nama username kalian di github
- GITHUB_REPO adalah nama repository kalian yang dijadikan target
- GITHUB_REF adalah referensi gabungan berformat
heads/<nama_branch>
. Diawali katakunciheads/
dan nama branch kalian. Branch utama biasanya adalahmain
. maka formatnya jadiheads/main
.
Deploy dan jalankan API server di Pipedream
Nah, kode-kode diatas mau kalian taruh mana? lokal komputer kalian? tidak-tidak, kita sudah di era cloud computing dan serverless. Kalian langsung implementasikan di pipedream. Saya ga perlu jelaskan panjang lebar. kalian bisa langsung cek aja webnya dan daftar. Langkah-langkahnya sebagai berikut:
gambar diatas memiliki URL https://xxxxxxx.m.pipedream.net ini adalah endpoint Rest API. Kalian akan daftarkan ini di wordpress webhook kalian.
Kemudian di baris terakhir (sebelum kurawal tutup ya) kalian tambahkan kode seperti ini:
let message = '';
try {
if (event.body.post?.post_status === 'publish') {
let postThumbnail = event.body.post_thumbnail; // string or false
if (isValidURL(postThumbnail)) {
let fileName = new URL(postThumbnail).pathname.slice(28);
let base64Image = await getImageAsBase64(postThumbnail);
let blobData = await createBlob(base64Image);
let lastCommit = await getLastCommitSha();
let commit = await createCommit(fileName, blobData, lastCommit);
let result = await pushCommit(commit);
message = JSON.stringify(result);
}
}
message = 'success';
} catch (error) {
console.error(error);
message = error.message;
}
return message;
Jika kalian perhatikan kode diatas, fungsi commit dan push ke GitHub akan jalan ketika event body mempunyai pos dengan status publish dan post_thumbnail
valid.
Selanjutnya, Kalian siapkan environment variables di Pipedream.
Selesai. kalian bisa coba-coba menambahkan step trigger lain seperti send email atau end workflow. Gimana? gampangkan!. Terakhir klik save dan deploy
Kalian bisa test dulu apakah kode kalian tidak bermasalah dan bisa jalan.
Maka akan muncul seperti ini
Pasang plugin wp-webhooks
Setelah terpasang di WordPress kalian. Buka wp-webhooks settings.
Terakhir klik Save all.
Integrasi wp-webhook dengan target server
Kalian pilih Pos saja agar webhook tidak terkirim dua kali.
Uji Coba
Kalian bisa mencoba langsung dengan cara membuat pos baru di WordPress dan menambahkan gambar unggulan. Kemudian langsung klik terbitkan. wp webhook akan berjalan otomatis dan trigger pipedream URL.
Bagaimana menampilkan gambar dari GitHub? mudah, formatnya
https://github.com/<github_username>/blob/<github_branch>/<nama_folder>/<nama_file>?raw=true
atau jika bukan di dalam folder maka formatnya
https://github.com/<github_username>/blob/<github_branch>/<nama_file>?raw=true
Penutup
Saya berikan tautan Pipedream workflow-nya, Sebagai referensi saat kalian mempraktekkan.
Jika kalian perhatikan, hanya gambar unggulan yang bisa dicadangkan. Adapun gambar di dalam pos tidak, inilah keterbatasan dari implementasi kita. Keterbatasan lain, kode ini hanya bisa 1 gambar dalam 1 kali commit dan push. Namun secara keseluruhan, konsep sudah cukup jelas Saya kira.
Saya cukupkan tulisan kali ini. Terima kasih sudah membaca tulisan ini sampai selesai, Tulisan ini saya dedikasikan untuk Indonesia lebih baik. Semoga bermanfaat dan yuk lanjut kodingnya!
Apabila ada pertanyaan atau ingin kolaborasi bisa kontak langsung di telegram.