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

feat: [sc-117417] Add semver support and device-os-output variable #7

Merged
merged 9 commits into from
Apr 6, 2023
Merged
Show file tree
Hide file tree
Changes from 8 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
14 changes: 12 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,26 @@ A GitHub Action to compile Particle application firmware
sources-folder: 'src'

# Target Device OS firmware version
# For production projects, you should pin to a specific Device OS version
# Allowed values:
# latest: the most recent Device OS version for the platform
# latest-lts: the most recent LTS Device OS version for the platform
# <version>: a specific Device OS version, e.g. 2.3.1
# ^<version>: a semver range, e.g. ^5.3.0
# For production projects, you should pin to a specific Device OS semver range, e.g. ^4.0.0
# Required: false
device-os-version: 'latest'
device-os-version: 'latest-lts'

# Particle access token
# If provided, the action will use the Particle Cloud Compiler instead of compiling within the GitHub Action runner
# Required: false
particle-access-token: ''
```

### Outputs

* `artifact-path`: Path to the compiled binary artifact. Typically, it will be `output/firmware.bin`
* `device-os-version`: The Device OS version that was used for compilation. This may differ from the requested version if the requested version is a semver range or `latest` or `latest-lts`. Example: `2.3.1`

### Example Pipeline

This is a simple example of a GitHub Actions pipeline that compiles a firmware project and uploads the compiled binary as an artifact.
Expand Down
6 changes: 4 additions & 2 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,17 @@ inputs:
default: ''
device-os-version:
required: false
description: 'Target Device OS firmware version. Example: 4.0.2'
default: 'latest'
description: 'Target Device OS firmware version. Allowed values: latest, latest-lts, or a semver version number. Example: latest, latest-lts, 4.x, ^5.3.0, 1.4.4'
default: 'latest-lts'
sources-folder:
required: false
description: 'Path to directory with sources to compile. Example: src'
default: 'src'
outputs:
artifact-path:
description: 'Path to the compiled binary file. Example: output/firmware.bin'
device-os-version:
description: 'This output contains the actual Device OS version used for compilation. Example: 4.0.2'
runs:
using: 'node16'
main: 'dist/index.js'
97 changes: 64 additions & 33 deletions dist/index.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@
"@particle/device-constants": "^3.1.7",
"execa": "^5.0.0",
"glob": "^7.2.3",
"particle-api-js": "^9.4.1"
"particle-api-js": "^9.4.1",
"semver": "^7.3.8"
},
"devDependencies": {
"@types/jest": "^27.5.2",
Expand Down
11 changes: 11 additions & 0 deletions src/action.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ describe('compileAction', () => {
it('should use compile locally with docker by default', async () => {
const dockerCheckMock = jest.fn();
const dockerBuildpackCompileMock = jest.fn();
jest.mock('./util', () => ({
resolveVersion: jest.fn(),
validatePlatformName: jest.fn(),
validatePlatformDeviceOsTarget: jest.fn()
}));
jest.mock('./docker', () => ({
dockerCheck: dockerCheckMock,
dockerBuildpackCompile: dockerBuildpackCompileMock
Expand All @@ -18,6 +23,11 @@ describe('compileAction', () => {
});

it('should use compile in the cloud if access token is provided', async () => {
jest.mock('./util', () => ({
resolveVersion: jest.fn(),
validatePlatformName: jest.fn(),
validatePlatformDeviceOsTarget: jest.fn()
}));
// mock particle-access-token input
jest.mock('@actions/core', () => ({
getInput: jest.fn().mockImplementation((name: string) => {
Expand Down Expand Up @@ -67,4 +77,5 @@ describe('compileAction', () => {
expect(setFailedMock).toHaveBeenCalled();
expect(setFailedMock).toHaveBeenCalledWith('Failed to compile code in cloud');
});

});
9 changes: 8 additions & 1 deletion src/action.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
import { getInput, info, setFailed, setOutput } from '@actions/core';
import { dockerBuildpackCompile, dockerCheck } from './docker';
import { particleCloudCompile, particleDownloadBinary } from './particle-api';
import { resolveVersion, validatePlatformDeviceOsTarget, validatePlatformName } from './util';

export async function compileAction(): Promise<void> {
try {
const auth: string = getInput('particle-access-token');
const platform: string = getInput('particle-platform-name');
const targetVersion: string = getInput('device-os-version');
const version: string = getInput('device-os-version');
const sources: string = getInput('sources-folder');

validatePlatformName(platform);

const targetVersion = await resolveVersion(platform, version);
await validatePlatformDeviceOsTarget(platform, targetVersion);

let outputPath: string | undefined;
if (!auth) {
info('No access token provided, running local compilation');
Expand All @@ -25,6 +31,7 @@ export async function compileAction(): Promise<void> {

if (outputPath) {
setOutput('artifact-path', outputPath);
setOutput('device-os-version', targetVersion);
} else {
setFailed(`Failed to compile code in '${sources}'`);
}
Expand Down
15 changes: 11 additions & 4 deletions src/docker.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { dockerBuildpackCompile, dockerCheck } from './docker';
import fs from 'fs';
import { normalize } from 'path';
import nock from 'nock';

const execa = require('execa');
jest.mock('execa');
Expand Down Expand Up @@ -56,6 +57,12 @@ describe('dockerCheck', () => {
});

describe('dockerBuildpackCompile', () => {
beforeEach(() => {
nock('https://binaries.particle.io')
.get('/firmware-versions-manifest.json')
.replyWithFile(200, `test/fixtures/firmware-manifest-v1/manifest.json`);
});

it('should throw on invalid platform', () => {
return expect(dockerBuildpackCompile({
workingDir: 'workingDir',
Expand All @@ -70,7 +77,7 @@ describe('dockerBuildpackCompile', () => {
workingDir: 'workingDir',
sources: 'sources',
platform: 'argon',
targetVersion: 'latest'
targetVersion: '4.0.2'
});
expect(execa).toHaveBeenCalledTimes(2);
expect(execa.mock.calls[0]).toEqual([
Expand Down Expand Up @@ -101,7 +108,7 @@ describe('dockerBuildpackCompile', () => {
workingDir: 'workingDir',
sources: 'src',
platform: 'argon',
targetVersion: 'latest'
targetVersion: '4.0.2'
});
expect(execa).toHaveBeenCalledTimes(2);
expect(execa.mock.calls[1]).toEqual([
Expand All @@ -127,7 +134,7 @@ describe('dockerBuildpackCompile', () => {
workingDir,
sources,
platform: 'argon',
targetVersion: 'latest'
targetVersion: '4.0.2'
});
expect(execa).toHaveBeenCalledTimes(2);
expect(execa.mock.calls[1]).toEqual([
Expand All @@ -151,7 +158,7 @@ describe('dockerBuildpackCompile', () => {
workingDir: 'workingDir',
sources: '/absolute/path/to/src',
platform: 'argon',
targetVersion: 'latest'
targetVersion: '4.0.2'
});
expect(execa).toHaveBeenCalledTimes(2);
expect(execa.mock.calls[1]).toEqual([
Expand Down
Loading