Skip to content

Commit

Permalink
feat: allow revision pinning for rockcraft
Browse files Browse the repository at this point in the history
  • Loading branch information
cjdcordeiro committed Nov 14, 2023
1 parent 4f63da7 commit bbff782
Show file tree
Hide file tree
Showing 9 changed files with 111 additions and 31 deletions.
14 changes: 13 additions & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,12 @@ jobs:
run: npm test
- name: Try to package code
run: npm run pack

run-rockcraft-pack-action:
strategy:
matrix:
os: [ubuntu-22.04, ubuntu-20.04]
revision: ['1194', '']
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
Expand All @@ -40,6 +41,17 @@ jobs:
with:
path: tests
verbosity: debug
revision: ${{ matrix.revision }}
- name: Assert revision number
run: |
set -ex
installed_rev="$(snap info rockcraft | tail -1 | awk '{print $(NF-2)}')"
if [ -z ${{ matrix.revision }} ]
then
[ "$installed_rev" != ${{ matrix.revision }} ]
else
[ "$installed_rev" == ${{ matrix.revision }} ]
fi
- name: Upload ROCK
uses: actions/upload-artifact@v3
with:
Expand Down
21 changes: 12 additions & 9 deletions dist/rockcraft-pack-action/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4133,7 +4133,7 @@ var external_fs_ = __nccwpck_require__(147);
var external_path_ = __nccwpck_require__(17);
// EXTERNAL MODULE: external "os"
var external_os_ = __nccwpck_require__(37);
;// CONCATENATED MODULE: ./src/tools.ts
;// CONCATENATED MODULE: ./lib/tools.js
// -*- mode: javascript; js-indent-level: 2 -*-


