Skip to content
Open
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
28 changes: 0 additions & 28 deletions .github/workflows/fix-php-code-style-issues.yml

This file was deleted.

26 changes: 26 additions & 0 deletions .github/workflows/gate.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: Sentinel Gate

on:
push:
branches: [master]
pull_request:
branches: [master]

jobs:
gate:
name: Sentinel Gate
runs-on: ubuntu-latest
permissions:
contents: write
checks: write
pull-requests: write
issues: write
steps:
- uses: actions/checkout@v4
- uses: synapse-sentinel/gate@v1
with:
check: certify
coverage-threshold: 100
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

100% coverage threshold may be too restrictive.

Requiring 100% test coverage can be impractical and may block legitimate PRs. Consider whether this strict threshold aligns with your development workflow, especially for:

  • Generated code or boilerplate
  • Defensive error handling
  • Edge cases with diminishing returns

A threshold of 90-95% is more commonly used in production environments.

🤖 Prompt for AI Agents
In .github/workflows/gate.yml at line 23 the coverage-threshold is set to 100
which is overly strict; update the value to a more practical threshold (e.g.,
95) or replace the hard-coded number with a reusable variable (e.g.,
${COVERAGE_THRESHOLD}) and document/update CI env or repo settings so the
threshold can be adjusted without editing the workflow.

auto-merge: true
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Auto-merge with write permissions poses security risks.

Enabling auto-merge: true combined with broad write permissions means PRs will merge automatically when checks pass, without human review. This can be risky because:

  • Code quality issues not caught by automated checks
  • Security vulnerabilities may slip through
  • Breaking changes to APIs or behavior
  • Compromised dependencies could be merged

Consider requiring manual approval for merges, especially for a repository with write access to contents and pull requests.

🤖 Prompt for AI Agents
.github/workflows/gate.yml around line 24: the workflow enables auto-merge
(auto-merge: true) which allows PRs to merge automatically when checks pass and
poses security risks; update the workflow to disable auto-merge by removing or
setting auto-merge to false, and/or add a requirement for manual approval by
configuring branch protection or a required reviewers step (e.g., require at
least one approver or restrict merge permissions to maintainers) so merges
cannot occur solely based on passing checks.

coverage-comment: true
github-token: ${{ secrets.GITHUB_TOKEN }}
Comment on lines +20 to +26
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🌐 Web query:

synapse-sentinel/gate GitHub action

💡 Result:

I couldn't find a GitHub repository or published Action named "synapse-sentinel/gate" on GitHub. Could you paste a link or give more context (owner, exact repo name, or where you saw it)?


🏁 Script executed:

# Check if the gate.yml file exists and view the full workflow
git ls-files ".github/workflows/*.yml" | grep -i gate

Repository: jordanpartridge/github-client

Length of output: 99


🌐 Web query:

synapse sentinel GitHub action gate checks

💡 Result:

Do you mean:

  • Azure Synapse (workspace) GitHub Action gate checks (CI/CD pre-deploy validations),
  • Azure Sentinel content repository GitHub Actions (policy/PR gate checks for Sentinel rules/workbooks), or
  • a specific GitHub Action named "synapse-sentinel" or "synapse sentinel"?

Tell me which one and your goal (e.g., run schema/KQL validation, block PR merges, run ARM/Bicep validation, deploy approvals), and I’ll fetch examples and config snippets.


🏁 Script executed:

# Read the full gate.yml workflow file
cat -n .github/workflows/gate.yml

Repository: jordanpartridge/github-client

Length of output: 790


🏁 Script executed:

# Check if there are custom actions defined in the repository
find .github/actions -type f -name "*.yml" -o -name "*.yaml" 2>/dev/null | head -20

Repository: jordanpartridge/github-client

Length of output: 55


🏁 Script executed:

# Search for "synapse-sentinel" anywhere in the repository
rg "synapse-sentinel" --type yaml --type yml

