Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 99a04df8b0 | |||
| ee3b6dd6ae |
90
.gitea/release-upload.ts
Normal file
90
.gitea/release-upload.ts
Normal file
@@ -0,0 +1,90 @@
|
||||
/**
|
||||
* Release asset uploader for Gitea
|
||||
* Streams large files without loading them into memory (bypasses curl's 2GB multipart limit)
|
||||
*
|
||||
* Usage: GITEA_TOKEN=xxx RELEASE_ID=123 GITEA_REPO=owner/repo tsx release-upload.ts
|
||||
*/
|
||||
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import * as https from 'https';
|
||||
|
||||
const token = process.env.GITEA_TOKEN;
|
||||
const releaseId = process.env.RELEASE_ID;
|
||||
const repo = process.env.GITEA_REPO;
|
||||
|
||||
if (!token || !releaseId || !repo) {
|
||||
console.error('Missing required env vars: GITEA_TOKEN, RELEASE_ID, GITEA_REPO');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const boundary = '----FormBoundary' + Date.now().toString(16);
|
||||
|
||||
async function uploadFile(filepath: string): Promise<void> {
|
||||
const filename = path.basename(filepath);
|
||||
const stats = fs.statSync(filepath);
|
||||
console.log(`Uploading ${filename} (${stats.size} bytes)...`);
|
||||
|
||||
const header = Buffer.from(
|
||||
`--${boundary}\r\n` +
|
||||
`Content-Disposition: form-data; name="attachment"; filename="${filename}"\r\n` +
|
||||
`Content-Type: application/octet-stream\r\n\r\n`
|
||||
);
|
||||
const footer = Buffer.from(`\r\n--${boundary}--\r\n`);
|
||||
const contentLength = header.length + stats.size + footer.length;
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const req = https.request({
|
||||
hostname: 'code.foss.global',
|
||||
path: `/api/v1/repos/${repo}/releases/${releaseId}/assets?name=${encodeURIComponent(filename)}`,
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Authorization': `token ${token}`,
|
||||
'Content-Type': `multipart/form-data; boundary=${boundary}`,
|
||||
'Content-Length': contentLength
|
||||
}
|
||||
}, (res) => {
|
||||
let data = '';
|
||||
res.on('data', chunk => data += chunk);
|
||||
res.on('end', () => {
|
||||
console.log(data);
|
||||
if (res.statusCode && res.statusCode >= 200 && res.statusCode < 300) {
|
||||
console.log(`✓ ${filename} uploaded successfully`);
|
||||
resolve();
|
||||
} else {
|
||||
reject(new Error(`Upload failed: ${res.statusCode} ${data}`));
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
req.on('error', reject);
|
||||
|
||||
// Stream: write header, pipe file, write footer
|
||||
req.write(header);
|
||||
const stream = fs.createReadStream(filepath);
|
||||
stream.on('error', reject);
|
||||
stream.on('end', () => {
|
||||
req.write(footer);
|
||||
req.end();
|
||||
});
|
||||
stream.pipe(req, { end: false });
|
||||
});
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const distDir = 'dist';
|
||||
const files = fs.readdirSync(distDir)
|
||||
.map(f => path.join(distDir, f))
|
||||
.filter(f => fs.statSync(f).isFile());
|
||||
|
||||
for (const file of files) {
|
||||
await uploadFile(file);
|
||||
}
|
||||
|
||||
console.log('All assets uploaded successfully');
|
||||
}
|
||||
|
||||
main().catch(err => {
|
||||
console.error(err);
|
||||
process.exit(1);
|
||||
});
|
||||
@@ -75,16 +75,13 @@ jobs:
|
||||
|
||||
echo "Created release with ID: $RELEASE_ID"
|
||||
|
||||
# Upload assets
|
||||
for asset in dist/*; do
|
||||
filename=$(basename "$asset")
|
||||
echo "Uploading $filename..."
|
||||
curl -X POST -s \
|
||||
-H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
|
||||
-H "Content-Type: application/octet-stream" \
|
||||
-T "$asset" \
|
||||
"https://code.foss.global/api/v1/repos/${{ gitea.repository }}/releases/$RELEASE_ID/assets?name=$filename"
|
||||
done
|
||||
# Upload assets using TypeScript (curl has 2GB multipart limit)
|
||||
pnpm install -g tsx
|
||||
|
||||
GITEA_TOKEN="${{ secrets.GITHUB_TOKEN }}" \
|
||||
GITEA_REPO="${{ gitea.repository }}" \
|
||||
RELEASE_ID="$RELEASE_ID" \
|
||||
tsx .gitea/release-upload.ts
|
||||
|
||||
- name: Cleanup old releases (keep 3 latest)
|
||||
run: |
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
# Changelog
|
||||
|
||||
## 2026-01-09 - 0.3.5 - fix(ci)
|
||||
add Gitea release asset uploader and switch release workflow to use it; bump package and daemon versions to 0.3.4
|
||||
|
||||
- Add .gitea/release-upload.ts: streams assets to Gitea to avoid curl's 2GB multipart limit
|
||||
- Update CI workflow (.gitea/workflows/release.yml) to run the TypeScript uploader via tsx
|
||||
- Bump package.json and ecoos_daemon/ts/version.ts to 0.3.4
|
||||
- Update bundled eco-daemon binary in isobuild/config/includes.chroot/opt/eco/bin/
|
||||
|
||||
## 2026-01-09 - 0.3.2 - fix(release)
|
||||
bump package and daemon to v0.3.1, add project README, and fix Gitea release upload flag
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
export const VERSION = "0.3.1";
|
||||
export const VERSION = "0.3.4";
|
||||
|
||||
Binary file not shown.
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ecobridge/eco-os",
|
||||
"version": "0.3.2",
|
||||
"version": "0.3.5",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "[ -z \"$CI\" ] && npm version patch --no-git-tag-version || true && node -e \"const v=require('./package.json').version; require('fs').writeFileSync('ecoos_daemon/ts/version.ts', 'export const VERSION = \\\"'+v+'\\\";\\n');\" && pnpm run daemon:bundle && cp ecoos_daemon/bundle/eco-daemon isobuild/config/includes.chroot/opt/eco/bin/ && mkdir -p .nogit/iso && docker build --no-cache -t ecoos-builder -f isobuild/Dockerfile . && docker run --privileged --name ecoos-build ecoos-builder && docker cp ecoos-build:/output/ecoos.iso .nogit/iso/ecoos.iso && docker rm ecoos-build",
|
||||
|
||||
Reference in New Issue
Block a user