-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
windows publish sample: publish draft release via nodejs
- Loading branch information
Showing
11 changed files
with
639 additions
and
57 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import {checkGithubVersionAndExport, exportMatchingVersionData, readPackageVersion} from "./jsLib/versionHelper.js"; | ||
import {produceFakeFilename} from "./jsLib/packagingHelper.js"; | ||
import {postToGitHubDispatch, waitForCompletion} from "./jsLib/githubApiHelper.js"; | ||
|
||
/** | ||
* requirements: | ||
* (file) | ||
* ./versions.yml | ||
* (env) | ||
* GITHUB_REF_NAME : provided by GHA | ||
*/ | ||
|
||
const version = readPackageVersion(); | ||
const envVersion = checkGithubVersionAndExport(version); | ||
exportMatchingVersionData(envVersion); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import {checkGithubVersionAndExport, exportMatchingVersionData, readPackageVersion} from "./jsLib/versionHelper.js"; | ||
import {produceFakeFilename} from "./jsLib/packagingHelper.js"; | ||
import {postToGitHubDispatch, waitForCompletion} from "./jsLib/githubApiHelper.js"; | ||
|
||
/** | ||
* requirements: | ||
* (env) | ||
* env.VERSION | ||
* env.LABEL | ||
* env.LABEL_FR | ||
* env.DESCRIPTION | ||
* env.DESCRIPTION_FR | ||
* RELEASE_EXE_FILE | ||
* REPO_API_URL, | ||
* REPO_WEB_URL | ||
* PAT_TOKEN | ||
*/ | ||
|
||
await postToGitHubDispatch(process.env.VERSION) | ||
await waitForCompletion() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
import fetch from 'node-fetch'; | ||
import fs from 'fs'; | ||
|
||
async function createRelease() { | ||
const { | ||
GITHUB_ENV, | ||
GITHUB_REF_NAME, | ||
GITHUB_TOKEN, | ||
REPO_API_URL, | ||
LABEL, | ||
LABEL_FR, | ||
DESCRIPTION, | ||
DESCRIPTION_FR, | ||
} = process.env; | ||
|
||
if (!GITHUB_TOKEN || !REPO_API_URL || !GITHUB_REF_NAME || !LABEL || !DESCRIPTION || !GITHUB_ENV) { | ||
throw new Error('Missing required environment variables.'); | ||
} | ||
|
||
const requestBody = { | ||
tag_name: GITHUB_REF_NAME, | ||
target_commitish: 'main', | ||
name: LABEL, | ||
body: `${DESCRIPTION}\n\n# ${LABEL_FR}\n\n${DESCRIPTION_FR}`, | ||
draft: true, | ||
prerelease: false, | ||
}; | ||
|
||
try { | ||
// Create release | ||
const response = await fetch(`${REPO_API_URL}/releases`, { | ||
method: 'POST', | ||
headers: { | ||
Authorization: `token ${GITHUB_TOKEN}`, | ||
'Content-Type': 'application/json', | ||
'User-Agent': 'Node.js/Fetch', | ||
}, | ||
body: JSON.stringify(requestBody), | ||
}); | ||
|
||
if (!response.ok) { | ||
const errorText = await response.text(); | ||
throw new Error(`Failed to create release: ${errorText}`); | ||
} | ||
|
||
const responseData = await response.json(); | ||
|
||
// Write API response to file | ||
const responseFile = 'release_response.json'; | ||
fs.writeFileSync(responseFile, JSON.stringify(responseData, null, 2)); | ||
console.log(`Release creation response saved to: ${responseFile}`); | ||
|
||
const releaseId = responseData.id; | ||
const uploadUrl = responseData.upload_url; | ||
|
||
if (!releaseId) { | ||
throw new Error(`Release ID is null. Full response: ${JSON.stringify(responseData)}`); | ||
} | ||
|
||
console.log(`Release created successfully! id: ${releaseId} - upload_url: ${uploadUrl}`); | ||
|
||
// Export variables to GitHub Actions environment | ||
fs.appendFileSync(GITHUB_ENV, `RELEASE_ID=${releaseId}\n`); | ||
fs.appendFileSync(GITHUB_ENV, `RELEASE_UPLOAD_URL=${uploadUrl}\n`); | ||
|
||
} catch (error) { | ||
console.error('Error creating release:', error.message); | ||
process.exit(1); | ||
} | ||
} | ||
|
||
createRelease(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,186 @@ | ||
import https from 'https'; | ||
|
||
export const postToGitHubDispatch = async () => { | ||
const { | ||
PAT_TOKEN, | ||
REPO_API_URL, | ||
VERSION, | ||
LABEL, | ||
LABEL_FR, | ||
DESCRIPTION, | ||
DESCRIPTION_FR, | ||
REPO_WEB_URL | ||
} = process.env; | ||
|
||
if (!PAT_TOKEN || !REPO_API_URL || !VERSION) { | ||
console.error('🔴 Error: Missing required environment variables.'); | ||
process.exit(1); | ||
} | ||
|
||
const data = JSON.stringify({ | ||
event_type: 'push-new-version', | ||
client_payload: { | ||
version: VERSION, | ||
label: LABEL, | ||
label_fr: LABEL_FR, | ||
description: DESCRIPTION, | ||
description_fr: DESCRIPTION_FR, | ||
note: `${REPO_WEB_URL}/releases/tag/v${VERSION}`, | ||
download: `${REPO_WEB_URL}/releases/download/v${VERSION}/chicken-bot.exe`, | ||
}, | ||
}); | ||
|
||
const options = { | ||
hostname: new URL(REPO_API_URL).hostname, | ||
path: new URL(REPO_API_URL).pathname + '/dispatches', | ||
method: 'POST', | ||
headers: { | ||
'Authorization': `token ${PAT_TOKEN}`, | ||
'User-Agent': 'GitHub-Actions-NodeJS-Script', | ||
'Accept': 'application/vnd.github.everest-preview+json', | ||
'Content-Type': 'application/json', | ||
'Content-Length': Buffer.byteLength(data), | ||
}, | ||
}; | ||
|
||
const sendRequest = () => | ||
new Promise((resolve, reject) => { | ||
const req = https.request(options, (res) => { | ||
let responseBody = ''; | ||
res.on('data', (chunk) => { | ||
responseBody += chunk; | ||
}); | ||
res.on('end', () => { | ||
if (res.statusCode >= 200 && res.statusCode < 300) { | ||
resolve(responseBody); | ||
} else { | ||
reject( | ||
new Error( | ||
`Request failed with status ${res.statusCode}: ${responseBody}` | ||
) | ||
); | ||
} | ||
}); | ||
}); | ||
|
||
req.on('error', (err) => reject(err)); | ||
req.write(data); | ||
req.end(); | ||
}); | ||
|
||
try { | ||
const response = await sendRequest(); | ||
console.log('✅ Successfully dispatched event to GitHub:'); | ||
console.log(response); | ||
} catch (error) { | ||
console.error(`🔴 Error: ${error.message}`); | ||
process.exit(1); | ||
} | ||
}; | ||
|
||
export const timeout = ms => { | ||
return new Promise(resolve => setTimeout(resolve, ms)); | ||
} | ||
|
||
const fetch = (url, token) => | ||
new Promise((resolve, reject) => { | ||
const options = { | ||
method: 'GET', | ||
headers: { | ||
Authorization: `token ${token}`, | ||
'User-Agent': 'GitHub-Actions-NodeJS-Script' | ||
}, | ||
}; | ||
|
||
const req = https.request(url, options, (res) => { | ||
let data = ''; | ||
|
||
res.on('data', (chunk) => { | ||
data += chunk; | ||
}); | ||
|
||
res.on('end', () => { | ||
if (res.statusCode >= 200 && res.statusCode < 300) { | ||
resolve(JSON.parse(data)); | ||
} else { | ||
reject(new Error(`HTTP ${res.statusCode}: ${data}`)); | ||
} | ||
}); | ||
}); | ||
|
||
req.on('error', (err) => reject(err)); | ||
req.end(); | ||
}); | ||
|
||
export const waitForCompletion = async () => { | ||
const { | ||
PAT_TOKEN, | ||
REPO_API_URL, | ||
} = process.env; | ||
|
||
if (!PAT_TOKEN || !REPO_API_URL) { | ||
console.error('🔴 Error: Missing required environment variables.'); | ||
process.exit(1); | ||
} | ||
|
||
const workflowName = 'push-new-version'; | ||
let runId = null; | ||
|
||
console.log(`ℹ️ Waiting for workflow "${workflowName}" to start...`); | ||
|
||
// Poll for the workflow run ID | ||
while (!runId) { | ||
try { | ||
const response = await fetch( | ||
`${REPO_API_URL}/actions/runs?event=repository_dispatch&status=in_progress`, | ||
PAT_TOKEN | ||
); | ||
|
||
const workflowRuns = response.workflow_runs || []; | ||
const matchingRun = workflowRuns.find( | ||
(run) => run.display_title === workflowName | ||
); | ||
|
||
if (matchingRun) { | ||
runId = matchingRun.id; | ||
} else { | ||
console.log('Waiting for workflow run ID...'); | ||
await timeout(3000); | ||
} | ||
} catch (error) { | ||
console.error(`🔴 Error fetching workflow runs: ${error.message}`); | ||
process.exit(1); | ||
} | ||
} | ||
|
||
console.log(`ℹ️ Workflow ID: ${runId}`); | ||
|
||
// Poll for the workflow completion status | ||
let conclusion = null; | ||
while (!conclusion || conclusion === 'in_progress') { | ||
try { | ||
const response = await fetch( | ||
`${REPO_API_URL}/actions/runs/${runId}`, | ||
PAT_TOKEN | ||
); | ||
|
||
conclusion = response.conclusion; | ||
if (conclusion === 'success') { | ||
console.log('✅ Workflow completed successfully.'); | ||
break; | ||
} else if (conclusion === 'failure') { | ||
console.error('🔴 The workflow FAILED.'); | ||
process.exit(1); | ||
} else if (conclusion === 'cancelled') { | ||
console.error('🚫 The workflow was CANCELLED.'); | ||
process.exit(1); | ||
} else { | ||
console.log('Waiting for the workflow to complete...'); | ||
await timeout(10000); | ||
} | ||
} catch (error) { | ||
console.error(`🔴 Error fetching workflow status: ${error.message}`); | ||
process.exit(1); | ||
} | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import fs from 'fs'; | ||
import path from 'path'; | ||
|
||
export const produceFakeFilename = async (sizeMb = 82) => { | ||
try { | ||
const fileName = process.env.FILE_NAME; | ||
|
||
if (!fileName) { | ||
console.error('🔴 Error: FILE_NAME environment variable is not set.'); | ||
process.exit(1); | ||
} | ||
|
||
// Create the ./packages directory if it doesn't exist | ||
const packagesDir = path.resolve('./packages'); | ||
if (!fs.existsSync(packagesDir)) { | ||
fs.mkdirSync(packagesDir, {recursive: true}); | ||
} | ||
|
||
// Generate a random file of sizeMb MB | ||
const filePath = path.join(packagesDir, fileName); | ||
const randomData = Buffer.alloc(sizeMb * 1024 * 1024); // 82 MB buffer | ||
fs.writeFileSync(filePath, randomData); | ||
|
||
console.log(`Preparing release file ${filePath} done:`); | ||
|
||
// List files in ./packages | ||
const files = fs.readdirSync(packagesDir).map(file => { | ||
const stats = fs.statSync(path.join(packagesDir, file)); | ||
return `${file} - ${stats.size} bytes`; | ||
}); | ||
|
||
console.log('Files in ./packages:'); | ||
console.log(files.join('\n')); | ||
} catch (error) { | ||
console.error(`🔴 Error: ${error.message}`); | ||
process.exit(1); | ||
} | ||
}; |
Oops, something went wrong.