Compare commits

..

No commits in common. "main" and "v1.3.0" have entirely different histories.
main ... v1.3.0

5 changed files with 56 additions and 267 deletions

View File

@ -1,22 +0,0 @@
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
// README at: https://github.com/devcontainers/templates/tree/main/src/javascript-node
{
"name": "gitea-release-action",
// Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
"image": "mcr.microsoft.com/devcontainers/javascript-node:4-22-bookworm"
// Features to add to the dev container. More info: https://containers.dev/features.
// "features": {},
// Use 'forwardPorts' to make a list of ports inside the container available locally.
// "forwardPorts": [],
// Use 'postCreateCommand' to run commands after the container is created.
// "postCreateCommand": "yarn install",
// Configure tool-specific properties.
// "customizations": {},
// Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
// "remoteUser": "root"
}

View File

@ -2,8 +2,6 @@
An action to support publishing release to Gitea. An action to support publishing release to Gitea.
Preserves the fields body, prerelease and name when pushing the release if no value is given.
## Inputs ## Inputs
The following are optional as `step.with` keys The following are optional as `step.with` keys

View File

@ -10,14 +10,10 @@ inputs:
body: body:
description: "Note-worthy description of changes in release" description: "Note-worthy description of changes in release"
required: false required: false
default: ${{ github.event.release.body != '' && github.event.release.body || null }}
body_path:
description: "Path to load description of changes in this release"
required: false
name: name:
description: "Gives the release a custom name. Defaults to tag name" description: "Gives the release a custom name. Defaults to tag name"
required: false required: false
default: ${{ github.event.release.name != '' && github.event.release.name || github.ref_name }} default: ${{ github.ref_name }}
tag_name: tag_name:
description: "Gives a tag name. Defaults to github.GITHUB_REF" description: "Gives a tag name. Defaults to github.GITHUB_REF"
required: false required: false
@ -25,11 +21,9 @@ inputs:
draft: draft:
description: "Creates a draft release. Defaults to false" description: "Creates a draft release. Defaults to false"
required: false required: false
default: ${{ github.event.release.draft || false }}
prerelease: prerelease:
description: "Identify the release as a prerelease. Defaults to false" description: "Identify the release as a prerelease. Defaults to false"
required: false required: false
default: ${{ github.event.release.prerelease || false }}
files: files:
description: "Newline-delimited list of path globs for asset files to upload" description: "Newline-delimited list of path globs for asset files to upload"
required: false required: false

150
dist/index.js vendored
View File

