Membuat cadangan gambar dari WordPress ke GitHub secara otomatis

01 April 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.

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:

inisialisasi github repository
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.

github settings
Pilih settings di pojok kanan atas (gambar profile)
github developer settings
Pilih developer settings di menu sebelah kiri
generate new token
Pilih generate new token
deskripsi token
Buat deskripsi yang sesuai untuk token tersebut
perijinan token
Pilih scope dan permission yang diperlukan
generate token
Pilih generate token
generated 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:

pipedream worlflow
Buat workflow baru
judul pipedream workflow
Ubah judul workflow
pipedream trigger workflow
Pilih HTTP API
tambah step trigger pipedream workflow
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.

pipedream trigger node.js
Pilih Run Node.js code
pipedream step node.js
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.

pengaturan pipedream environment variable
Pilih tombol new environment variable
environment variable form pipedream
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.

deploy pipedream step node.js function
Pilih deploy

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

tombol send event pipedream
Pilih send test event

Maka akan muncul seperti ini

pesan sukses pipedream
Pesan sukses

Pasang plugin wp-webhooks

wp-webhooks plugin page
Sumber: https://wordpress.org/plugins/wp-webhooks/

Setelah terpasang di WordPress kalian. Buka wp-webhooks settings.

wp-webhook settings
Pilih settings
pengaturan mode debug wp-webhook
Aktifkan mode debug
wp-webhook send data on post update
Aktifkan send data on post update

Terakhir klik Save all.

Integrasi wp-webhook dengan target server

wp-webhook menu send data
Pilih send data
tambah webhook url
Isi nama webhook dan webhook URL dengan URL dari pipedream kemudian klik add
pengaturan webhook pada post update
Pilih settings pada kolom action sebelah kanan
opsi send data on post update
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.

pipedream receive event from wp-webhook
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

Catatan: diimplementasi kita pada bagian ini, kita simpan gambar di dalam folder public. Jika kalian ingin mengubahnya, ubah pada bagian itu ya!. Dan ini contoh menampilkan gambar dari GitHub:

lanjut koding
https://github.com/ikhsanalatsary/dddd/blob/master/mstile-150×150.png?raw=true
lanjut koding utama
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.

#Api Integration
#Node.js
#Web Development
#Webhooks
#WordPress
© 2021 Lanjutkoding.com