Skip to content

Commit

Permalink
feat(action): setup ollama cli
Browse files Browse the repository at this point in the history
  • Loading branch information
remarkablemark committed Feb 20, 2025
1 parent 743b7ed commit 9d9b73e
Show file tree
Hide file tree
Showing 10 changed files with 106 additions and 87 deletions.
22 changes: 14 additions & 8 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,19 @@ jobs:
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}

- name: Run action
uses: ./

- name: Get version
run: ollama --version

# action should work on a clean machine without building
integration:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
version: [2.27.0]
version: [0.5.10, 0.5.11]

steps:
- name: Checkout repository
Expand All @@ -47,21 +53,21 @@ jobs:
- name: Run action
uses: ./
with:
cli-version: ${{ matrix.version }}
cli-name: gh
version: ${{ matrix.version }}
name: ollama-cli

- name: Locate binary
run: command -v gh
run: command -v ollama-cli

- name: Check version
shell: bash
run: |
gh --version &> CLI_VERSION
ollama-cli --version &> CLI_VERSION
if [[ $(cat CLI_VERSION) != *'${{ matrix.version }}'* ]]; then
echo 'Version does not match. See version below:'
gh --version
ollama-cli --version
exit 1
fi
- name: Show help
run: gh --help
- name: Run LLM
run: ollama-cli run llama3.2 'Explain the basics of machine learning.'
19 changes: 11 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,22 @@
[![build](https://github.com/ai-action/setup-ollama/actions/workflows/build.yml/badge.svg)](https://github.com/ai-action/setup-ollama/actions/workflows/build.yml)
[![codecov](https://codecov.io/gh/ai-action/setup-ollama/graph/badge.svg?token=PGPJ2Q8HUO)](https://codecov.io/gh/ai-action/setup-ollama)

🦙 Set up GitHub Actions workflow with [ollama](https://github.com/ollama/ollama).
🦙 Set up GitHub Actions workflow with [Ollama](https://github.com/ollama/ollama).

## Quick Start

```yaml
name: setup-ollama
on: push
jobs:
setup-ollama:
prompt:
runs-on: ubuntu-latest
steps:
- name: Setup setup-ollama
uses: ai-action/setup-ollama@v1

- name: Run LLM
run: ollama run llama3.2 'Explain the basics of machine learning.'
```
## Usage
Expand All @@ -32,24 +35,24 @@ See [action.yml](action.yml)
## Inputs
### `cli-version`
### `version`

**Optional**: The CLI [version](https://github.com/cli/cli/releases). Defaults to [`2.49.0`](https://github.com/cli/cli/releases/tag/v2.49.0):
**Optional**: The CLI [version](https://github.com/ollama/ollama/releases). Defaults to [`0.5.11`](https://github.com/ollama/ollama/releases/tag/v0.5.11):

```yaml
- uses: ai-action/setup-ollama@v1
with:
cli-version: 2.49.0
version: 0.5.11
```

### `cli-name`
### `name`

**Optional**: The CLI name. Defaults to `gh`:
**Optional**: The CLI name. Defaults to `ollama`:

```yaml
- uses: ai-action/setup-ollama@v1
with:
cli-name: gh
name: ollama
```

## License
Expand Down
10 changes: 5 additions & 5 deletions action.yml
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
name: setup-ollama
description: GitHub Actions setup CLI template
description: Set up GitHub Actions workflow with ollama
author: remarkablemark
inputs:
cli-version:
version:
description: CLI version
required: false
default: 2.49.0
cli-name:
default: 0.5.11
name:
description: CLI name
required: false
default: gh
default: ollama
runs:
using: node20
main: dist/index.js
Expand Down
2 changes: 1 addition & 1 deletion dist/index.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "setup-ollama",
"version": "1.0.0-alpha",
"description": "GitHub Actions setup CLI template",
"description": "Set up GitHub Actions workflow with ollama",
"author": "Mark <[email protected]>",
"main": "src/index.ts",
"scripts": {
Expand Down
49 changes: 14 additions & 35 deletions src/__snapshots__/utils.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -6,65 +6,44 @@ exports[`getBinaryPath when OS is "linux" returns CLI filepath 1`] = `"directory

exports[`getBinaryPath when OS is "win32" returns CLI filepath 1`] = `"directory/name.exe"`;

exports[`getDownloadObject when OS is "darwin" and arch is "arm" gets download object 1`] = `
exports[`getDownloadObject when OS is "darwin" and arch is "arm64" gets download object 1`] = `
{
"binaryDirectory": "gh_2.27.0_macOS_arm/bin",
"url": "https://github.com/cli/cli/releases/download/v2.27.0/gh_2.27.0_macOS_arm.tar.gz",
}
`;

exports[`getDownloadObject when OS is "darwin" and arch is "x32" gets download object 1`] = `
{
"binaryDirectory": "gh_2.27.0_macOS_386/bin",
"url": "https://github.com/cli/cli/releases/download/v2.27.0/gh_2.27.0_macOS_386.tar.gz",
"binaryDirectory": "",
"url": "https://github.com/ollama/ollama/releases/download/v0.5.11/ollama-darwin.tgz",
}
`;

exports[`getDownloadObject when OS is "darwin" and arch is "x64" gets download object 1`] = `
{
"binaryDirectory": "gh_2.27.0_macOS_amd64/bin",
"url": "https://github.com/cli/cli/releases/download/v2.27.0/gh_2.27.0_macOS_amd64.tar.gz",
}
`;

exports[`getDownloadObject when OS is "linux" and arch is "arm" gets download object 1`] = `
{
"binaryDirectory": "gh_2.27.0_linux_arm/bin",
"url": "https://github.com/cli/cli/releases/download/v2.27.0/gh_2.27.0_linux_arm.tar.gz",
"binaryDirectory": "",
"url": "https://github.com/ollama/ollama/releases/download/v0.5.11/ollama-darwin.tgz",
}
`;

exports[`getDownloadObject when OS is "linux" and arch is "x32" gets download object 1`] = `
exports[`getDownloadObject when OS is "linux" and arch is "arm64" gets download object 1`] = `
{
"binaryDirectory": "gh_2.27.0_linux_386/bin",
"url": "https://github.com/cli/cli/releases/download/v2.27.0/gh_2.27.0_linux_386.tar.gz",
"binaryDirectory": "bin",
"url": "https://github.com/ollama/ollama/releases/download/v0.5.11/ollama-linux-arm64.tgz",
}
`;

exports[`getDownloadObject when OS is "linux" and arch is "x64" gets download object 1`] = `
{
"binaryDirectory": "gh_2.27.0_linux_amd64/bin",
"url": "https://github.com/cli/cli/releases/download/v2.27.0/gh_2.27.0_linux_amd64.tar.gz",
}
`;

exports[`getDownloadObject when OS is "win32" and arch is "arm" gets download object 1`] = `
{
"binaryDirectory": "bin",
"url": "https://github.com/cli/cli/releases/download/v2.27.0/gh_2.27.0_windows_arm.zip",
"url": "https://github.com/ollama/ollama/releases/download/v0.5.11/ollama-linux-amd64.tgz",
}
`;

exports[`getDownloadObject when OS is "win32" and arch is "x32" gets download object 1`] = `
exports[`getDownloadObject when OS is "win32" and arch is "arm64" gets download object 1`] = `
{
"binaryDirectory": "bin",
"url": "https://github.com/cli/cli/releases/download/v2.27.0/gh_2.27.0_windows_386.zip",
"binaryDirectory": "",
"url": "https://github.com/ollama/ollama/releases/download/v0.5.11/ollama-windows-arm64.zip",
}
`;

exports[`getDownloadObject when OS is "win32" and arch is "x64" gets download object 1`] = `
{
"binaryDirectory": "bin",
"url": "https://github.com/cli/cli/releases/download/v2.27.0/gh_2.27.0_windows_amd64.zip",
"binaryDirectory": "",
"url": "https://github.com/ollama/ollama/releases/download/v0.5.11/ollama-windows-amd64.zip",
}
`;
29 changes: 20 additions & 9 deletions src/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,22 @@
import * as core from '@actions/core';
import * as exec from '@actions/exec';
import * as tc from '@actions/tool-cache';
import { type ChildProcess, spawn } from 'child_process';
import os from 'os';

import { run } from '.';

jest.mock('@actions/core');
jest.mock('@actions/exec');
jest.mock('@actions/tool-cache');
jest.mock('child_process');
jest.mock('os');

const mockedCore = jest.mocked(core);
const mockedExec = jest.mocked(exec);
const mockedTc = jest.mocked(tc);
const mockedOs = jest.mocked(os);
const mockedSpawn = jest.mocked(spawn);

beforeEach(() => {
jest.resetAllMocks();
Expand All @@ -31,46 +34,54 @@ describe.each(['darwin', 'win32', 'linux'])('when OS is %p', (os) => {

mockedCore.getInput.mockImplementation((input) => {
switch (input) {
case 'cli-version':
case 'version':
return cliVersion;
case 'cli-name':
case 'name':
return cliName;
default:
return '';
}
});
});

const binPath = os === 'linux' ? `${pathToCLI}/bin` : pathToCLI;
const cliPath = `${binPath}/${cliName}`;

it('downloads, extracts, and adds CLI to PATH', async () => {
mockedTc.downloadTool.mockResolvedValueOnce(pathToTarball);
const extract = os === 'win32' ? mockedTc.extractZip : mockedTc.extractTar;
extract.mockResolvedValueOnce(pathToCLI);
const unref = jest.fn();
mockedSpawn.mockReturnValueOnce({ unref } as unknown as ChildProcess);

await run();

expect(mockedTc.downloadTool).toHaveBeenCalledWith(
expect.stringContaining(
`https://github.com/cli/cli/releases/download/v${cliVersion}/gh_${cliVersion}_`,
`https://github.com/ollama/ollama/releases/download/v${cliVersion}/ollama-`,
),
);

expect(extract).toHaveBeenCalledWith(pathToTarball);

expect(mockedExec.exec).toHaveBeenCalledWith('mv', [
expect.stringContaining(`/bin/${cliName}`),
expect.stringContaining(`/bin/${cliName}`),
`${binPath}/ollama`,
cliPath,
]);

expect(mockedSpawn).toHaveBeenCalledWith(cliPath, ['serve'], {
detached: true,
});
expect(unref).toHaveBeenCalledTimes(1);

expect(mockedTc.cacheFile).toHaveBeenCalledWith(
expect.stringContaining(`/bin/${cliName}`),
cliPath,
cliName,
cliName,
cliVersion,
);

expect(mockedCore.addPath).toHaveBeenCalledWith(
expect.stringContaining(pathToCLI),
);
expect(mockedCore.addPath).toHaveBeenCalledWith(binPath);
});
});

Expand Down
15 changes: 11 additions & 4 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,16 @@ import {
extractZip,
find,
} from '@actions/tool-cache';
import { spawn } from 'child_process';
import path from 'path';

import { getBinaryPath, getDownloadObject } from './utils';

export async function run() {
try {
// Get the version and name of the tool to be installed
const cliVersion = getInput('cli-version');
const cliName = getInput('cli-name');
const cliVersion = getInput('version');
const cliName = getInput('name');
const toolName = cliName;

// Find previously cached directory (if applicable)
Expand All @@ -39,11 +40,17 @@ export async function run() {
binaryPath = getBinaryPath(binaryDirectory, cliName);

// Rename the binary
if (cliName !== 'gh') {
await exec('mv', [getBinaryPath(binaryDirectory, cliName), binaryPath]);
if (cliName !== 'ollama') {
await exec('mv', [
getBinaryPath(binaryDirectory, 'ollama'),
binaryPath,
]);
}
}

// Run Ollama in the background
spawn(binaryPath, ['serve'], { detached: true }).unref();

// Expose the tool by adding it to the PATH
addPath(path.dirname(binaryPath));

Expand Down
4 changes: 2 additions & 2 deletions src/utils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ jest.mock('os');
const mockedOs = jest.mocked(os);

const platforms = ['darwin', 'linux', 'win32'] as const;
const architectures = ['arm', 'x32', 'x64'] as const;
const architectures = ['arm64', 'x64'] as const;

const table = platforms.reduce(
(testSuites, os) => [
Expand All @@ -18,7 +18,7 @@ const table = platforms.reduce(

describe('getDownloadObject', () => {
describe.each(table)('when OS is %p and arch is %p', (os, arch) => {
const version = '2.27.0';
const version = '0.5.11';

beforeEach(() => {
jest.resetAllMocks();
Expand Down
Loading

0 comments on commit 9d9b73e

Please sign in to comment.