Expand Down Expand Up @@ -4219,20 +4219,20 @@ async function ensureLXD() {
await exec.exec('sudo', ['lxd', 'init', '--auto']);
await ensureLXDNetwork();
}
async function ensureRockcraft(channel) {
async function ensureRockcraft(channel, revision) {
const haveRockcraft = await haveExecutable('/snap/bin/rockcraft');
core.info('Installing Rockcraft...');
await exec.exec('sudo', [
'snap',
haveRockcraft ? 'refresh' : 'install',
'--channel',
channel,
revision.length > 0 ? '--revision' : '--channel',
revision.length > 0 ? revision : channel,
'--classic',
'rockcraft'
]);
}

;// CONCATENATED MODULE: ./src/rockcraft-pack.ts
;// CONCATENATED MODULE: ./lib/rockcraft-pack.js
// -*- mode: javascript; js-indent-level: 2 -*-


Expand All @@ -4244,6 +4244,7 @@ class RockcraftBuilder {
constructor(options) {
this.projectRoot = expandHome(options.projectRoot);
this.rockcraftChannel = options.rockcraftChannel;
this.rockcraftRevision = options.rockcraftRevision;
if (allowedVerbosity.includes(options.rockcraftPackVerbosity)) {
this.rockcraftPackVerbosity = options.rockcraftPackVerbosity;
}
Expand All @@ -4256,7 +4257,7 @@ class RockcraftBuilder {
core.startGroup('Installing Rockcraft plus dependencies');
await ensureSnapd();
await ensureLXD();
await ensureRockcraft(this.rockcraftChannel);
await ensureRockcraft(this.rockcraftChannel, this.rockcraftRevision);
core.endGroup();
let rockcraft = 'rockcraft pack';
let rockcraftPackArgs = '';
Expand Down Expand Up @@ -4286,20 +4287,22 @@ class RockcraftBuilder {
}
}

;// CONCATENATED MODULE: ./src/rockcraft-pack-action.ts
;// CONCATENATED MODULE: ./lib/rockcraft-pack-action.js
// -*- mode: javascript; js-indent-level: 2 -*-


async function run() {
try {
const projectRoot = core.getInput('path');
core.info(`Building ROCK in "${projectRoot}"...`);
const rockcraftChannel = core.getInput('rockcraft-channel') || 'edge';
const rockcraftChannel = core.getInput('rockcraft-channel') || 'stable';
const rockcraftPackVerbosity = core.getInput('verbosity');
const rockcraftRevision = core.getInput('revision');
const builder = new RockcraftBuilder({
projectRoot,
rockcraftChannel,
rockcraftPackVerbosity
rockcraftPackVerbosity,
rockcraftRevision
});
await builder.pack();
const rock = await builder.outputRock();
Expand Down
6 changes: 3 additions & 3 deletions lib/tools.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,14 +83,14 @@ export async function ensureLXD() {
await exec.exec('sudo', ['lxd', 'init', '--auto']);
await ensureLXDNetwork();
}
export async function ensureRockcraft(channel) {
export async function ensureRockcraft(channel, revision) {
const haveRockcraft = await haveExecutable('/snap/bin/rockcraft');
core.info('Installing Rockcraft...');
await exec.exec('sudo', [
'snap',
haveRockcraft ? 'refresh' : 'install',
'--channel',
channel,
revision.length > 0 ? '--revision' : '--channel',
revision.length > 0 ? revision : channel,
'--classic',
'rockcraft'
]);
Expand Down
6 changes: 6 additions & 0 deletions rockcraft-pack/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@ inputs:
The default is 'trace'.
default: 'trace'
revision:
description: >
Pin the snap revision to install.
If not provided, it defaults to whatever revision is in latest/stable.
default: ''
outputs:
rock:
description: 'The file name of the resulting ROCK.'
Expand Down
4 changes: 3 additions & 1 deletion src/rockcraft-pack-action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@ async function run(): Promise<void> {
core.info(`Building ROCK in "${projectRoot}"...`)
const rockcraftChannel = core.getInput('rockcraft-channel') || 'stable'
const rockcraftPackVerbosity = core.getInput('verbosity')
const rockcraftRevision = core.getInput('revision')

const builder = new RockcraftBuilder({
projectRoot,
rockcraftChannel,
rockcraftPackVerbosity
rockcraftPackVerbosity,
rockcraftRevision
})
await builder.pack()
const rock = await builder.outputRock()
Expand Down
5 changes: 4 additions & 1 deletion src/rockcraft-pack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,19 @@ interface RockcraftBuilderOptions {
projectRoot: string
rockcraftChannel: string
rockcraftPackVerbosity: string
rockcraftRevision: string
}

export class RockcraftBuilder {
projectRoot: string
rockcraftChannel: string
rockcraftPackVerbosity: string
rockcraftRevision: string

constructor(options: RockcraftBuilderOptions) {
this.projectRoot = tools.expandHome(options.projectRoot)
this.rockcraftChannel = options.rockcraftChannel
this.rockcraftRevision = options.rockcraftRevision
if (allowedVerbosity.includes(options.rockcraftPackVerbosity)) {
this.rockcraftPackVerbosity = options.rockcraftPackVerbosity
} else {
Expand All @@ -36,7 +39,7 @@ export class RockcraftBuilder {
core.startGroup('Installing Rockcraft plus dependencies')
await tools.ensureSnapd()
await tools.ensureLXD()
await tools.ensureRockcraft(this.rockcraftChannel)
await tools.ensureRockcraft(this.rockcraftChannel, this.rockcraftRevision)
core.endGroup()

let rockcraft = 'rockcraft pack'
Expand Down
9 changes: 6 additions & 3 deletions src/tools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,14 +94,17 @@ export async function ensureLXD(): Promise<void> {
await ensureLXDNetwork()
}

export async function ensureRockcraft(channel: string): Promise<void> {
export async function ensureRockcraft(
channel: string,
revision: string
): Promise<void> {
const haveRockcraft = await haveExecutable('/snap/bin/rockcraft')
core.info('Installing Rockcraft...')
await exec.exec('sudo', [
'snap',
haveRockcraft ? 'refresh' : 'install',
'--channel',
channel,
revision.length > 0 ? '--revision' : '--channel',
revision.length > 0 ? revision : channel,
'--classic',
'rockcraft'
])
Expand Down
57 changes: 48 additions & 9 deletions tests/rockcraft-pack.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,16 @@ test('RockcraftBuilder expands tilde in project root', () => {
let builder = new build.RockcraftBuilder({
projectRoot: '~',
rockcraftChannel: 'edge',
rockcraftPackVerbosity: 'trace'
rockcraftPackVerbosity: 'trace',
rockcraftRevision: '1'
})
expect(builder.projectRoot).toBe(os.homedir())

builder = new build.RockcraftBuilder({
projectRoot: '~/foo/bar',
rockcraftChannel: 'stable',
rockcraftPackVerbosity: 'trace'
rockcraftPackVerbosity: 'trace',
rockcraftRevision: '1'
})
expect(builder.projectRoot).toBe(path.join(os.homedir(), 'foo/bar'))
})
Expand Down Expand Up @@ -50,7 +52,8 @@ test('RockcraftBuilder.pack runs a ROCK build', async () => {
const builder = new build.RockcraftBuilder({
projectRoot: projectDir,
rockcraftChannel: 'stable',
rockcraftPackVerbosity: 'debug'
rockcraftPackVerbosity: 'debug',
rockcraftRevision: '1'
})
await builder.pack()

Expand Down Expand Up @@ -89,11 +92,43 @@ test('RockcraftBuilder.build can set the Rockcraft channel', async () => {
const builder = new build.RockcraftBuilder({
projectRoot: '.',
rockcraftChannel: 'test-channel',
rockcraftPackVerbosity: 'trace'
rockcraftPackVerbosity: 'trace',
rockcraftRevision: ''
})
await builder.pack()

expect(ensureRockcraft).toHaveBeenCalledWith('test-channel')
expect(ensureRockcraft).toHaveBeenCalledWith('test-channel', '')
})

test('RockcraftBuilder.build can set the Rockcraft revision', async () => {
expect.assertions(1)

const ensureSnapd = jest
.spyOn(tools, 'ensureSnapd')
.mockImplementation(async (): Promise<void> => {})
const ensureLXD = jest
.spyOn(tools, 'ensureLXD')
.mockImplementation(async (): Promise<void> => {})
const ensureRockcraft = jest
.spyOn(tools, 'ensureRockcraft')
.mockImplementation(async (channel): Promise<void> => {})
const execMock = jest
.spyOn(exec, 'exec')
.mockImplementation(
async (program: string, args?: string[]): Promise<number> => {
return 0
}
)

const builder = new build.RockcraftBuilder({
projectRoot: '.',
rockcraftChannel: 'channel',
rockcraftPackVerbosity: 'trace',
rockcraftRevision: '123'
})
await builder.pack()

expect(ensureRockcraft).toHaveBeenCalledWith('channel', '123')
})

test('RockcraftBuilder.build can pass known verbosity', async () => {
Expand All @@ -119,7 +154,8 @@ test('RockcraftBuilder.build can pass known verbosity', async () => {
const builder = new build.RockcraftBuilder({
projectRoot: '.',
rockcraftChannel: 'stable',
rockcraftPackVerbosity: 'trace'
rockcraftPackVerbosity: 'trace',
rockcraftRevision: '1'
})
await builder.pack()

Expand All @@ -133,7 +169,8 @@ test('RockcraftBuilder.build can pass known verbosity', async () => {
new build.RockcraftBuilder({
projectRoot: '.',
rockcraftChannel: 'stable',
rockcraftPackVerbosity: 'fake-verbosity'
rockcraftPackVerbosity: 'fake-verbosity',
rockcraftRevision: '1'
})
}
expect(badBuilder).toThrowError()
Expand All @@ -146,7 +183,8 @@ test('RockcraftBuilder.outputRock fails if there are no ROCKs', async () => {
const builder = new build.RockcraftBuilder({
projectRoot: projectDir,
rockcraftChannel: 'stable',
rockcraftPackVerbosity: 'trace'
rockcraftPackVerbosity: 'trace',
rockcraftRevision: '1'
})

const readdir = jest
Expand All @@ -168,7 +206,8 @@ test('RockcraftBuilder.outputRock returns the first ROCK', async () => {
const builder = new build.RockcraftBuilder({
projectRoot: projectDir,
rockcraftChannel: 'stable',
rockcraftPackVerbosity: 'trace'
rockcraftPackVerbosity: 'trace',
rockcraftRevision: '1'
})

const readdir = jest
Expand Down
20 changes: 16 additions & 4 deletions tests/tools.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -254,8 +254,8 @@ test('ensureLXD still calls "lxd init" if LXD is installed', async () => {
expect(execMock).toHaveBeenNthCalledWith(4, 'sudo', ['lxd', 'init', '--auto'])
})

test('ensureSnapcraft installs Snapcraft if needed', async () => {
expect.assertions(2)
test('ensureRockcraft installs Rockcraft if needed', async () => {
expect.assertions(4)

const accessMock = jest
.spyOn(fs.promises, 'access')
Expand All @@ -275,7 +275,7 @@ test('ensureSnapcraft installs Snapcraft if needed', async () => {
}
)

await tools.ensureRockcraft('edge')
await tools.ensureRockcraft('edge', '')

expect(accessMock).toHaveBeenCalled()
expect(execMock).toHaveBeenNthCalledWith(1, 'sudo', [
Expand All @@ -286,6 +286,18 @@ test('ensureSnapcraft installs Snapcraft if needed', async () => {
'--classic',
'rockcraft'
])

await tools.ensureRockcraft('stable', '1234')

expect(accessMock).toHaveBeenCalled()
expect(execMock).toHaveBeenNthCalledWith(2, 'sudo', [
'snap',
'install',
'--revision',
'1234',
'--classic',
'rockcraft'
])
})

test('ensureRockcraft refreshes if Rockcraft is installed', async () => {
Expand All @@ -309,7 +321,7 @@ test('ensureRockcraft refreshes if Rockcraft is installed', async () => {
}
)

await tools.ensureRockcraft('edge')
await tools.ensureRockcraft('edge', '')

expect(accessMock).toHaveBeenCalled()
expect(execMock).toHaveBeenNthCalledWith(1, 'sudo', [
Expand Down

0 comments on commit bbff782

Please sign in to comment.