Skip to content

Add dc_format input to the action #94

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: v2
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .github/actions/verify-d-compiler/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,15 @@ inputs:
description: "Use .sig file to verify downloaded archives"
type: boolean
default: true
dc_format:
description: "The way the $DC and $DMD variables are set: absolute path or basename"
default: absolute
required: true
type: choice
options:
- absolute
- basename
- shortname
runs:
using: "composite"
steps:
Expand All @@ -26,6 +35,7 @@ runs:
gh_token: ${{ inputs.gh_token }}
gdmd_sha: ${{ inputs.gdmd_sha }}
verify_sig: ${{ inputs.verify_sig }}
dc_format: ${{ inputs.dc_format }}

- name: Verify D compiler ($DC)
shell: bash
Expand Down
62 changes: 62 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -194,3 +194,65 @@ jobs:
- name : Compile with dub
run: |
cd .github && dub run --single hello.d --compiler=${DC}

dc-format:
needs: verify-index-js-up-to-date
name: Check dc_format input
strategy:
max-parallel: 5
fail-fast: false
matrix:
include:
- { dc: dmd, os: ubuntu-latest, dc_format: absolute }
- { dc: ldc, os: windows-latest, dc_format: absolute }
- { dc: gdc-14, os: ubuntu-latest, dc_format: shortname }
- { dc: ldc, os: windows-latest, dc_format: basename }
- { dc: ldc-1.41.0, os: macos-latest, dc_format: basename }
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/verify-d-compiler
with:
dc: ${{ matrix.dc }}
dc_format: ${{ matrix.dc_format }}

- name: Check DC and DMD variables
run: |
fail=

for var in DC DMD; do
value="${!var}"

base=$(basename "${value}")
case "${DC_FORMAT}" in
absolute)
expected=$(command -v "${base}")
if [[ ${{ matrix.os }} == windows-* ]]; then
expected=$(cygpath -aw "${expected}")
fi
;;
basename)
expected="${base}"
;;
shortname)
expected="${base%.exe}"
;;
*)
echo "Unknown DC_FORMAT: ${DC_FORMAT}"
exit 1
;;
esac

echo -n "Checking if ${var} (${value}) is ${expected}..."
if [[ ${value} == "${expected}" ]]; then
echo " good"
else
echo " fail"
fail=1
fi
done

