Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: use devcard V2 and download the png image over stream #404

Merged
merged 18 commits into from
Feb 14, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .nvmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
v16
v20
2 changes: 1 addition & 1 deletion action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ inputs:

commit_filename:
description: Filename to save devcard to
default: devcard.svg
default: devcard.png
required: false

committer_email:
Expand Down
10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "action-devcard",
"version": "2.3.1",
"version": "2.4.0",
kopancek marked this conversation as resolved.
Show resolved Hide resolved
"description": "GitHub Action to download the devcard from daily.dev",
"private": true,
"author": {
Expand All @@ -12,6 +12,10 @@
"name": "Ole-Martin Bratteng",
"email": "ole-martin@bratteng.com"
}
{
"name": "Milan Freml",
"email": "kopancek@gmail.com"
}
],
"scripts": {
"lint": "eslint 'src/**/*.ts' --cache",
Expand All @@ -24,16 +28,12 @@
"dependencies": {
"@actions/core": "^1.10.1",
"@actions/github": "^6.0.0",
"jsdom": "^22.1.0",
"node-fetch": "^3.3.2",
"sharp": "^0.32.6",
"simple-git": "^3.20.0",
"uuid": "^9.0.1"
},
"devDependencies": {
"@types/jsdom": "21.x",
"@types/node": "20.x",
"@types/sharp": "0.32.x",
"@types/uuid": "9.x",
"@typescript-eslint/eslint-plugin": "^6.9.1",
"@typescript-eslint/parser": "^6.20.0",
Expand Down
52 changes: 6 additions & 46 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,42 +2,20 @@ import * as core from '@actions/core'
import * as github from '@actions/github'
import type { GraphQlQueryResponseData } from '@octokit/graphql'

import { Readable } from 'stream';
import { finished } from 'stream/promises';

import sgit from 'simple-git'
import fetch from 'node-fetch'
import fs from 'fs/promises'
import path from 'path'
import jsdom from 'jsdom'
import sharp from 'sharp'
import { validate } from 'uuid'

process.on('unhandledRejection', (error) => {
throw error
})

const convertImageToBase64 = async (url: string): Promise<string> => {
const resp = await fetch(url)
const contentType = resp.headers.get('content-type')

return `data:${contentType};base64,${(await resp.buffer()).toString('base64')}`
}

const fetchImagesFromSVG = async (svg: string): Promise<Record<string, string>> => {
const dom = new jsdom.JSDOM(svg)

dom.serialize()

const images: Record<string, string> = {}

dom.window.document.querySelectorAll('image').forEach((image) => {
const src = image.getAttribute('xlink:href')
src && (images[src] = src)
})

return images
}

const devcardURL = (devcard_id: string): string =>
`https://api.daily.dev/devcards/${devcard_id}.svg?r=${new Date().valueOf()}&ref=action`
`https://api.daily.dev/devcards/v2/${devcard_id}.png?r=${new Date().valueOf()}&ref=action`

const validateDevcardIdAsUUID = (devcard_id: string): boolean => {
// An UUIDv4 regex without hyphens
Expand Down Expand Up @@ -72,29 +50,11 @@ const validateDevcardIdAsUUID = (devcard_id: string): boolean => {
// Fetch the latest devcard
try {
const res = await fetch(devcardURL(devcard_id))
devCardContent = await res.text()
const images = await fetchImagesFromSVG(devCardContent)

for (const image in images) {
if (Object.prototype.hasOwnProperty.call(images, image)) {
devCardContent = devCardContent.replace(image, await convertImageToBase64(images[image]))
}
}

await fs.mkdir(path.dirname(path.join(`/tmp`, filename)), { recursive: true })
const stream = fs.createWriteStream(path.join(`/tmp`, filename))
await finished(Readable.fromWeb(res.body).pipe(stream))
await fs.writeFile(path.join(`/tmp`, filename), devCardContent)

if (filename.endsWith('.png')) {
await sharp(path.join(`/tmp`, filename))
.png({
quality: 100,
})
.toFile(path.join(`/tmp`, `_${filename}`))

await fs.rename(path.join(`/tmp`, `_${filename}`), path.join(`/tmp`, filename))
console.log('Converted devcard to PNG', 'ok')
}

console.log(`Saved to ${path.join(`/tmp`, filename)}`, 'ok')
} catch (error) {
console.debug(error)
Expand Down
Loading