Membuat cadangan gambar dari WordPress ke GitHub secara otomatis

31 Maret 2021 - Abdul Fattah Ikhsan

Bagikan:

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.

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:

lanjutkoding-github-repo-create
Centang initial Readme ketika membuat repository

Kedua, kita harus menyiapkan Personal access token, Token ini adalah kredensial ketika kalian menggunakan GitHub API v3 tanpa harus menggunakan password utama.

lanjutkoding-github-settings
Pilih settings di pojok kanan atas (gambar profile)
lanjutkoding-github-dev-settings
Pilih developer settings di menu sebelah kiri
lanjutkoding-github-personal-access-token
Pilih personal access token di menu sebelah kiri
lanjutkoding-github-personal-token
Pilih generate new token
lanjutkoding-github-note-token
Buat deskripsi yang sesuai untuk token tersebut
lanjutkoding-github-permission
Pilih scope dan permission yang diperlukan
lanjutkoding-github-generate-token
Pilih generate token
lanjutkoding-github-copy-token
Pilih 📋 simbol clipboard untuk copy tokennya

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.

  1. GITHUB_TOKEN adalah personal access token yang tadi kalian buat.
  2. GITHUB_USERNAME adalah nama username kalian di github
  3. GITHUB_REPO adalah nama repository kalian yang dijadikan target
  4. GITHUB_REF adalah referensi gabungan berformat heads/<nama_branch>. Diawali katakunci heads/ dan nama branch kalian. Branch utama biasanya adalah main. maka formatnya jadi heads/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:

lanjutkoding-pipedream-workflow
Ubah judul workflow
lanjutkoding-pipedream-title
Pilih HTTP API
lanjutkoding-pipedream-trigger
Pilih tombol + di bawah untuk menambahkan step trigger

gambar diatas memiliki URL https://xxxxxxx.m.pipedream.net ini adalah endpoint Rest API. Kalian akan daftarkan ini di wordpress webhook kalian.

lanjutkoding-pipedream-step-1
Pilih Run Node.js code
lanjutkoding-pipedream-step-2
Taruh kode-kode diatas ke dalam fungsi trigger pada baris ke 2 seperti di gambar

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.

lanjutkoding-pipedream-env-variable
Pilih tombol new environment variable
lanjutkoding-pipedream-env-variable2
Buat masing-masing variable. contohnya disini GITHUB_TOKEN dulu

Selesai. kalian bisa coba-coba menambahkan step trigger lain seperti send email atau end workflow. Gimana? gampangkan!. Terakhir klik save dan deploy

lanjutkoding-pipedream-step-deploy
Pilih deploy

Kalian bisa test dulu apakah kode kalian tidak bermasalah dan bisa jalan.

lanjutkoding-pipedream-step-test-event
Pilih send test event

Maka akan muncul seperti ini

lanjutkoding-pipedream-message-event
Pesan sukses

Pasang plugin wp-webhooks

Tautan resmi wp-webhooks, Setelah terpasang di WordPress kalian. Buka wp-webhooks settings.

lanjutkoding-wpwebhook-step-1
Pilih settings
lanjutkoding-wpwebhook-step-2
Aktifkan debug mode
lanjutkoding-wpwebhook-step-3
Aktifkan send data on post update

Terakhir klik Save all.

Integrasi wp-webhook dengan target server

lanjutkoding-wpwebhook-step-4
Pilih send data
lanjutkoding-wpwebhook-step-5
Isi nama webhook dan webhook URL dengan URL dari pipedream kemudian klik add
lanjutkoding-wpwebhook-step-6
Pilih settings pada kolom action sebelah kanan
lanjutkoding-wpwebhook-step-7
Aktifkan trigger from backend only dan on selected post types dan klik save settings

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.

lanjutkoding-pipedream-trigger-event
Disini saya kasih contoh pipedream sudah ter-trigger tapi dapat error credential karena belum ada token

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

Dan ini contohnya:

lanjutkoding
https://github.com/ikhsanalatsary/dddd/blob/master/mstile-150×150.png?raw=true
raycast-yuk-lanjutkoding
https://github.com/ikhsanalatsary/dddd/blob/master/public/raycast-yuk-lanjutkoding.png?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.

Ekstra: Apabila kalian merasa tulisan ini bermanfaat dan ingin mendukung penulis. Boleh dong traktirannya 😉. Cus Scan QR-nya

#Node.js
#Web
#WordPress
© 2021 - 2023 lanjutkoding.com