Author SHA1 Message Date
dependabot[bot] e3ba7e82e2 chore(deps-dev): update pestphp/pest requirement from ^3.0 to ^5.3
Updates the requirements on [pestphp/pest](https://github.com/pestphp/pest) to permit the latest version.
- [Release notes](https://github.com/pestphp/pest/releases)
- [Changelog](https://github.com/pestphp/pest/blob/5.x/RELEASE.md)
- [Commits](https://github.com/pestphp/pest/compare/v3.0.0...v5.3.5)

---
updated-dependencies:
- dependency-name: pestphp/pest
  dependency-version: 5.3.5
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-11-03 21:24:30 +00:00
pixel-workflows[bot] c94788fdb8 chore: update dependabot configuration 2026-07-27 23:27:56 +00:00
pixel-workflows[bot] 3a5c51d3d0 chore: sync files from wearepixel/pixel-workflows - synced local 'pint.json' with remote 'files/pint.json' 2026-07-27 08:21:02 +00:00
pixel-workflows[bot] f7d07f45e5 chore: sync files from wearepixel/pixel-workflows - created local '.gitattributes' from remote 'files/.gitattributes' 2026-07-27 08:20:59 +00:00
pixel-workflows[bot] b4a5d00439 chore: sync files from wearepixel/pixel-workflows - synced local '.editorconfig' with remote 'files/.editorconfig' 2026-07-27 08:20:56 +00:00
pixel-workflows[bot] 524a09d545 chore: sync files from wearepixel/pixel-workflows - created local '.github/workflows/dependabot-slack-alert.yml' from remote 'files/.github/workflows/dependabot-slack-alert.yml' 2026-07-27 08:20:53 +00:00
pixel-workflows[bot] c75ab43346 chore: sync files from wearepixel/pixel-workflows - created local '.github/workflows/dependabot-auto-merge.yml' from remote 'files/.github/workflows/dependabot-auto-merge.yml' 2026-07-27 08:20:50 +00:00
Joel Male 32266f6dd5 fix: revert JSON serialization workaround, upgrade SDK to 6.3.1 instead
v2.0.1's useJson() workaround was wrong: the JSON request serializer
silently drops nested single-object fields (e.g. CustomerRef, which
QuickBooks requires), and the JSON response deserializer never returns
a typed entity, so $result->Id is always null downstream. That breaks
every dsCall() site, worse than the bug it was meant to fix.

The actual root cause was that quickbooks/v3-php-sdk 5.4.7 predates
QuickBooks Online's new invoice AllowOnlinePayPalPayment field, so its
XML deserializer throws on responses that include it. SDK 6.3.1
declares the field, so upgrading resolves the original error while
keeping the fully-supported XML path (and closes out the SDK bump
Dependabot already had queued in #3).

Verified: deserializing a response containing AllowOnlinePayPalPayment
throws RuntimeException on 5.4.7 and returns a correctly typed
IPPInvoice (with Id populated) on 6.3.1.
2026-07-27 07:15:59 +03:00
9 changed files with 193 additions and 39 deletions
+6 -4
View File
@@ -3,14 +3,16 @@ root = true
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
indent_style = space
indent_size = 4
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true
[*.md]
trim_trailing_whitespace = false
[*.yml]
indent_style = space
[*.{yml,yaml}]
indent_size = 2
[docker-compose.yml]
indent_size = 4
+11
View File
@@ -0,0 +1,11 @@
* text=auto eol=lf
*.blade.php diff=html
*.css diff=css
*.html diff=html
*.md diff=markdown
*.php diff=php
/.github export-ignore
CHANGELOG.md export-ignore
.styleci.yml export-ignore
+5
View File
@@ -8,6 +8,7 @@ updates:
open-pull-requests-limit: 10
groups:
actions:
applies-to: version-updates
patterns: ["*"]
commit-message:
prefix: "chore"
@@ -23,9 +24,13 @@ updates:
open-pull-requests-limit: 10
groups:
php-minor-patch:
applies-to: version-updates
update-types:
- "minor"
- "patch"
php-security:
applies-to: security-updates
patterns: ["*"]
commit-message:
prefix: "chore"
include: "scope"
@@ -0,0 +1,59 @@
name: Dependabot Auto-merge
on:
workflow_run:
workflows: ["Tests"]
types: [completed]
permissions:
contents: write
pull-requests: write
jobs:
auto-merge:
runs-on: ubuntu-latest
if: |
github.event.workflow_run.conclusion == 'success' &&
github.event.workflow_run.event == 'pull_request' &&
github.event.workflow_run.actor.login == 'dependabot[bot]'
steps:
- name: Find PR and check update type
id: check
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
HEAD_BRANCH: ${{ github.event.workflow_run.head_branch }}
run: |
PR_DATA=$(gh pr list --repo "${{ github.repository }}" --head "$HEAD_BRANCH" --json number,title,url,author --jq '.[0]')
PR_URL=$(echo "$PR_DATA" | jq -r '.url')
PR_AUTHOR=$(echo "$PR_DATA" | jq -r '.author.login')
PR_TITLE=$(echo "$PR_DATA" | jq -r '.title')
echo "pr_url=$PR_URL" >> $GITHUB_OUTPUT
if [ "$PR_AUTHOR" != "app/dependabot" ]; then
echo "is_safe=false" >> $GITHUB_OUTPUT
echo "Not a Dependabot PR, skipping."
exit 0
fi
# Parse major version numbers from title: "bump X from A[.B.C] to D[.E.F]"
# Works for both "from 4.0.0 to 4.1.0" and "from 4 to 6" (GitHub Actions)
FROM_MAJOR=$(echo "$PR_TITLE" | grep -oP 'from \K[0-9]+')
TO_MAJOR=$(echo "$PR_TITLE" | grep -oP 'to \K[0-9]+')
echo "PR: $PR_TITLE (major: $FROM_MAJOR -> $TO_MAJOR)"
if [ "$FROM_MAJOR" = "$TO_MAJOR" ]; then
echo "is_safe=true" >> $GITHUB_OUTPUT
else
echo "is_safe=false" >> $GITHUB_OUTPUT
echo "Major version bump, skipping auto-merge."
fi
- name: Merge minor and patch updates
if: steps.check.outputs.is_safe == 'true'
run: gh pr merge --merge "${{ steps.check.outputs.pr_url }}"
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -0,0 +1,98 @@
name: Dependabot Slack Alert
on:
pull_request_target:
types: [opened]
jobs:
notify:
name: Notify Slack of major update
runs-on: ubuntu-latest
if: github.actor == 'dependabot[bot]'
steps:
- name: Check if major version bump
id: check
env:
PR_TITLE: ${{ github.event.pull_request.title }}
run: |
from_major=$(echo "$PR_TITLE" | grep -oP 'from \K[0-9]+' | head -1)
to_major=$(echo "$PR_TITLE" | grep -oP 'to \K[0-9]+' | head -1)
if [ -n "$from_major" ] && [ -n "$to_major" ] && [ "$from_major" != "$to_major" ]; then
echo "is_major=true" >> $GITHUB_OUTPUT
echo "Major bump detected: $from_major -> $to_major"
else
echo "is_major=false" >> $GITHUB_OUTPUT
echo "Minor/patch bump, skipping"
fi
- name: Send Slack alert
if: steps.check.outputs.is_major == 'true'
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
PR_TITLE: ${{ github.event.pull_request.title }}
PR_URL: ${{ github.event.pull_request.html_url }}
PR_NUMBER: ${{ github.event.pull_request.number }}
REPO: ${{ github.repository }}
run: |
if [ -z "$SLACK_WEBHOOK_URL" ]; then
echo "SLACK_WEBHOOK_URL not configured for this repo, skipping"
exit 0
fi
payload=$(jq -n \
--arg repo "$REPO" \
--arg title "$PR_TITLE" \
--arg url "$PR_URL" \
--arg pr "#$PR_NUMBER" \
'{
blocks: [
{
type: "section",
text: {
type: "mrkdwn",
text: ":dependabot: *Major dependency update requires review*"
}
},
{
type: "section",
fields: [
{type: "mrkdwn", text: ("*Repository*\n`" + $repo + "`")},
{type: "mrkdwn", text: ("*Pull Request*\n<" + $url + "|" + $pr + ">") }
]
},
{
type: "section",
text: {
type: "mrkdwn",
text: $title
}
},
{
type: "context",
elements: [
{
type: "mrkdwn",
text: "Major version bumps are not auto-merged as they may contain breaking changes."
}
]
},
{
type: "actions",
elements: [
{
type: "button",
text: {type: "plain_text", text: "Review PR"},
url: $url,
style: "primary"
}
]
}
]
}')
curl -s -o /dev/null -w "%{http_code}" -X POST "$SLACK_WEBHOOK_URL" \
-H "Content-type: application/json" \
--data "$payload" | grep -q "^200$" \
&& echo "Slack notification sent" \
|| echo "Slack notification failed"
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "wearepixel/laravel-quickbooks",
"version": "2.0.1",
"version": "2.0.2",
"description": "Laravel Client for QuickBooks.",
"keywords": [
"quickbooks",
@@ -22,12 +22,12 @@
"illuminate/routing": "^10.0|^11.0|^12.0",
"illuminate/support": "^10.0|^11.0|^12.0",
"nesbot/carbon": "^2.62.1|^3.0",
"quickbooks/v3-php-sdk": "^5.4.6"
"quickbooks/v3-php-sdk": "^6.3.1"
},
"require-dev": {
"laravel/pint": "^1.2",
"mockery/mockery": "^1.6",
"pestphp/pest": "^3.0",
"pestphp/pest": "^5.3",
"psy/psysh": "^0.12"
},
"autoload": {
+8 -1
View File
@@ -1,6 +1,13 @@
{
"preset": "laravel",
"rules": {
"no_superfluous_phpdoc_tags": true
"concat_space": {
"spacing": "one"
},
"class_attributes_separation": false,
"ordered_imports": {
"sort_algorithm": "length"
},
"not_operator_with_space": false
}
}
+3 -9
View File
@@ -181,12 +181,6 @@ public function hasValidRefreshToken(): bool
* 2) Have valid refresh token, so renew access token & then use
* 3) No existing token, so need to link account
*
* useJson() is applied in every case: the SDK's default XML deserializer reflects
* declared properties on its Data classes and throws when QuickBooks adds a new
* response field the installed SDK version doesn't know about yet. The JSON
* deserializer builds instances from the class's own properties and silently
* ignores unrecognised keys instead, so it tolerates QuickBooks-side schema drift.
*
* @throws SdkException
* @throws ServiceException
*/
@@ -209,7 +203,7 @@ protected function makeDataService(): DataService
'QBORealmID' => $this->token->realm_id,
'refreshTokenKey' => $this->token->refresh_token,
]),
)->useJson();
);
}
// Have refresh, so update access & allow app to run
@@ -220,7 +214,7 @@ protected function makeDataService(): DataService
'QBORealmID' => $this->token->realm_id,
'refreshTokenKey' => $this->token->refresh_token,
]),
)->useJson();
);
$oauth_token = $data_service->getOAuth2LoginHelper()->refreshToken();
@@ -232,7 +226,7 @@ protected function makeDataService(): DataService
}
// Create new...
return DataService::Configure($this->parseDataConfigs())->useJson();
return DataService::Configure($this->parseDataConfigs());
}
/**
-22
View File
@@ -1,6 +1,5 @@
<?php
use QuickBooksOnline\API\Core\Http\Serialization\SerializationFormat;
use QuickBooksOnline\API\DataService\DataService;
use QuickBooksOnline\API\Exception\ServiceException;
use Wearepixel\QuickBooks\Client;
@@ -131,27 +130,6 @@
it('returns a report service using the data service')
->skip('Once we figure out how to test around the static DataService::Configure');
it('configures the data service to use JSON serialization so unrecognised QuickBooks response fields do not throw', function () {
$this->token_mock
->shouldReceive('getAttribute')
->twice()
->with('hasValidAccessToken')
->andReturnFalse();
$this->token_mock
->shouldReceive('getAttribute')
->once()
->with('hasValidRefreshToken')
->andReturnFalse();
$format = $this->client
->getDataService()
->getServiceContext()
->IppConfiguration->Message->Request->SerializationFormat;
expect($format)->toBe(SerializationFormat::Json);
});
it('has logging off by default')
->skip('Have to figure out how to test this with the new code in 5.x');