Skip to content
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

Add store-credentials and environment support #18

Merged
merged 2 commits into from
Mar 2, 2023
Merged
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
41 changes: 39 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ jobs:
strategy:
matrix:
base:
- core
- core18
- core20
- core22
Expand All @@ -33,20 +32,58 @@ jobs:
- ''
- 'true'
- 'false'
runner:
- ubuntu-latest
include:
- base: core
arch: ''
usePodman: 'false'
runner: ubuntu-20.04
- base: core
arch: ''
usePodman: 'true'
runner: ubuntu-20.04
- base: core
arch: i386
usePodman: 'false'
runner: ubuntu-20.04
- base: core
arch: i386
usePodman: 'true'
runner: ubuntu-20.04
- base: core
arch: amd64
usePodman: 'false'
runner: ubuntu-20.04
- base: core
arch: amd64
usePodman: 'true'
runner: ubuntu-20.04
- base: core
arch: armhf
usePodman: 'false'
runner: ubuntu-20.04
- base: core
arch: armhf
usePodman: 'true'
runner: ubuntu-20.04
- base: core
arch: arm64
usePodman: 'false'
runner: ubuntu-20.04
- base: core
arch: arm64
usePodman: 'true'
runner: ubuntu-20.04
- base: core18
arch: i386
usePodman: 'false'
runner: ubuntu-latest
- base: core18
arch: i386
usePodman: 'true'
runs-on: ubuntu-latest
runner: ubuntu-latest
runs-on: ${{ matrix.runner }}
steps:
- uses: docker/setup-qemu-action@v2
- uses: actions/checkout@v3
Expand Down
26 changes: 25 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ notes
-----

* `s390x` is broken at the moment.
* `core20` & `core22` builds do not support `i386` architecture because Ubuntu has dropped support for `i386` in Ubuntu 20.04 and later.
* Builds for `core20`, and later, do not support `i386` architecture because Ubuntu has dropped support for `i386` in Ubuntu 20.04 and later.
* `core` builds do not support `s390x` architecture because Ubuntu does not have support for `s390x` before Ubuntu 18.04.

## Action inputs
Expand Down Expand Up @@ -143,3 +143,27 @@ to indicate an alternative architecture from any of those supported by
the `snapcraft` utility. At the time of writing the supported
architectures are `amd64`, `i386`, `arm64`, `armhf`, `ppc64el` and `s390x`.
This is most-useful when used with GitHub Actions' `matrix` feature.

### `environment`

Add environment variables to the Snapcraft build context. Each
variable needs to be specified on a separate line. For example:

```yaml
with:
environment: |
FOO=bar
BAZ=qux
```
### `store-auth`

Set the `SNAPCRAFT_STORE_CREDENTIALS` environment variable. This
is useful when using the `snapcraft push` command.

You should not save the token into the yaml file directly, but use
the GitHub Actions secrets feature:

```yaml
with:
store-auth: ${{ secrets.STORE_AUTH }}
```
173 changes: 154 additions & 19 deletions __tests__/build.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import * as exec from '@actions/exec'
import * as build from '../src/build'
import * as tools from '../src/tools'

const default_base = 'core20'
const default_base = 'core22'

