Skip to content

Commit 689364b

Browse files
mpociotclaude
andcommitted
Add Repository.createWorkspace method, CI workflow, and tests
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 3e62394 commit 689364b

4 files changed

Lines changed: 138 additions & 0 deletions

File tree

.github/workflows/tests.yml

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
name: Tests
2+
3+
on:
4+
push:
5+
pull_request:
6+
7+
jobs:
8+
tests:
9+
runs-on: ubuntu-latest
10+
11+
strategy:
12+
fail-fast: false
13+
matrix:
14+
php: ['8.2', '8.3', '8.4']
15+
16+
steps:
17+
- name: Checkout
18+
uses: actions/checkout@v4
19+
20+
- name: Setup PHP
21+
uses: shivammathur/setup-php@v2
22+
with:
23+
php-version: ${{ matrix.php }}
24+
coverage: none
25+
26+
- name: Validate composer.json
27+
run: composer validate --strict
28+
29+
- name: Install dependencies
30+
run: composer install --prefer-dist --no-interaction --no-progress
31+
32+
- name: Run tests
33+
run: composer test

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@ $polyscope = new Polyscope('your-api-token');
1818
$servers = $polyscope->servers();
1919
$repositories = $polyscope->repositories();
2020
$workspaces = $polyscope->workspaces();
21+
22+
// Create a workspace directly from a repository resource.
23+
$workspace = $repositories[0]->createWorkspace([
24+
'prompt' => 'Fix the login flow',
25+
'server_id' => 'srv-1', // optional
26+
]);
2127
```
2228

2329
If no token is passed, the SDK automatically falls back to Polyscope's local settings file and reads `authToken`.

src/Resources/Repository.php

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
namespace Polyscope\Laravel\Resources;
66

7+
use RuntimeException;
8+
79
class Repository extends Resource
810
{
911
public ?string $id = null;
@@ -38,4 +40,42 @@ class Repository extends Resource
3840
public ?string $createdAt = null;
3941

4042
public ?string $serverId = null;
43+
44+
/**
45+
* @param array<string, mixed> $data
46+
*/
47+
public function createWorkspace(array $data = []): Workspace
48+
{
49+
$repositoryId = $this->id();
50+
51+
if (
52+
isset($data['repository_id'])
53+
&& is_string($data['repository_id'])
54+
&& $data['repository_id'] !== $repositoryId
55+
) {
56+
throw new RuntimeException('The provided repository_id does not match this repository resource.');
57+
}
58+
59+
$data['repository_id'] = $repositoryId;
60+
61+
return $this->client()->createWorkspace($data);
62+
}
63+
64+
protected function client(): \Polyscope\Laravel\Polyscope
65+
{
66+
if ($this->polyscope === null) {
67+
throw new RuntimeException('No Polyscope client instance available for this resource.');
68+
}
69+
70+
return $this->polyscope;
71+
}
72+
73+
protected function id(): string
74+
{
75+
if ($this->id === null || $this->id === '') {
76+
throw new RuntimeException('Repository ID is missing from resource payload.');
77+
}
78+
79+
return $this->id;
80+
}
4181
}

tests/PolyscopeSDKTest.php

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
use Polyscope\Laravel\Resources\Workspace;
1919
use Polyscope\Laravel\Resources\WorkspaceDiff;
2020
use Polyscope\Laravel\Resources\WorkspaceMessages;
21+
use RuntimeException;
2122

2223
class PolyscopeSDKTest extends TestCase
2324
{
@@ -205,6 +206,64 @@ public function test_creating_workspace_returns_workspace_resource(): void
205206
$this->assertSame([], $workspace->linkedWorktreeIds);
206207
}
207208

209+
public function test_repository_resource_can_create_workspace_without_manual_repository_id(): void
210+
{
211+
$sdk = new Polyscope('token', $http = Mockery::mock(Client::class));
212+
213+
$http->shouldReceive('request')
214+
->once()
215+
->with('POST', 'v1/workspaces', [
216+
'timeout' => 30,
217+
'json' => [
218+
'prompt' => 'Fix bug',
219+
'server_id' => 'srv-1',
220+
'repository_id' => 'repo-1',
221+
],
222+
])
223+
->andReturn(new Response(201, [], json_encode([
224+
'data' => [
225+
'id' => 'wt-1',
226+
'repo_id' => 'repo-1',
227+
'branch' => 'fix-bug',
228+
'status' => 'active',
229+
],
230+
], JSON_THROW_ON_ERROR)));
231+
232+
$repository = new \Polyscope\Laravel\Resources\Repository([
233+
'id' => 'repo-1',
234+
'name' => 'polyscope',
235+
'path' => '/code/polyscope',
236+
], $sdk);
237+
238+
$workspace = $repository->createWorkspace([
239+
'prompt' => 'Fix bug',
240+
'server_id' => 'srv-1',
241+
]);
242+
243+
$this->assertInstanceOf(Workspace::class, $workspace);
244+
$this->assertSame('wt-1', $workspace->id);
245+
$this->assertSame('repo-1', $workspace->repoId);
246+
}
247+
248+
public function test_repository_resource_rejects_mismatched_repository_id_when_creating_workspace(): void
249+
{
250+
$this->expectException(RuntimeException::class);
251+
$this->expectExceptionMessage('The provided repository_id does not match this repository resource.');
252+
253+
$sdk = new Polyscope('token');
254+
255+
$repository = new \Polyscope\Laravel\Resources\Repository([
256+
'id' => 'repo-1',
257+
'name' => 'polyscope',
258+
'path' => '/code/polyscope',
259+
], $sdk);
260+
261+
$repository->createWorkspace([
262+
'repository_id' => 'repo-2',
263+
'prompt' => 'Fix bug',
264+
]);
265+
}
266+
208267
public function test_workspace_show_maps_nested_properties(): void
209268
{
210269
$sdk = new Polyscope('token', $http = Mockery::mock(Client::class));

0 commit comments

Comments
 (0)