Skip to content

Commit

Permalink
move debian packaging out to dedicated step (#263)
Browse files Browse the repository at this point in the history
  • Loading branch information
shiftkey committed Aug 11, 2024
1 parent d835cf5 commit fcc449d
Show file tree
Hide file tree
Showing 8 changed files with 358 additions and 81 deletions.
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -166,5 +166,8 @@
"markdownlint-cli": "^0.32.2",
"reserved-words": "^0.1.2",
"tsconfig-paths": "^3.9.0"
},
"optionalDependencies": {
"electron-installer-debian": "3.2.0"
}
}
17 changes: 0 additions & 17 deletions script/electron-builder-linux.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,26 +11,9 @@ linux:
# see https://github.com/shiftkey/desktop/issues/72 for more details
- x-scheme-handler/x-github-desktop-dev-auth
target:
- deb
- rpm
- AppImage
maintainer: 'GitHub, Inc <[email protected]>'
deb:
afterInstall: './script/linux-after-install.sh'
afterRemove: './script/linux-after-remove.sh'
depends:
# default Electron dependencies
- gconf2
- gconf-service
- libnotify4
- libappindicator1
- libxtst6
- libnss3
# dugite-native dependencies
- libcurl3 | libcurl4
# keytar dependencies
- libsecret-1-0
- gnome-keyring
rpm:
depends:
# dugite-native dependencies
Expand Down
101 changes: 101 additions & 0 deletions script/package-debian.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import { promisify } from 'util'
import { join } from 'path'

import glob = require('glob')
const globPromise = promisify(glob)

import { rename } from 'fs-extra'

import { getVersion } from '../app/package-info'
import { getDistPath, getDistRoot } from './dist-info'

const distRoot = getDistRoot()

// best guess based on documentation
type DebianOptions = {
// required
src: string
dest: string
arch: 'amd64' | 'i386' | 'arm64'
// optional
description?: string
productDescription?: string
categories?: Array<string>
section?: string
priority?: 'required' | 'important' | 'standard' | 'optional' | 'extra'
homepage?: string
icon?: any
scripts?: {
preinst?: string
postinst?: string
prerm?: string
postrm?: string
}
mimeType?: Array<string>
maintainer?: string
depends?: Array<string>
}

const options: DebianOptions = {
src: getDistPath(),
dest: distRoot,
arch: 'amd64',
description: 'Simple collaboration from your desktop',
productDescription:
'This is the unofficial port of GitHub Desktop for Linux distributions',
section: 'GNOME;GTK;Development',
priority: 'extra',
homepage: 'https://github.com/shiftkey/desktop',
depends: [
// Desktop-specific dependencies
'libcurl3 | libcurl4',
'libsecret-1-0',
'gnome-keyring',
],
icon: {
'256x256': 'app/static/logos/256x256.png',
'512x512': 'app/static/logos/512x512.png',
'1024x1024': 'app/static/logos/1024x1024.png',
},
scripts: {
postinst: 'script/resources/deb/postinst.sh',
postrm: 'script/resources/deb/postrm.sh',
},
mimeType: [
'x-scheme-handler/x-github-client',
'x-scheme-handler/x-github-desktop-auth',
// workaround for handling OAuth flow until we figure out what we're doing
// with the development OAuth details
//
// see https://github.com/shiftkey/desktop/issues/72 for more details
'x-scheme-handler/x-github-desktop-dev-auth',
],
maintainer: 'Brendan Forster <[email protected]>',
}

export async function packageDebian(): Promise<string> {
if (process.platform === 'win32') {
return Promise.reject('Windows is not supported')
}

const installer = require('electron-installer-debian')

await installer(options)
const installersPath = `${distRoot}/github-desktop*.deb`

const files = await globPromise(installersPath)

if (files.length !== 1) {
return Promise.reject(
`Expected one file but instead found '${files.join(', ')}' - exiting...`
)
}

const oldPath = files[0]

const newFileName = `GitHubDesktop-linux-${getVersion()}.deb`
const newPath = join(distRoot, newFileName)
await rename(oldPath, newPath)

return Promise.resolve(newPath)
}
68 changes: 68 additions & 0 deletions script/package-electron-builder.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/* eslint-disable no-sync */

import * as path from 'path'
import * as cp from 'child_process'
import { promisify } from 'util'

import glob = require('glob')
const globPromise = promisify(glob)

import { getDistPath, getDistRoot } from './dist-info'