@ -40594,8 +40594,6 @@ var __webpack_exports__ = {};
// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk. // This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk.
(() => { (() => {
;// CONCATENATED MODULE: external "node:fs/promises"
const promises_namespaceObject = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("node:fs/promises");
// EXTERNAL MODULE: external "fs" // EXTERNAL MODULE: external "fs"
var external_fs_ = __nccwpck_require__(7147); var external_fs_ = __nccwpck_require__(7147);
var external_fs_namespaceObject = /*#__PURE__*/__nccwpck_require__.t(external_fs_, 2); var external_fs_namespaceObject = /*#__PURE__*/__nccwpck_require__.t(external_fs_, 2);
@ -43828,7 +43826,7 @@ var external_path_ = __nccwpck_require__(1017);
// EXTERNAL MODULE: external "url" // EXTERNAL MODULE: external "url"
var external_url_ = __nccwpck_require__(7310); var external_url_ = __nccwpck_require__(7310);
;// CONCATENATED MODULE: external "fs/promises" ;// CONCATENATED MODULE: external "fs/promises"
const external_fs_promises_namespaceObject = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("fs/promises"); const promises_namespaceObject = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("fs/promises");
// EXTERNAL MODULE: external "events" // EXTERNAL MODULE: external "events"
var external_events_ = __nccwpck_require__(2361); var external_events_ = __nccwpck_require__(2361);
// EXTERNAL MODULE: external "stream" // EXTERNAL MODULE: external "stream"
@ -44872,10 +44870,10 @@ const defaultFS = {
readlinkSync: external_fs_.readlinkSync, readlinkSync: external_fs_.readlinkSync,
realpathSync, realpathSync,
promises: { promises: {
lstat: external_fs_promises_namespaceObject.lstat, lstat: promises_namespaceObject.lstat,
readdir: external_fs_promises_namespaceObject.readdir, readdir: promises_namespaceObject.readdir,
readlink: external_fs_promises_namespaceObject.readlink, readlink: promises_namespaceObject.readlink,
realpath: external_fs_promises_namespaceObject.realpath, realpath: promises_namespaceObject.realpath,
}, },
}; };
// if they just gave us require('fs') then use our default // if they just gave us require('fs') then use our default
@ -48147,25 +48145,20 @@ var crypto_js = __nccwpck_require__(4134);
function getIsTrue(v) {
const trueValue = ['true', 'True', 'TRUE']
return trueValue.includes(v)
}
async function run() { async function run() {
try { try {
const server_url = core.getInput("server_url") const server_url = core.getInput("server_url")
const name = core.getInput("name") const name = core.getInput("name")
const body = getReleaseBody(core.getInput("body"), core.getInput("body_path")) const body = getReleaseBody(core.getInput("body"), core.getInput("body_path"))
const tag_name = core.getInput("tag_name") const tag_name = core.getInput("tag_name")
const draft = getIsTrue(core.getInput("draft")) const draft = Boolean(core.getInput("draft"))
const prerelease = getIsTrue(core.getInput("prerelease")) const prerelease = Boolean(core.getInput("prerelease"))
const files = core.getInput("files") const files = core.getInput("files")
const repository = core.getInput("repository") const repository = core.getInput("repository")
const token = core.getInput("token") const token = core.getInput("token")
const target_commitish = core.getInput("target_commitish") const target_commitish = core.getInput("target_commitish")
const md5sum = getIsTrue(core.getInput("md5sum")) const md5sum = core.getInput("md5sum")
const sha256sum = getIsTrue(core.getInput("sha256sum")) const sha256sum = core.getInput("sha256sum")
const [owner, repo] = (repository).split("/") const [owner, repo] = (repository).split("/")
@ -48265,68 +48258,6 @@ function paths(patterns) {
}, []); }, []);
}; };
async function createStreamableFile(fpath) {
const name = external_path_.basename(fpath);
const handle = await promises_namespaceObject.open(fpath);
const { size } = await handle.stat();
const file = new external_buffer_.File([], name);
file.stream = () => handle.readableWebStream();
file.close = async () => await handle?.close();
// Set correct size otherwise, fetch will encounter UND_ERR_REQ_CONTENT_LENGTH_MISMATCH
Object.defineProperty(file, 'size', { get: () => size });
return file;
}
async function calculateMultipleHashes(file, algorithms = ['md5', 'sha256']) {
const stream = file.stream();
const reader = stream.getReader();
const hashers = algorithms.map(alg => {
switch(alg.toLowerCase()) {
case 'md5':
return { name: 'md5', instance: crypto_js.algo.MD5.create() };
case 'sha1':
return { name: 'sha1', instance: crypto_js.algo.SHA1.create() };
case 'sha256':
return { name: 'sha256', instance: crypto_js.algo.SHA256.create() };
case 'sha512':
return { name: 'sha512', instance: crypto_js.algo.SHA512.create() };
default:
throw new Error(`not support hash: ${alg}`);
}
});
try {
while (true) {
const { done, value } = await reader.read();
if (done) {
break;
}
const wordArray = crypto_js.lib.WordArray.create(value);
hashers.forEach(hasher => {
hasher.instance.update(wordArray);
});
}
const result = {};
hashers.forEach(hasher => {
result[hasher.name] = hasher.instance.finalize().toString(crypto_js.enc.Hex);
});
return result;
} finally {
reader.releaseLock();
}
}
/** /**
* *
* @param {gitea.GiteaApi} client * @param {gitea.GiteaApi} client
@ -48334,7 +48265,6 @@ async function calculateMultipleHashes(file, algorithms = ['md5', 'sha256']) {
* @param {String} repo * @param {String} repo
* @param {Number} release_id * @param {Number} release_id
* @param {Array<String>} all_files * @param {Array<String>} all_files
* @param {Map<String, Any>} additional parameters
*/ */
async function uploadFiles(client, owner, repo, release_id, all_files, params) { async function uploadFiles(client, owner, repo, release_id, all_files, params) {
params = params || {}; params = params || {};
@ -48343,55 +48273,32 @@ async function uploadFiles(client, owner, repo, release_id, all_files, params) {
repo: repo, repo: repo,
id: release_id, id: release_id,
}) })
// deleted old release attachment
const will_deleted = new Set();
for (const filepath of all_files) { for (const filepath of all_files) {
will_deleted.add(external_path_.basename(filepath)); for (const attachment of attachments) {
if (params.md5sum) { let will_deleted = [external_path_.basename(filepath), `${external_path_.basename(filepath)}.md5`, `${external_path_.basename(filepath)}.sha256`]
will_deleted.add(`${external_path_.basename(filepath)}.md5`); if (will_deleted.includes(attachment.name)) {
await client.repository.repoDeleteReleaseAttachment({
owner: owner,
repo: repo,
id: release_id,
attachmentId: attachment.id,
})
console.log(`Successfully deleted old release attachment ${attachment.name}`)
}
} }
if (params.sha256sum) { const content = external_fs_.readFileSync(filepath);
will_deleted.add(`${external_path_.basename(filepath)}.sha256`); let blob = new external_buffer_.Blob([content]);
}
}
for (const attachment of attachments) {
if (will_deleted.has(attachment.name)) {
await client.repository.repoDeleteReleaseAttachment({
owner: owner,
repo: repo,
id: release_id,
attachmentId: attachment.id,
})
console.log(`Successfully deleted old release attachment ${attachment.name}`)
}
}
// upload new release attachment
for (const filepath of all_files) {
let curfile = await createStreamableFile(filepath)
await client.repository.repoCreateReleaseAttachment({ await client.repository.repoCreateReleaseAttachment({
owner: owner, owner: owner,
repo: repo, repo: repo,
id: release_id, id: release_id,
attachment: curfile, attachment: blob,
name: external_path_.basename(filepath), name: external_path_.basename(filepath),
}) })
await curfile.close();
let algorithms = [];
if (params.md5sum) { if (params.md5sum) {
algorithms = algorithms.concat('md5'); let wordArray = crypto_js.lib.WordArray.create(content);
} let hash = crypto_js.MD5(wordArray).toString();
if (params.sha256sum) { blob = new external_buffer_.Blob([hash], { type : 'plain/text' });
algorithms = algorithms.concat('sha256');
}
let hashes = {};
if (algorithms.length !== 0) {
curfile = await createStreamableFile(filepath)
hashes = await calculateMultipleHashes(curfile, algorithms)
await curfile.close();
}
if (params.md5sum) {
let hash = hashes.md5;
let blob = new external_buffer_.Blob([hash], { type : 'plain/text' });
await client.repository.repoCreateReleaseAttachment({ await client.repository.repoCreateReleaseAttachment({
owner: owner, owner: owner,
repo: repo, repo: repo,
@ -48401,8 +48308,9 @@ async function uploadFiles(client, owner, repo, release_id, all_files, params) {
}) })
} }
if (params.sha256sum) { if (params.sha256sum) {
let hash = hashes.sha256; let wordArray = crypto_js.lib.WordArray.create(content);
let blob = new external_buffer_.Blob([hash], { type : 'plain/text' }); let hash = crypto_js.SHA256(wordArray).toString();
blob = new external_buffer_.Blob([hash], { type : 'plain/text' });
await client.repository.repoCreateReleaseAttachment({ await client.repository.repoCreateReleaseAttachment({
owner: owner, owner: owner,
repo: repo, repo: repo,

139
main.js
View File

@ -1,6 +1,5 @@
import asyncfs from "node:fs/promises";
import fs from "fs"; import fs from "fs";
import { Blob, File } from "buffer"; import { Blob } from "buffer";
import * as glob from "glob"; import * as glob from "glob";
import core from "@actions/core"; import core from "@actions/core";
@ -9,10 +8,6 @@ import gitea from "gitea-api";
import path from 'path'; import path from 'path';
import CryptoJS from 'crypto-js'; import CryptoJS from 'crypto-js';
function getIsTrue(v) {
const trueValue = ['true', 'True', 'TRUE']
return trueValue.includes(v)
}
async function run() { async function run() {
try { try {
@ -20,14 +15,14 @@ async function run() {
const name = core.getInput("name") const name = core.getInput("name")
const body = getReleaseBody(core.getInput("body"), core.getInput("body_path")) const body = getReleaseBody(core.getInput("body"), core.getInput("body_path"))
const tag_name = core.getInput("tag_name") const tag_name = core.getInput("tag_name")
const draft = getIsTrue(core.getInput("draft")) const draft = Boolean(core.getInput("draft"))
const prerelease = getIsTrue(core.getInput("prerelease")) const prerelease = Boolean(core.getInput("prerelease"))
const files = core.getInput("files") const files = core.getInput("files")
const repository = core.getInput("repository") const repository = core.getInput("repository")
const token = core.getInput("token") const token = core.getInput("token")
const target_commitish = core.getInput("target_commitish") const target_commitish = core.getInput("target_commitish")
const md5sum = getIsTrue(core.getInput("md5sum")) const md5sum = core.getInput("md5sum")
const sha256sum = getIsTrue(core.getInput("sha256sum")) const sha256sum = core.getInput("sha256sum")
const [owner, repo] = (repository).split("/") const [owner, repo] = (repository).split("/")
@ -127,68 +122,6 @@ function paths(patterns) {
}, []); }, []);
}; };
async function createStreamableFile(fpath) {
const name = path.basename(fpath);
const handle = await asyncfs.open(fpath);
const { size } = await handle.stat();
const file = new File([], name);
file.stream = () => handle.readableWebStream();
file.close = async () => await handle?.close();
// Set correct size otherwise, fetch will encounter UND_ERR_REQ_CONTENT_LENGTH_MISMATCH
Object.defineProperty(file, 'size', { get: () => size });
return file;
}
async function calculateMultipleHashes(file, algorithms = ['md5', 'sha256']) {
const stream = file.stream();
const reader = stream.getReader();
const hashers = algorithms.map(alg => {
switch(alg.toLowerCase()) {
case 'md5':
return { name: 'md5', instance: CryptoJS.algo.MD5.create() };
case 'sha1':
return { name: 'sha1', instance: CryptoJS.algo.SHA1.create() };
case 'sha256':
return { name: 'sha256', instance: CryptoJS.algo.SHA256.create() };
case 'sha512':
return { name: 'sha512', instance: CryptoJS.algo.SHA512.create() };
default:
throw new Error(`not support hash: ${alg}`);
}
});
try {
while (true) {
const { done, value } = await reader.read();
if (done) {
break;
}
const wordArray = CryptoJS.lib.WordArray.create(value);
hashers.forEach(hasher => {
hasher.instance.update(wordArray);
});
}
const result = {};
hashers.forEach(hasher => {
result[hasher.name] = hasher.instance.finalize().toString(CryptoJS.enc.Hex);
});
return result;
} finally {
reader.releaseLock();
}
}
/** /**
* *
* @param {gitea.GiteaApi} client * @param {gitea.GiteaApi} client
@ -205,55 +138,32 @@ async function uploadFiles(client, owner, repo, release_id, all_files, params) {
repo: repo, repo: repo,
id: release_id, id: release_id,
}) })
// deleted old release attachment
const will_deleted = new Set();
for (const filepath of all_files) { for (const filepath of all_files) {
will_deleted.add(path.basename(filepath)); for (const attachment of attachments) {
if (params.md5sum) { let will_deleted = [path.basename(filepath), `${path.basename(filepath)}.md5`, `${path.basename(filepath)}.sha256`]
will_deleted.add(`${path.basename(filepath)}.md5`); if (will_deleted.includes(attachment.name)) {
await client.repository.repoDeleteReleaseAttachment({
owner: owner,
repo: repo,
id: release_id,
attachmentId: attachment.id,
})
console.log(`Successfully deleted old release attachment ${attachment.name}`)
}
} }
if (params.sha256sum) { const content = fs.readFileSync(filepath);
will_deleted.add(`${path.basename(filepath)}.sha256`); let blob = new Blob([content]);
}
}
for (const attachment of attachments) {
if (will_deleted.has(attachment.name)) {
await client.repository.repoDeleteReleaseAttachment({
owner: owner,
repo: repo,
id: release_id,
attachmentId: attachment.id,
})
console.log(`Successfully deleted old release attachment ${attachment.name}`)
}
}
// upload new release attachment
for (const filepath of all_files) {
let curfile = await createStreamableFile(filepath)
await client.repository.repoCreateReleaseAttachment({ await client.repository.repoCreateReleaseAttachment({
owner: owner, owner: owner,
repo: repo, repo: repo,
id: release_id, id: release_id,
attachment: curfile, attachment: blob,
name: path.basename(filepath), name: path.basename(filepath),
}) })
await curfile.close();
let algorithms = [];
if (params.md5sum) { if (params.md5sum) {
algorithms = algorithms.concat('md5'); let wordArray = CryptoJS.lib.WordArray.create(content);
} let hash = CryptoJS.MD5(wordArray).toString();
if (params.sha256sum) { blob = new Blob([hash], { type : 'plain/text' });
algorithms = algorithms.concat('sha256');
}
let hashes = {};
if (algorithms.length !== 0) {
curfile = await createStreamableFile(filepath)
hashes = await calculateMultipleHashes(curfile, algorithms)
await curfile.close();
}
if (params.md5sum) {
let hash = hashes.md5;
let blob = new Blob([hash], { type : 'plain/text' });
await client.repository.repoCreateReleaseAttachment({ await client.repository.repoCreateReleaseAttachment({
owner: owner, owner: owner,
repo: repo, repo: repo,
@ -263,8 +173,9 @@ async function uploadFiles(client, owner, repo, release_id, all_files, params) {
}) })
} }
if (params.sha256sum) { if (params.sha256sum) {
let hash = hashes.sha256; let wordArray = CryptoJS.lib.WordArray.create(content);
let blob = new Blob([hash], { type : 'plain/text' }); let hash = CryptoJS.SHA256(wordArray).toString();
blob = new Blob([hash], { type : 'plain/text' });
await client.repository.repoCreateReleaseAttachment({ await client.repository.repoCreateReleaseAttachment({
owner: owner, owner: owner,
repo: repo, repo: repo,