Skip to content

Commit

Permalink
introduce separate publish step which runs after build (#899)
Browse files Browse the repository at this point in the history
  • Loading branch information
shiftkey committed Oct 8, 2023
1 parent fec510f commit 51ab810
Show file tree
Hide file tree
Showing 4 changed files with 203 additions and 14 deletions.
73 changes: 59 additions & 14 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ on:
- 'linux-release-*'
tags:
- 'release-*.*.*-linux*'
- 'release-*.*.*-test*'
pull_request:
branches:
- linux
Expand Down Expand Up @@ -198,20 +199,6 @@ jobs:
- name: Package application
run: yarn run package
if: ${{ matrix.friendlyName == 'Ubuntu' }}
- name: Create Release
uses: softprops/action-gh-release@v1
if:
${{ matrix.friendlyName == 'Ubuntu' && startsWith(github.ref,
'refs/tags/') }}
with:
files: |
dist/*.AppImage
dist/*.deb
dist/*.rpm
dist/*.txt
draft: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Upload output artifacts
uses: actions/upload-artifact@v3
if: matrix.friendlyName == 'Ubuntu'
Expand All @@ -221,4 +208,62 @@ jobs:
dist/*.AppImage
dist/*.deb
dist/*.rpm
dist/*.sha256
retention-days: 5

publish:
name: Create GitHub release
needs: [build, lint]
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/')
permissions:
contents: write
steps:
- uses: actions/checkout@v3

- name: Download all artifacts
uses: actions/download-artifact@v2
with:
path: './artifacts'

- name: Display structure of downloaded files
run: ls -R
working-directory: './artifacts'

- name: Get tag name without prefix
run: |
RELEASE_TAG=${GITHUB_REF/refs\/tags\//}
echo "RELEASE_TAG=${RELEASE_TAG}" >> $GITHUB_ENV
tagNameWithoutPrefix="${RELEASE_TAG:1}"
echo "RELEASE_TAG_WITHOUT_PREFIX=${tagNameWithoutPrefix}" >> $GITHUB_ENV
# TODO: generate release notes
# - pull in default if version matches X.Y.Z-linux1
# - otherwise stub template

- name: Generate release notes
run: |
yarn
node -r ts-node/register script/generate-release-notes.ts "${{ github.workspace }}/artifacts" "${{ env.RELEASE_TAG_WITHOUT_PREFIX }}"
RELEASE_NOTES_FILE=script/release_notes.txt
if [[ ! -f "$RELEASE_NOTES_FILE" ]]; then
echo "$RELEASE_NOTES_FILE does not exist. Something might have gone wrong while generating the release notes."
exit 1
fi
echo "Release notes:"
echo "---"
cat ${RELEASE_NOTES_FILE}
echo "---"
- name: Create Release
uses: softprops/action-gh-release@v1
with:
name: GitHub Desktop for Linux ${{ env.RELEASE_TAG_WITHOUT_PREFIX }}
body_path: script/release_notes.txt
files: |
artifacts/*.AppImage
artifacts/*.deb
artifacts/*.rpm
draft: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,4 @@ app/node_modules/
junit*.xml
*.swp
tslint-rules/
script/release_notes.txt
140 changes: 140 additions & 0 deletions script/generate-release-notes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
/* eslint-disable no-sync */

const glob = require('glob')
const { basename } = require('path')
const fs = require('fs')

type ChecksumEntry = { filename: string; checksum: string }

type ChecksumGroups = Record<'x64' | 'arm' | 'arm64', Array<ChecksumEntry>>

// 3 architectures * 3 package formats * 2 files (package + checksum file)
const SUCCESSFUL_RELEASE_FILE_COUNT = 3 * 3 * 2

const Glob = glob.GlobSync

const args = process.argv.slice(2)
const artifactsDir = args[0]

if (!artifactsDir) {
console.error(
`🔴 First parameter with artifacts directory not found. Aborting...`
)
process.exit(1)
}

const releaseTagWithoutPrefix = args[1]
if (!releaseTagWithoutPrefix) {
console.error(`🔴 Second parameter with release tag not found. Aborting...`)
process.exit(1)
}

console.log(
`Preparing release notes for release tag ${releaseTagWithoutPrefix}`
)

const files = new Glob(artifactsDir + '/**/*', { nodir: true })

let countFiles = 0
const shaEntries = new Array<ChecksumEntry>()

for (const file of files.found) {
if (file.endsWith('.sha256')) {
shaEntries.push(getShaContents(file))
}

countFiles++
}

if (SUCCESSFUL_RELEASE_FILE_COUNT !== countFiles) {
console.error(
`🔴 Artifacts folder has ${countFiles} assets, expecting ${SUCCESSFUL_RELEASE_FILE_COUNT}. Please check the GH Actions artifacts to see which are missing.`
)
process.exit(1)
}

const shaEntriesByArchitecture: ChecksumGroups = {
x64: shaEntries.filter(
e =>
e.filename.includes('-linux-x86_64-') ||
e.filename.includes('-linux-amd64-')
),
arm: shaEntries.filter(
e =>
e.filename.includes('-linux-armv7l-') ||
e.filename.includes('-linux-armhf-')
),
arm64: shaEntries.filter(
e =>
e.filename.includes('-linux-aarch64-') ||
e.filename.includes('-linux-arm64-')
),
}

console.log(`Found ${countFiles} files in artifacts directory`)
console.log(shaEntriesByArchitecture)

const draftReleaseNotes = generateDraftReleaseNotes(
[],
shaEntriesByArchitecture
)
const releaseNotesPath = __dirname + '/release_notes.txt'

fs.writeFileSync(releaseNotesPath, draftReleaseNotes, { encoding: 'utf8' })

console.log(
`✅ All done! The release notes have been written to ${releaseNotesPath}`
)

/**
* Returns the filename (excluding .sha256) and its contents (a SHA256 checksum).
*/
function getShaContents(filePath: string): {
filename: string
checksum: string
} {
const filename = basename(filePath).slice(0, -7)
const checksum = fs.readFileSync(filePath, 'utf8')

return { filename, checksum }
}

function formatEntry(e: ChecksumEntry): string {
return `**${e.filename}**\n${e.checksum}\n`
}

/**
* Takes the release notes entries and the SHA entries, then merges them into the full draft release notes ✨
*/
function generateDraftReleaseNotes(
releaseNotesEntries: Array<string>,
shaEntries: ChecksumGroups
): string {
const changelogText = releaseNotesEntries.join('\n')

const x64Section = shaEntries.x64.map(formatEntry).join('\n')
const armSection = shaEntries.arm.map(formatEntry).join('\n')
const arm64Section = shaEntries.arm64.map(formatEntry).join('\n')

const draftReleaseNotes = `${changelogText}
## Fixes and improvements
TODO
## SHA-256 checksums
### x64
${x64Section}
### ARM64
${arm64Section}
### ARM
${armSection}`

return draftReleaseNotes
}
3 changes: 3 additions & 0 deletions script/package.ts
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,9 @@ async function generateChecksums(files: Array<string>) {
for (const [fullPath, checksum] of checksums) {
const fileName = path.basename(fullPath)
checksumsText += `${checksum} - ${fileName}\n`

const checksumFilePath = `${fullPath}.sha256`
await writeFile(checksumFilePath, checksum)
}

const checksumFile = path.join(distRoot, 'checksums.txt')
Expand Down

0 comments on commit 51ab810

Please sign in to comment.