Repository: jordanpartridge/github-client

Length of output: 100


🏁 Script executed:

# Search for synapse-sentinel anywhere in repo without type restriction
rg "synapse-sentinel"

Repository: jordanpartridge/github-client

Length of output: 55


🏁 Script executed:

# Check if custom actions directory exists
ls -la .github/ | grep -E "^d"

Repository: jordanpartridge/github-client

Length of output: 298


🏁 Script executed:

# If custom actions exist, list them
if [ -d ".github/actions" ]; then find .github/actions -type f; else echo "No .github/actions directory"; fi

Repository: jordanpartridge/github-client

Length of output: 101


The synapse-sentinel/gate@v1 action does not exist and will cause workflow failures.

This action cannot be found as a published GitHub Action, and there are no custom actions defined in the repository. The workflow will fail immediately when GitHub Actions attempts to resolve this action. Either replace it with a real, maintained action or create a custom action with the required functionality. Additionally, the auto-merge: true setting combined with write permissions creates a security risk—merge decisions should require human review.

🤖 Prompt for AI Agents
.github/workflows/gate.yml lines 20-26: the workflow references a non-existent
action synapse-sentinel/gate@v1 which will cause resolution failures and also
enables risky auto-merge; replace this entry with a real, maintained action (or
implement a local composite/custom action in .github/actions and reference it)
that provides the intended certify/check/coverage features, update any input
names to match the chosen action's documented inputs (e.g., coverage-threshold,
coverage-comment), and remove or disable auto-merge (or set it to false) so
merges require human review; also ensure the workflow's token and permissions
are set minimally (no unnecessary write/merge rights) and validate the corrected
workflow by running a dry-run or linting it.

42 changes: 0 additions & 42 deletions .github/workflows/phpstan.yml

This file was deleted.

58 changes: 0 additions & 58 deletions .github/workflows/run-tests.yml

This file was deleted.

51 changes: 51 additions & 0 deletions tests/Enums/DirectionEnumTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php

use JordanPartridge\GithubClient\Enums\Direction;

describe('Direction enum', function () {
it('has ASC case with correct value', function () {
expect(Direction::ASC->value)->toBe('asc');
});

it('has DESC case with correct value', function () {
expect(Direction::DESC->value)->toBe('desc');
});

it('has exactly two cases', function () {
expect(Direction::cases())
->toHaveCount(2)
->and(array_column(Direction::cases(), 'name'))
->toContain('ASC', 'DESC');
});

it('can be created from valid string values', function () {
expect(Direction::from('asc'))->toBe(Direction::ASC)
->and(Direction::from('desc'))->toBe(Direction::DESC);
});

it('throws ValueError for invalid string value', function () {
expect(fn () => Direction::from('invalid'))
->toThrow(ValueError::class);
});

it('returns null for invalid value with tryFrom', function () {
expect(Direction::tryFrom('invalid'))->toBeNull()
->and(Direction::tryFrom('ASC'))->toBeNull()
->and(Direction::tryFrom('DESC'))->toBeNull();
});

it('can be used in match expressions', function () {
$result = match (Direction::ASC) {
Direction::ASC => 'ascending',
Direction::DESC => 'descending',
};

expect($result)->toBe('ascending');
});

it('works with array functions', function () {
$values = array_map(fn (Direction $d) => $d->value, Direction::cases());

expect($values)->toBe(['asc', 'desc']);
});
});
62 changes: 62 additions & 0 deletions tests/Enums/Issues/IssueSortEnumTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<?php

use JordanPartridge\GithubClient\Enums\Issues\Sort;