[[ -z ${fail} ]] || exit 1
env:
DC_FORMAT: ${{ matrix.dc_format }}
shell: bash
26 changes: 26 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,8 @@ Examples:
gdmd_sha: '0a64b92ec5ad1177988496df4f3ca47c47580501'
# turn off gpg verification (only dmd archives currently undergo this verification)
verify_sig: false
# set DC to `gdc-12` and DMD to `gdmd-12` instead of `/usr/bin/gdc-12`
dc_format: basename
```

### compiler
Expand Down Expand Up @@ -169,6 +171,24 @@ The default value is `any`.
You can disable installing an additional `dub` by passing an empty string.
Note that this does not affect the `dub` executable that comes packaged with `dmd` and `ldc2`.

### dc_format

This option allows you to change the path value of the `DC` and `DMD` environment variables set by this action.
There are three possible values:
- `absolute`
- `basename`
- `shortname`

Assuming that `ldc2` has been downloaded and extracted to the following directories, the `dc_format` input would set `$DC` like so:

| | `C:\Program Files\ldc2-1.41.0-windows` | `/home/toolcache/cache/ldc2-1.41.0-linux` |
| `absolute` | `C:\Program Files\ldc2-1.41.0-windows\bin\ldc2.exe` | `/home/toolcache/cache/ldc2-1.41.0-linux/bin/ldc2-1.40` |
| `basename` | `ldc2.exe` | `ldc2-1.40` |
| `shortname` | `ldc2` | `ldc2-1.40` |

The default value for this setting is `absolute`.
Previously, before `v2`, the action would set the variable in the same way `shortname` does now.

### gh_token

A github token used to perform queries to https://api.github.com.
Expand Down Expand Up @@ -276,3 +296,9 @@ This is a special value that means:
2. if the compiler is `gdc`, install latest `dub`

This has become the default value because most D projects use `dub` to build and it is a hindrance to manually specify it just because `gdc` doesn't come with it.

Added the `dc_format` input to control how the `DC` and `DMD` variables are set.
They allow setting the variables to:
- the absolute path of the compiler executable
- the basename of the executable
- the basename without the `.exe` extension
93 changes: 73 additions & 20 deletions __tests__/d-compiler.test.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,22 @@
import { Compiler } from '../src/d'
import fs from 'fs'
import SETTINGS from '../src/settings'

describe('Test Compiler class', () => {
const logSpy = jest.spyOn(console, 'log').mockReturnValue(undefined)
jest.spyOn(process.stdout, 'write').mockReturnValue(true)

let originalEnv = process.env
afterEach(() => process.env = originalEnv)
const originalEnv = process.env
const originalSep = SETTINGS.sep
const originalExeExt = SETTINGS.exeExt
// This value is cached so it matches the host's
const pathSep = (process.platform == 'win32' ? ';' : ':')

afterEach(() => {
process.env = originalEnv
SETTINGS.sep = originalSep
SETTINGS.exeExt = originalExeExt
})

beforeEach(() => logSpy.mockClear())

Expand All @@ -17,13 +27,6 @@ describe('Test Compiler class', () => {
let c = new Compiler('url', undefined, name, 'ver', bin, libs, dmdWrapper)
const root = '/root/folder'

// The values are computed when d.ts is imported so
// they will have the values of the host system, even
// if process.platform is modified in the tests.
const sep = process.platform == 'win32' ? '\\' : '/'
const extension = process.platform == 'win32' ? '.exe' : ''
const pathSep = (process.platform == 'win32' ? ';' : ':')

test('Test setting PATH', () => {
process.env['PATH']='/bin'
c.addBinPath(root)
Expand Down Expand Up @@ -88,6 +91,8 @@ describe('Test Compiler class', () => {
test('Test makeAvailable', async () => {
jest.spyOn(c, 'getCached').mockResolvedValue(root)

SETTINGS.sep = '/'
SETTINGS.exeExt = ''
for (const platform of [ 'linux', 'darwin', 'freebsd' ]) {
Object.defineProperty(process, 'platform', { value: platform })
jest.spyOn(fs, 'existsSync').mockReturnValue(true).
Expand All @@ -99,11 +104,13 @@ describe('Test Compiler class', () => {

expect(process.env['PATH']).toBe(root + bin + pathSep + '/bin')
expect(process.env['LD_LIBRARY_PATH']).toBe(root + libs[1])
expect(process.env['DC']).toBe(`${root}${bin}${sep}${name}${extension}`)
expect(process.env['DMD']).toBe(`${root}${bin}${sep}${dmdWrapper}${extension}`)
expect(process.env['DC']).toBe(`${root}${bin}/${name}`)
expect(process.env['DMD']).toBe(`${root}${bin}/${dmdWrapper}`)
}


SETTINGS.sep = '\\'
SETTINGS.exeExt = '.exe'
Object.defineProperty(process, 'platform', { value: 'win32' })
jest.spyOn(fs, 'existsSync').mockReturnValue(true)

Expand All @@ -113,16 +120,62 @@ describe('Test Compiler class', () => {
const expPath = `${root}${libs[1]}${pathSep}` + `${root}${libs[0]}${pathSep}` +
`${root}${bin}${pathSep}` + '\\bin'
expect(process.env['PATH']).toBe(expPath)
expect(process.env['DC']).toBe(`${root}${bin}${sep}${name}${extension}`)
expect(process.env['DMD']).toBe(`${root}${bin}${sep}${dmdWrapper}${extension}`)
expect(process.env['DC']).toBe(`${root}${bin}\\${name}.exe`)
expect(process.env['DMD']).toBe(`${root}${bin}\\${dmdWrapper}.exe`)
})

test('DC and DMD get set to the absolute path of the compiler', () => {
for (const platform of [ 'linux', 'win32', 'darwin', 'freebsd' ]) {
Object.defineProperty(process, 'platform', { value: platform })
c.setDC(root)
expect(process.env['DC']).toBe(root + bin + sep + name + extension)
expect(process.env['DMD']).toBe(root + bin + sep + dmdWrapper + extension)
}
describe('Test DC and DMD path format', () => {
const origDcFormat = SETTINGS.dcFormat
beforeEach(() => SETTINGS.sep = '/')
afterEach(() => SETTINGS.dcFormat = origDcFormat)

test('default is absolute', () => {
SETTINGS.exeExt = '.exe'
c.setDC(root)
expect(process.env['DC']).toBe(root + bin + '/' + name + '.exe')
expect(process.env['DMD']).toBe(root + bin + '/' + dmdWrapper + '.exe')
})

test('explicit absolute', () => {
SETTINGS.exeExt = ''
SETTINGS.dcFormat = 'absolute'
c.setDC(root)
expect(process.env['DC']).toBe(root + bin + '/' + name)
expect(process.env['DMD']).toBe(root + bin + '/' + dmdWrapper)
})

describe('basename', () => {
beforeEach(() => SETTINGS.dcFormat = 'basename')
test('posix', () => {
SETTINGS.exeExt = ''
c.setDC(root)
expect(process.env['DC']).toBe(name)
expect(process.env['DMD']).toBe(dmdWrapper)
})

test('windows', () => {
SETTINGS.exeExt = '.exe'
c.setDC(root)
expect(process.env['DC']).toBe(name + '.exe')
expect(process.env['DMD']).toBe(dmdWrapper + '.exe')
})
})

describe('shortname', () => {
beforeEach(() => SETTINGS.dcFormat = 'shortname')
test('posix', () => {
SETTINGS.exeExt = ''
c.setDC(root)
expect(process.env['DC']).toBe(name)
expect(process.env['DMD']).toBe(dmdWrapper)
})

test('windows', () => {
SETTINGS.exeExt = '.exe'
c.setDC(root)
expect(process.env['DC']).toBe(name)
expect(process.env['DMD']).toBe(dmdWrapper)
})
})
})
})
56 changes: 41 additions & 15 deletions __tests__/d-dmd.test.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { DMD, SETTINGS } from '../src/d'
import { DMD } from '../src/d'
import * as gpg from '../src/gpg'
import * as utils from '../src/utils'
import * as testUtils from './test-helpers.test'
import * as tc from '@actions/tool-cache'
import fs from 'fs'

import SETTINGS from '../src/settings'

testUtils.hideConsoleLogs()
testUtils.saveProcessRestorePoint()
testUtils.disableNetwork()
Expand Down Expand Up @@ -442,10 +444,10 @@ test('dmd fails on unsupported platforms', async () => {
describe('Test makeAvailable', () => {
const root = '/tmp/cache'
const origEnv = process.env
const origSep = SETTINGS.sep
const origExeExt = SETTINGS.exeExt

// These values are cached so they match the hosts
const sep = (process.platform == 'win32' ? '\\' : '/')
const exeExt = (process.platform == 'win32' ? '.exe' : '')
// This value is cached so it matches the host's
const pathSep = (process.platform == 'win32' ? ';' : ':')

beforeEach(() => {
Expand All @@ -455,30 +457,40 @@ describe('Test makeAvailable', () => {
process.env['PATH'] = '/bin'
process.env['LD_LIBRARY_PATH'] = ''
})
afterEach(() => process.env = origEnv)
afterEach(() => {
process.env = origEnv
SETTINGS.sep = origSep
SETTINGS.exeExt = origExeExt
})

test('linux', async () => {
Object.defineProperty(process, 'platform', { value: 'linux' })
SETTINGS.sep = '/'
SETTINGS.exeExt = ''
const dmd = await init('dmd-2.109.1')
await dmd.makeAvailable()
expect(process.env['PATH']).toBe(root + '/dmd2/linux/bin64' + pathSep + '/bin')
expect(process.env['LD_LIBRARY_PATH']).toBe(root + '/dmd2/linux/lib64')
expect(process.env['DC']).toBe(root + `/dmd2/linux/bin64${sep}dmd${exeExt}`)
expect(process.env['DMD']).toBe(root + `/dmd2/linux/bin64${sep}dmd${exeExt}`)
expect(process.env['DC']).toBe(root + '/dmd2/linux/bin64/dmd')
expect(process.env['DMD']).toBe(root + '/dmd2/linux/bin64/dmd')
})

test('osx', async () => {
Object.defineProperty(process, 'platform', { value: 'darwin' })
SETTINGS.sep = '/'
SETTINGS.exeExt = ''
const dmd = await init('dmd-2.109.1')
await dmd.makeAvailable()
expect(process.env['PATH']).toBe(root + '/dmd2/osx/bin' + pathSep + '/bin')
expect(process.env['LD_LIBRARY_PATH']).toBe(root + '/dmd2/osx/lib')
expect(process.env['DC']).toBe(root + `/dmd2/osx/bin${sep}dmd${exeExt}`)
expect(process.env['DMD']).toBe(root + `/dmd2/osx/bin${sep}dmd${exeExt}`)
expect(process.env['DC']).toBe(root + '/dmd2/osx/bin/dmd')
expect(process.env['DMD']).toBe(root + '/dmd2/osx/bin/dmd')
})

test('windows', async () => {
Object.defineProperty(process, 'platform', { value: 'win32' })
SETTINGS.sep = '\\'
SETTINGS.exeExt = '.exe'
const dmd = await init('dmd-2.109.1')
await dmd.makeAvailable()

Expand All @@ -493,12 +505,12 @@ describe('Test makeAvailable', () => {
// Check that the 64bit folder appears before the 32bit one
expect(found64).toBeLessThan(found32)

expect(process.env['DC']).toBe(root + `\\dmd2\\windows\\bin64${sep}dmd${exeExt}`)
expect(process.env['DMD']).toBe(root + `\\dmd2\\windows\\bin64${sep}dmd${exeExt}`)
expect(process.env['DC']).toBe(root + `\\dmd2\\windows\\bin64\\dmd.exe`)
expect(process.env['DMD']).toBe(root + `\\dmd2\\windows\\bin64\\dmd.exe`)
})

describe('Check that verify_sig is respected', () => {
const save = SETTINGS.verify_sig
const save = SETTINGS.verifySig
const gpgSpy = jest.spyOn(gpg, 'verify').mockResolvedValue(undefined)

beforeEach(() => {
Expand All @@ -507,20 +519,34 @@ describe('Test makeAvailable', () => {
jest.spyOn(utils, 'extract').mockResolvedValue('/tmp/p2')
jest.spyOn(tc, 'cacheDir').mockResolvedValue('/tmp/p3')
})
afterEach(() => SETTINGS.verify_sig = save)
afterEach(() => SETTINGS.verifySig = save)

test('verify_sig === false', async () => {
SETTINGS.verify_sig = false
SETTINGS.verifySig = false
const dmd = await init('dmd-2.109.1')
await dmd.makeAvailable()
expect(gpgSpy).not.toHaveBeenCalled()
})

test('verify_sig === true', async () => {
SETTINGS.verify_sig = true
SETTINGS.verifySig = true
const dmd = await init('dmd-2.109.1')
await dmd.makeAvailable()
expect(gpgSpy).toHaveBeenCalled()
})
})

describe('test DC and DMD format', () => {
const origDcFormat = SETTINGS.dcFormat
afterEach(() => SETTINGS.dcFormat = origDcFormat)

test('basename', async () => {
SETTINGS.dcFormat = 'basename'
SETTINGS.exeExt = '.exe'
const dmd = await init('dmd-2.108')
await dmd.makeAvailable()
expect(process.env['DC']).toBe('dmd.exe')
expect(process.env['DMD']).toBe('dmd.exe')
})
})
})
Loading
Loading