mirror of
https://gitea.com/actions/gitea-release-action.git
synced 2026-03-24 21:58:23 +00:00
Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b8d9144f30 | ||
|
|
e476391eee | ||
|
|
fd3cba014c | ||
|
|
9ee2a5d4a3 | ||
|
|
4875285c09 | ||
|
|
aae35ac409 | ||
|
|
c95a2785f0 | ||
|
|
424dc33baa | ||
|
|
9ca8dcac95 | ||
|
|
05b1004877 | ||
|
|
008a54b0cd | ||
|
|
fe8e032280 | ||
|
|
3dbdc45d61 | ||
|
|
f66c1c98f1 | ||
|
|
65a502e85c | ||
|
|
f119011bd6 | ||
|
|
1d562cf526 | ||
|
|
f00f823d73 | ||
|
|
6a4c0c7c03 | ||
|
|
89861ccfb7 | ||
|
|
1ab8e7176e |
22
.devcontainer/devcontainer.json
Normal file
22
.devcontainer/devcontainer.json
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
// 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"
|
||||||
|
}
|
||||||
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
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
|
||||||
@@ -12,13 +14,15 @@ The following are optional as `step.with` keys
|
|||||||
| `body` | String | Text communicating notable changes in this release |
|
| `body` | String | Text communicating notable changes in this release |
|
||||||
| `body_path` | String | Path to load text communicating notable changes in this release |
|
| `body_path` | String | Path to load text communicating notable changes in this release |
|
||||||
| `draft` | Boolean | Creates a draft release. Defaults to false |
|
| `draft` | Boolean | Creates a draft release. Defaults to false |
|
||||||
| `prerelease` | Boolean | Indicator of whether or not is a prerelease |
|
| `prerelease` | Boolean | Indicator of whether or not is a prerelease. Defaults to false |
|
||||||
| `files` | String | Newline-delimited globs of paths to assets to upload for release |
|
| `files` | String | Newline-delimited globs of paths to assets to upload for release |
|
||||||
| `name` | String | Name of the release. Defaults to tag name |
|
| `name` | String | Name of the release. Defaults to tag name |
|
||||||
| `tag_name` | String | Name of a tag. Defaults to `github.ref_name` |
|
| `tag_name` | String | Name of a tag. Defaults to `github.ref_name` |
|
||||||
| `repository` | String | Name of a target repository in `<owner>/<repo>` format. Defaults to `github.repository` |
|
| `repository` | String | Name of a target repository in `<owner>/<repo>` format. Defaults to `github.repository` |
|
||||||
| `token` | String | Gitea Token. Defaults to `${{ github.token }}` |
|
| `token` | String | Gitea Token. Defaults to `${{ github.token }}` |
|
||||||
| `target_commitish` | String | Commitish value that determines where the Git tag is created from. Can be any branch or commit SHA. |
|
| `target_commitish` | String | Commitish value that determines where the Git tag is created from. Can be any branch or commit SHA. |
|
||||||
|
| `md5sum` | Boolean | Publish .md5 along with artifacts, Defaults to false |
|
||||||
|
| `sha256sum` | Boolean | Publish .md5 along with artifacts, Defaults to false |
|
||||||
|
|
||||||
## Example usage
|
## Example usage
|
||||||
|
|
||||||
@@ -38,3 +42,4 @@ If you want to ignore ssl verify error, you can set env `NODE_TLS_REJECT_UNAUTHO
|
|||||||
- [softprops/action-gh-release: 📦 GitHub Action for creating GitHub Releases](https://github.com/softprops/action-gh-release)
|
- [softprops/action-gh-release: 📦 GitHub Action for creating GitHub Releases](https://github.com/softprops/action-gh-release)
|
||||||
- [sigyl-actions/gitea-action-release-asset](https://github.com/sigyl-actions/gitea-action-release-asset)
|
- [sigyl-actions/gitea-action-release-asset](https://github.com/sigyl-actions/gitea-action-release-asset)
|
||||||
- [actions/release-action: An action written by Golang to support publishing release to Gitea(not Github Actions compatible) - release-action - Gitea: Git with a cup of tea](https://gitea.com/actions/release-action)
|
- [actions/release-action: An action written by Golang to support publishing release to Gitea(not Github Actions compatible) - release-action - Gitea: Git with a cup of tea](https://gitea.com/actions/release-action)
|
||||||
|
- [wangyoucao577/go-release-action: Automatically publish Go binaries to Github Release Assets through Github Action.](https://github.com/wangyoucao577/go-release-action)
|
||||||
|
|||||||
16
action.yml
16
action.yml
@@ -10,10 +10,14 @@ 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.ref_name }}
|
default: ${{ github.event.release.name != '' && github.event.release.name || 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
|
||||||
@@ -21,9 +25,11 @@ 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
|
||||||
@@ -38,9 +44,15 @@ inputs:
|
|||||||
target_commitish:
|
target_commitish:
|
||||||
description: 'Commitish value that determines where the Git tag is created from. Can be any branch or commit SHA.'
|
description: 'Commitish value that determines where the Git tag is created from. Can be any branch or commit SHA.'
|
||||||
required: false
|
required: false
|
||||||
|
md5sum:
|
||||||
|
description: 'Publish `.md5` along with artifacts.'
|
||||||
|
required: false
|
||||||
|
sha256sum:
|
||||||
|
description: 'Publish `.sha256` along with artifacts.'
|
||||||
|
required: false
|
||||||
runs:
|
runs:
|
||||||
using: "node16"
|
using: "node16"
|
||||||
main: "dist/index.js"
|
main: "dist/index.js"
|
||||||
branding:
|
branding:
|
||||||
color: "green"
|
color: "green"
|
||||||
icon: "package"
|
icon: "package"
|
||||||
|
|||||||
7418
dist/index.js
vendored
7418
dist/index.js
vendored
File diff suppressed because it is too large
Load Diff
159
main.js
159
main.js
@@ -1,11 +1,18 @@
|
|||||||
|
import asyncfs from "node:fs/promises";
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
import { Blob } from "buffer";
|
import { Blob, File } from "buffer";
|
||||||
import * as glob from "glob";
|
import * as glob from "glob";
|
||||||
|
|
||||||
import core from "@actions/core";
|
import core from "@actions/core";
|
||||||
|
|
||||||
import gitea from "gitea-api";
|
import gitea from "gitea-api";
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
|
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 {
|
||||||
@@ -13,12 +20,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 = Boolean(core.getInput("draft"))
|
const draft = getIsTrue(core.getInput("draft"))
|
||||||
const prerelease = Boolean(core.getInput("prerelease"))
|
const prerelease = getIsTrue(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 sha256sum = getIsTrue(core.getInput("sha256sum"))
|
||||||
|
|
||||||
const [owner, repo] = (repository).split("/")
|
const [owner, repo] = (repository).split("/")
|
||||||
|
|
||||||
@@ -41,7 +50,10 @@ async function run() {
|
|||||||
if (all_files.length == 0) {
|
if (all_files.length == 0) {
|
||||||
console.warn(`${file_patterns} not include valid file.`);
|
console.warn(`${file_patterns} not include valid file.`);
|
||||||
}
|
}
|
||||||
await uploadFiles(gitea_client, owner, repo, response.id, all_files)
|
await uploadFiles(gitea_client, owner, repo, response.id, all_files, {
|
||||||
|
md5sum: md5sum,
|
||||||
|
sha256sum: sha256sum,
|
||||||
|
})
|
||||||
console.log(`🎉 Release ready at ${response.html_url}`);
|
console.log(`🎉 Release ready at ${response.html_url}`);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
@@ -115,6 +127,68 @@ 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
|
||||||
@@ -122,34 +196,83 @@ function paths(patterns) {
|
|||||||
* @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) {
|
async function uploadFiles(client, owner, repo, release_id, all_files, params) {
|
||||||
|
params = params || {};
|
||||||
const attachments = await client.repository.repoListReleaseAttachments({
|
const attachments = await client.repository.repoListReleaseAttachments({
|
||||||
owner: owner,
|
owner: owner,
|
||||||
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) {
|
||||||
for (const attachment of attachments) {
|
will_deleted.add(path.basename(filepath));
|
||||||
if (attachment.name === path.basename(filepath)) {
|
if (params.md5sum) {
|
||||||
await client.repository.repoDeleteReleaseAttachment({
|
will_deleted.add(`${path.basename(filepath)}.md5`);
|
||||||
owner: owner,
|
|
||||||
repo: repo,
|
|
||||||
id: release_id,
|
|
||||||
attachmentId: attachment.id,
|
|
||||||
})
|
|
||||||
console.log(`Successfully deleted old release attachment ${attachment.name}`)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
const content = fs.readFileSync(filepath);
|
if (params.sha256sum) {
|
||||||
const blob = new Blob([content]);
|
will_deleted.add(`${path.basename(filepath)}.sha256`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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: blob,
|
attachment: curfile,
|
||||||
name: path.basename(filepath),
|
name: path.basename(filepath),
|
||||||
})
|
})
|
||||||
|
await curfile.close();
|
||||||
|
let algorithms = [];
|
||||||
|
if (params.md5sum) {
|
||||||
|
algorithms = algorithms.concat('md5');
|
||||||
|
}
|
||||||
|
if (params.sha256sum) {
|
||||||
|
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({
|
||||||
|
owner: owner,
|
||||||
|
repo: repo,
|
||||||
|
id: release_id,
|
||||||
|
attachment: blob,
|
||||||
|
name: `${path.basename(filepath)}.md5`,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if (params.sha256sum) {
|
||||||
|
let hash = hashes.sha256;
|
||||||
|
let blob = new Blob([hash], { type : 'plain/text' });
|
||||||
|
await client.repository.repoCreateReleaseAttachment({
|
||||||
|
owner: owner,
|
||||||
|
repo: repo,
|
||||||
|
id: release_id,
|
||||||
|
attachment: blob,
|
||||||
|
name: `${path.basename(filepath)}.sha256`,
|
||||||
|
})
|
||||||
|
}
|
||||||
console.log(`Successfully uploaded release attachment ${filepath}`)
|
console.log(`Successfully uploaded release attachment ${filepath}`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
6
package-lock.json
generated
6
package-lock.json
generated
@@ -11,6 +11,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/core": "^1.10.1",
|
"@actions/core": "^1.10.1",
|
||||||
"@actions/github": "^6.0.0",
|
"@actions/github": "^6.0.0",
|
||||||
|
"crypto-js": "^4.2.0",
|
||||||
"gitea-api": "^1.17.3-1",
|
"gitea-api": "^1.17.3-1",
|
||||||
"glob": "^10.3.10"
|
"glob": "^10.3.10"
|
||||||
},
|
},
|
||||||
@@ -276,6 +277,11 @@
|
|||||||
"node": ">= 8"
|
"node": ">= 8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/crypto-js": {
|
||||||
|
"version": "4.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz",
|
||||||
|
"integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q=="
|
||||||
|
},
|
||||||
"node_modules/deprecation": {
|
"node_modules/deprecation": {
|
||||||
"version": "2.3.1",
|
"version": "2.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz",
|
||||||
|
|||||||
@@ -8,7 +8,8 @@
|
|||||||
"test": "echo \"Error: no test specified\" && exit 1",
|
"test": "echo \"Error: no test specified\" && exit 1",
|
||||||
"package": "ncc build main.js -o dist",
|
"package": "ncc build main.js -o dist",
|
||||||
"build": "ncc build main.js",
|
"build": "ncc build main.js",
|
||||||
"start": "node main.js"
|
"start": "node main.js",
|
||||||
|
"test111": "node 111.js"
|
||||||
},
|
},
|
||||||
"keywords": [],
|
"keywords": [],
|
||||||
"author": "",
|
"author": "",
|
||||||
@@ -16,6 +17,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/core": "^1.10.1",
|
"@actions/core": "^1.10.1",
|
||||||
"@actions/github": "^6.0.0",
|
"@actions/github": "^6.0.0",
|
||||||
|
"crypto-js": "^4.2.0",
|
||||||
"gitea-api": "^1.17.3-1",
|
"gitea-api": "^1.17.3-1",
|
||||||
"glob": "^10.3.10"
|
"glob": "^10.3.10"
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user