export async function packageElectronBuilder(): Promise<Array<string>> {
const distPath = getDistPath()
const distRoot = getDistRoot()

const electronBuilder = path.resolve(
__dirname,
'..',
'node_modules',
'.bin',
'electron-builder'
)

const configPath = path.resolve(__dirname, 'electron-builder-linux.yml')

const args = [
'build',
'--prepackaged',
distPath,
'--x64',
'--config',
configPath,
]

const { error } = cp.spawnSync(electronBuilder, args, { stdio: 'inherit' })

if (error != null) {
return Promise.reject(error)
}

const appImageInstaller = `${distRoot}/GitHubDesktop-linux-*.AppImage`

let files = await globPromise(appImageInstaller)
if (files.length !== 1) {
return Promise.reject(
`Expected one AppImage installer but instead found '${files.join(
', '
)}' - exiting...`
)
}

const appImageInstallerPath = files[0]

const rpmInstaller = `${distRoot}/GitHubDesktop-linux-*.rpm`

files = await globPromise(rpmInstaller)
if (files.length !== 1) {
return Promise.reject(
`Expected one RPM installer but instead found '${files.join(
', '
)}' - exiting...`
)
}

const rpmInstallerPath = files[0]

return Promise.resolve([appImageInstallerPath, rpmInstallerPath])
}
78 changes: 28 additions & 50 deletions script/package.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
/* eslint-disable no-sync */

import * as cp from 'child_process'
import { chmodSync, createReadStream } from 'fs'
import { createReadStream } from 'fs'
import { writeFile } from 'fs/promises'
import { pathExists, chmod } from 'fs-extra'
import * as path from 'path'
import * as electronInstaller from 'electron-winstaller'
import * as crypto from 'crypto'

import glob = require('glob')

import { getProductName, getCompanyName } from '../app/package-info'
import {
getDistPath,
Expand All @@ -30,7 +29,9 @@ import { getVersion } from '../app/package-info'
import { rename } from 'fs/promises'
import { join } from 'path'
import { assertNonNullable } from '../app/src/lib/fatal-error'
import { pathExistsSync } from 'fs-extra'

import { packageElectronBuilder } from './package-electron-builder'
import { packageDebian } from './package-debian'

const distPath = getDistPath()
const productName = getProductName()
Expand Down Expand Up @@ -186,69 +187,46 @@ function getSha256Checksum(fullPath: string): Promise<string> {
})
}

function generateChecksums() {
async function generateChecksums(files: Array<string>) {
const distRoot = getDistRoot()

const installersPath = `${distRoot}/GitHubDesktop-linux-*`

glob(installersPath, async (error, files) => {
if (error != null) {
throw error
}

const checksums = new Map<string, string>()
const checksums = new Map<string, string>()

for (const f of files) {
const checksum = await getSha256Checksum(f)
checksums.set(f, checksum)
}
for (const f of files) {
const checksum = await getSha256Checksum(f)
checksums.set(f, checksum)
}

let checksumsText = `Checksums: \n`
let checksumsText = `Checksums: \n`

for (const [fullPath, checksum] of checksums) {
const fileName = path.basename(fullPath)
checksumsText += `${checksum} - ${fileName}\n`
}
for (const [fullPath, checksum] of checksums) {
const fileName = path.basename(fullPath)
checksumsText += `${checksum} - ${fileName}\n`
}

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

await writeFile(checksumFile, checksumsText)
})
await writeFile(checksumFile, checksumsText)
}

function packageLinux() {
async function packageLinux() {
const helperPath = path.join(getDistPath(), 'chrome-sandbox')
const exists = pathExistsSync(helperPath)
const exists = await pathExists(helperPath)

if (exists) {
console.log('Updating file mode for chrome-sandbox…')
chmodSync(helperPath, 0o4755)
await chmod(helperPath, 0o4755)
}

const electronBuilder = path.resolve(
__dirname,
'..',
'node_modules',
'.bin',
'electron-builder'
)

const configPath = path.resolve(__dirname, 'electron-builder-linux.yml')

const args = [
'build',
'--prepackaged',
distPath,
'--x64',
'--config',
configPath,
]
const files = await packageElectronBuilder()
const debianPackage = await packageDebian()

const { error } = cp.spawnSync(electronBuilder, args, { stdio: 'inherit' })
const installers = [...files, debianPackage]

if (error != null) {
throw error
console.log(`Installers created:`)
for (const installer of installers) {
console.log(` - ${installer}`)
}

generateChecksums()
generateChecksums(installers)
}
4 changes: 2 additions & 2 deletions script/linux-after-install.sh → script/resources/deb/postinst.sh
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
set -e

PROFILE_D_FILE="/etc/profile.d/github-desktop.sh"
INSTALL_DIR="/opt/${productFilename}"
INSTALL_DIR="/usr/lib/github-desktop"
CLI_DIR="$INSTALL_DIR/resources/app/static"

case "$1" in
Expand All @@ -30,4 +30,4 @@ case "$1" in
;;
esac

exit 0
exit 0
File renamed without changes.
Loading

0 comments on commit fcc449d

Please sign in to comment.