afterEach(() => {
jest.restoreAllMocks()
Expand All @@ -21,8 +21,9 @@ test('SnapcraftBuilder expands tilde in project root', () => {
'stable',
'',
'',
'',
false
[],
false,
''
)
expect(builder.projectRoot).toBe(os.homedir())

Expand All @@ -32,8 +33,9 @@ test('SnapcraftBuilder expands tilde in project root', () => {
'stable',
'',
'',
'',
false
[],
false,
''
)
expect(builder.projectRoot).toBe(path.join(os.homedir(), 'foo/bar'))
})
Expand Down Expand Up @@ -65,7 +67,7 @@ for (const base of ['core', 'core18', 'core20', 'core22']) {
}
for (const [base, arch, channel] of matrix) {
test(`SnapcraftBuilder.build runs a snap build using Docker with base: ${base}; and arch: ${arch}`, async () => {
expect.assertions(3)
expect.assertions(4)

const ensureDockerExperimentalMock = jest
.spyOn(tools, 'ensureDockerExperimental')
Expand All @@ -75,6 +77,9 @@ for (const [base, arch, channel] of matrix) {
.mockImplementation(
async (projectRoot: string): Promise<string> => Promise.resolve(base)
)
const detectCGroupsV1Mock = jest
.spyOn(tools, 'detectCGroupsV1')
.mockImplementation(async (): Promise<boolean> => Promise.resolve(true))
const execMock = jest
.spyOn(exec, 'exec')
.mockImplementation(
Expand All @@ -90,8 +95,9 @@ for (const [base, arch, channel] of matrix) {
'stable',
'',
arch,
'',
false
[],
false,
''
)
await builder.build()

Expand All @@ -102,6 +108,11 @@ for (const [base, arch, channel] of matrix) {

expect(ensureDockerExperimentalMock).toHaveBeenCalled()
expect(detectBaseMock).toHaveBeenCalled()
if (base === 'core') {
expect(detectCGroupsV1Mock).toHaveBeenCalled()
} else {
expect(detectCGroupsV1Mock).not.toHaveBeenCalled()
}
expect(execMock).toHaveBeenCalledWith(
'docker',
[
Expand Down Expand Up @@ -130,8 +141,7 @@ for (const [base, arch, channel] of matrix) {
})

test(`SnapcraftBuilder.build runs a snap build using Podman with base: ${base}; and arch: ${arch}`, async () => {
expect.assertions(3)

expect.assertions(4)
const ensureDockerExperimentalMock = jest
.spyOn(tools, 'ensureDockerExperimental')
.mockImplementation(async (): Promise<void> => Promise.resolve())
Expand All @@ -140,6 +150,9 @@ for (const [base, arch, channel] of matrix) {
.mockImplementation(
async (projectRoot: string): Promise<string> => Promise.resolve(base)
)
const detectCGroupsV1Mock = jest
.spyOn(tools, 'detectCGroupsV1')
.mockImplementation(async (): Promise<boolean> => Promise.resolve(true))
const execMock = jest
.spyOn(exec, 'exec')
.mockImplementation(
Expand All @@ -155,13 +168,19 @@ for (const [base, arch, channel] of matrix) {
'stable',
'',
arch,
'',
true
[],
true,
''
)
await builder.build()

expect(ensureDockerExperimentalMock).not.toHaveBeenCalled()
expect(detectBaseMock).toHaveBeenCalled()
if (base === 'core') {
expect(detectCGroupsV1Mock).toHaveBeenCalled()
} else {
expect(detectCGroupsV1Mock).not.toHaveBeenCalled()
}
expect(execMock).toHaveBeenCalledWith(
'sudo podman',
[
Expand Down Expand Up @@ -214,8 +233,9 @@ test('SnapcraftBuilder.build can disable build info', async () => {
'stable',
'',
'',
'',
false
[],
false,
''
)
await builder.build()

Expand Down Expand Up @@ -266,8 +286,62 @@ test('SnapcraftBuilder.build can pass additional arguments', async () => {
'stable',
'--foo --bar',
'',
[],
false,
''
)
await builder.build()

expect(execMock).toHaveBeenCalledWith(
'docker',
[
'run',
'--rm',
'--tty',
'--privileged',
'--volume',
`${process.cwd()}:/data`,
'--workdir',
'/data',
'--env',
`SNAPCRAFT_IMAGE_INFO={"build_url":"https://github.com/user/repo/actions/runs/42"}`,
'--env',
'USE_SNAPCRAFT_CHANNEL=stable',
`diddledani/snapcraft:${default_base}`,
'snapcraft',
'--foo',
'--bar'
],
expect.anything()
)
})

test('SnapcraftBuilder.build can pass extra environment variables', async () => {
expect.assertions(1)

const ensureDockerExperimentalMock = jest
.spyOn(tools, 'ensureDockerExperimental')
.mockImplementation(async (): Promise<void> => Promise.resolve())
const detectBaseMock = jest
.spyOn(tools, 'detectBase')
.mockImplementation(
async (projectRoot: string): Promise<string> => default_base
)
const execMock = jest
.spyOn(exec, 'exec')
.mockImplementation(
async (program: string, args?: string[]): Promise<number> => 0
)

const builder = new build.SnapcraftBuilder(
'.',
false,
'stable',
'--foo --bar',
'',
false
['FOO=bar', 'BAZ=qux'],
false,
''
)
await builder.build()

Expand All @@ -283,6 +357,10 @@ test('SnapcraftBuilder.build can pass additional arguments', async () => {
'--workdir',
'/data',
'--env',
'FOO=bar',
'--env',
'BAZ=qux',
'--env',
`SNAPCRAFT_IMAGE_INFO={"build_url":"https://github.com/user/repo/actions/runs/42"}`,
'--env',
'USE_SNAPCRAFT_CHANNEL=stable',
Expand All @@ -295,6 +373,61 @@ test('SnapcraftBuilder.build can pass additional arguments', async () => {
)
})

test('SnapcraftBuilder.build adds store credentials', async () => {
expect.assertions(1)

const ensureDockerExperimentalMock = jest
.spyOn(tools, 'ensureDockerExperimental')
.mockImplementation(async (): Promise<void> => Promise.resolve())
const detectBaseMock = jest
.spyOn(tools, 'detectBase')
.mockImplementation(
async (projectRoot: string): Promise<string> => default_base
)
const execMock = jest
.spyOn(exec, 'exec')
.mockImplementation(
async (program: string, args?: string[]): Promise<number> => 0
)

const builder = new build.SnapcraftBuilder(
'.',
false,
'stable',
'--foo --bar',
'',
[],
false,
'TEST_STORE_CREDENTIALS'
)
await builder.build()

expect(execMock).toHaveBeenCalledWith(
'docker',
[
'run',
'--rm',
'--tty',
'--privileged',
'--volume',
`${process.cwd()}:/data`,
'--workdir',
'/data',
'--env',
`SNAPCRAFT_IMAGE_INFO={"build_url":"https://github.com/user/repo/actions/runs/42"}`,
'--env',
'USE_SNAPCRAFT_CHANNEL=stable',
'--env',
'SNAPCRAFT_STORE_CREDENTIALS=TEST_STORE_CREDENTIALS',
`diddledani/snapcraft:${default_base}`,
'snapcraft',
'--foo',
'--bar'
],
expect.anything()
)
})

test('SnapcraftBuilder.outputSnap fails if there are no snaps', async () => {
expect.assertions(2)

Expand All @@ -305,8 +438,9 @@ test('SnapcraftBuilder.outputSnap fails if there are no snaps', async () => {
'stable',
'',
'',
'',
false
[],
false,
''
)

const readdir = jest
Expand All @@ -331,8 +465,9 @@ test('SnapcraftBuilder.outputSnap returns the first snap', async () => {
'stable',
'',
'',
'',
false
[],
false,
''
)

const readdir = jest
Expand Down
Loading