describe('Issues Sort enum', function () {
it('has CREATED case with correct value', function () {
expect(Sort::CREATED->value)->toBe('created');
});

it('has UPDATED case with correct value', function () {
expect(Sort::UPDATED->value)->toBe('updated');
});

it('has COMMENTS case with correct value', function () {
expect(Sort::COMMENTS->value)->toBe('comments');
});

it('has exactly three cases', function () {
expect(Sort::cases())
->toHaveCount(3)
->and(array_column(Sort::cases(), 'name'))
->toContain('CREATED', 'UPDATED', 'COMMENTS');
});

it('can be created from valid string values', function () {
expect(Sort::from('created'))->toBe(Sort::CREATED)
->and(Sort::from('updated'))->toBe(Sort::UPDATED)
->and(Sort::from('comments'))->toBe(Sort::COMMENTS);
});

it('throws ValueError for invalid string value', function () {
expect(fn () => Sort::from('invalid'))
->toThrow(ValueError::class);
});

it('returns null for invalid value with tryFrom', function () {
expect(Sort::tryFrom('invalid'))->toBeNull()
->and(Sort::tryFrom('CREATED'))->toBeNull()
->and(Sort::tryFrom('pushed'))->toBeNull();
});

it('can be used in match expressions', function () {
$getSortLabel = fn (Sort $sort) => match ($sort) {
Sort::CREATED => 'Sort by creation date',
Sort::UPDATED => 'Sort by last update',
Sort::COMMENTS => 'Sort by comment count',
};

expect($getSortLabel(Sort::CREATED))->toBe('Sort by creation date')
->and($getSortLabel(Sort::COMMENTS))->toBe('Sort by comment count');
});

it('works with array functions', function () {
$values = array_map(fn (Sort $s) => $s->value, Sort::cases());

expect($values)->toBe(['created', 'updated', 'comments']);
});

it('is distinct from main Sort enum', function () {
expect(Sort::class)->toBe('JordanPartridge\GithubClient\Enums\Issues\Sort');
});
});
72 changes: 72 additions & 0 deletions tests/Enums/Issues/IssueStateEnumTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<?php

use JordanPartridge\GithubClient\Enums\Issues\State;

describe('Issues State enum', function () {
it('has OPEN case with correct value', function () {
expect(State::OPEN->value)->toBe('open');
});

it('has CLOSED case with correct value', function () {
expect(State::CLOSED->value)->toBe('closed');
});

it('has ALL case with correct value', function () {
expect(State::ALL->value)->toBe('all');
});

it('has exactly three cases', function () {
expect(State::cases())
->toHaveCount(3)
->and(array_column(State::cases(), 'name'))
->toContain('OPEN', 'CLOSED', 'ALL');
});

it('can be created from valid string values', function () {
expect(State::from('open'))->toBe(State::OPEN)
->and(State::from('closed'))->toBe(State::CLOSED)
->and(State::from('all'))->toBe(State::ALL);
});

it('throws ValueError for invalid string value', function () {
expect(fn () => State::from('invalid'))
->toThrow(ValueError::class);
});

it('returns null for invalid value with tryFrom', function () {
expect(State::tryFrom('invalid'))->toBeNull()
->and(State::tryFrom('OPEN'))->toBeNull()
->and(State::tryFrom('pending'))->toBeNull();
});

it('can be used in match expressions', function () {
$getStateDescription = fn (State $state) => match ($state) {
State::OPEN => 'Open issues only',
State::CLOSED => 'Closed issues only',
State::ALL => 'All issues',
};

expect($getStateDescription(State::OPEN))->toBe('Open issues only')
->and($getStateDescription(State::ALL))->toBe('All issues');
});

it('works with array functions', function () {
$values = array_map(fn (State $s) => $s->value, State::cases());

expect($values)->toBe(['open', 'closed', 'all']);
});

it('is distinct from Pulls State enum', function () {
expect(State::class)->toBe('JordanPartridge\GithubClient\Enums\Issues\State');
});

it('can filter to only active states', function () {
$activeStates = array_filter(
State::cases(),
fn (State $state) => $state !== State::ALL,
);

expect($activeStates)->toHaveCount(2)
->and(array_column($activeStates, 'value'))->toContain('open', 'closed');
});
});
Loading
Loading