paubox 0.3.2 β 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/scripts/assert_specs_ran.rb +40 -0
- data/.github/workflows/ci.yml +40 -0
- data/.github/workflows/pr-title.yml +36 -0
- data/.github/workflows/release-please.yml +88 -0
- data/.gitignore +4 -1
- data/.release-please-manifest.json +3 -0
- data/CHANGELOG.md +74 -0
- data/CLAUDE.md +114 -0
- data/README.md +255 -12
- data/api.md +283 -0
- data/lib/paubox/client.rb +15 -5
- data/lib/paubox/dynamic_templates.rb +58 -0
- data/lib/paubox/form.rb +51 -0
- data/lib/paubox/form_submission.rb +34 -0
- data/lib/paubox/forms_client.rb +211 -0
- data/lib/paubox/version.rb +1 -1
- data/lib/paubox.rb +10 -2
- data/paubox_ruby.gemspec +4 -0
- data/release-please-config.json +14 -0
- metadata +44 -7
- data/.travis.yml +0 -5
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: da4b3dae43dc155032452be9913d48e4da7ba65878067923af62bb5497783ebc
|
|
4
|
+
data.tar.gz: f7e0db657ed86db45207f3c0fcd280febd834262ebcac0313a5c48c0b7e2f186
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b450e2ca12166a1689fc460ec810c11dc6ad53cc2d1e71d29a06f701db91f901d2ead1ca4eb7c61f91ebb444c5caadcbc49c8a5f81157a256514bf90f4b33ac0
|
|
7
|
+
data.tar.gz: db478b8679f6acb5a5851b80826f81a1dd0b8360250acd68254812e4cf75c5f4bef83f21c8ec939bd43ec339e0489a554c4bfe271cc246719afcbb93816668c3
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
# Fail CI when a green rspec exit code does not mean the suite ran.
|
|
5
|
+
#
|
|
6
|
+
# A passing run is not evidence of coverage: an error outside an example, a
|
|
7
|
+
# stray tag filter, or a spec_helper that stops loading files can leave rspec
|
|
8
|
+
# reporting success having executed almost nothing. The failure mode is
|
|
9
|
+
# invisible precisely because the exit code is 0.
|
|
10
|
+
|
|
11
|
+
require 'json'
|
|
12
|
+
|
|
13
|
+
# Floor, not a target. Only trips if coverage regresses; adding specs is free.
|
|
14
|
+
MIN_EXAMPLES = 250
|
|
15
|
+
|
|
16
|
+
summary = JSON.parse(File.read(ARGV.fetch(0))).fetch('summary')
|
|
17
|
+
|
|
18
|
+
total = summary.fetch('example_count')
|
|
19
|
+
pending = summary.fetch('pending_count')
|
|
20
|
+
failures = summary.fetch('failure_count')
|
|
21
|
+
errors = summary.fetch('errors_outside_of_examples_count')
|
|
22
|
+
executed = total - pending
|
|
23
|
+
|
|
24
|
+
puts format(
|
|
25
|
+
'examples=%d executed=%d failures=%d pending=%d errors_outside_examples=%d',
|
|
26
|
+
total, executed, failures, pending, errors
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
problems = []
|
|
30
|
+
problems << "#{errors} error(s) outside of examples" if errors.positive?
|
|
31
|
+
if executed < MIN_EXAMPLES
|
|
32
|
+
problems << "only #{executed} example(s) executed, expected at least #{MIN_EXAMPLES}"
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
unless problems.empty?
|
|
36
|
+
warn "FAIL: #{problems.join('; ')}"
|
|
37
|
+
exit 1
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
puts "OK: suite executed #{executed} examples"
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
push:
|
|
6
|
+
branches: [master]
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
spec:
|
|
13
|
+
name: rspec (ruby ${{ matrix.ruby }})
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
strategy:
|
|
16
|
+
fail-fast: false
|
|
17
|
+
matrix:
|
|
18
|
+
ruby: ["3.1", "3.2", "3.3", "3.4"]
|
|
19
|
+
|
|
20
|
+
steps:
|
|
21
|
+
- uses: actions/checkout@v4
|
|
22
|
+
|
|
23
|
+
- uses: ruby/setup-ruby@v1
|
|
24
|
+
with:
|
|
25
|
+
ruby-version: ${{ matrix.ruby }}
|
|
26
|
+
# Resolves bundler from the gemspec's own '~> 2.0' constraint and
|
|
27
|
+
# caches the installed gems.
|
|
28
|
+
bundler-cache: true
|
|
29
|
+
|
|
30
|
+
- name: Run specs
|
|
31
|
+
# Both formatters are explicit: a CLI --format overrides the one in
|
|
32
|
+
# .rspec, so without this the log would be empty on failure. The JSON
|
|
33
|
+
# file feeds the gate below.
|
|
34
|
+
run: >-
|
|
35
|
+
bundle exec rspec
|
|
36
|
+
--format documentation
|
|
37
|
+
--format json --out rspec-results.json
|
|
38
|
+
|
|
39
|
+
- name: Assert the suite actually executed
|
|
40
|
+
run: ruby .github/scripts/assert_specs_ran.rb rspec-results.json
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
name: PR Title
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
branches: [master, main]
|
|
6
|
+
types: [opened, edited, reopened, synchronize]
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
conventional-title:
|
|
13
|
+
name: Conventional commit title
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
steps:
|
|
16
|
+
# With squash merging the squash commit subject is the PR title, so this
|
|
17
|
+
# string is all release-please ever parses. A title it cannot parse is
|
|
18
|
+
# silently dropped from the release rather than failing anything, so it is
|
|
19
|
+
# gated here instead.
|
|
20
|
+
- uses: amannn/action-semantic-pull-request@v6
|
|
21
|
+
env:
|
|
22
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
23
|
+
with:
|
|
24
|
+
types: |
|
|
25
|
+
feat
|
|
26
|
+
fix
|
|
27
|
+
perf
|
|
28
|
+
revert
|
|
29
|
+
docs
|
|
30
|
+
style
|
|
31
|
+
refactor
|
|
32
|
+
test
|
|
33
|
+
build
|
|
34
|
+
ci
|
|
35
|
+
chore
|
|
36
|
+
deps
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
name: release-please
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [master]
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
contents: write
|
|
9
|
+
pull-requests: write
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
release-please:
|
|
13
|
+
name: Release Please
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
outputs:
|
|
16
|
+
release_created: ${{ steps.release.outputs.release_created }}
|
|
17
|
+
tag_name: ${{ steps.release.outputs.tag_name }}
|
|
18
|
+
steps:
|
|
19
|
+
# Maintains a release PR that bumps VERSION in lib/paubox/version.rb and
|
|
20
|
+
# writes CHANGELOG.md. Merging that PR creates the tag and the GitHub
|
|
21
|
+
# release, which gates the publish job below.
|
|
22
|
+
#
|
|
23
|
+
# The manifest is seeded from RubyGems (0.3.2), not from version.rb, which
|
|
24
|
+
# had drifted to 0.4.0. Neither 0.4.0 nor 0.3.1 was ever pushed, so
|
|
25
|
+
# seeding from the repo would have skipped two unused numbers.
|
|
26
|
+
#
|
|
27
|
+
# include-component-in-tag is false so tags stay bare `vX.Y.Z`, matching
|
|
28
|
+
# the existing v0.3.0 and v0.3.2 and the rest of the SDK fleet.
|
|
29
|
+
- uses: googleapis/release-please-action@v4
|
|
30
|
+
id: release
|
|
31
|
+
with:
|
|
32
|
+
token: ${{ secrets.GITHUB_TOKEN }}
|
|
33
|
+
config-file: release-please-config.json
|
|
34
|
+
manifest-file: .release-please-manifest.json
|
|
35
|
+
|
|
36
|
+
publish:
|
|
37
|
+
name: Publish ${{ needs.release-please.outputs.tag_name }} to RubyGems
|
|
38
|
+
needs: release-please
|
|
39
|
+
if: needs.release-please.outputs.release_created == 'true'
|
|
40
|
+
runs-on: ubuntu-latest
|
|
41
|
+
permissions:
|
|
42
|
+
contents: read
|
|
43
|
+
# Required for OIDC. Without it the credentials step cannot identify
|
|
44
|
+
# itself to RubyGems.org and the push fails.
|
|
45
|
+
id-token: write
|
|
46
|
+
steps:
|
|
47
|
+
- uses: actions/checkout@v4
|
|
48
|
+
with:
|
|
49
|
+
ref: ${{ needs.release-please.outputs.tag_name }}
|
|
50
|
+
# The gemspec builds its file list from `git ls-files`, so the
|
|
51
|
+
# checkout has to keep the repository intact.
|
|
52
|
+
persist-credentials: false
|
|
53
|
+
|
|
54
|
+
- uses: ruby/setup-ruby@v1
|
|
55
|
+
with:
|
|
56
|
+
ruby-version: '3.4'
|
|
57
|
+
bundler-cache: true
|
|
58
|
+
|
|
59
|
+
- name: Run specs
|
|
60
|
+
run: bundle exec rspec --format documentation
|
|
61
|
+
|
|
62
|
+
- name: Verify the tag and version.rb agree
|
|
63
|
+
# Cheap guard against pushing a gem whose version does not match the
|
|
64
|
+
# tag it was cut from. RubyGems only allows a yank within 72 hours and
|
|
65
|
+
# never allows the number to be reused.
|
|
66
|
+
env:
|
|
67
|
+
RELEASE_TAG: ${{ needs.release-please.outputs.tag_name }}
|
|
68
|
+
run: |
|
|
69
|
+
GEM_VERSION=$(ruby -Ilib -e 'require "paubox/version"; print Paubox::VERSION')
|
|
70
|
+
if [ "v${GEM_VERSION}" != "${RELEASE_TAG}" ]; then
|
|
71
|
+
echo "::error::version.rb is ${GEM_VERSION} but the tag is ${RELEASE_TAG}"
|
|
72
|
+
exit 1
|
|
73
|
+
fi
|
|
74
|
+
echo "version.rb ${GEM_VERSION} matches ${RELEASE_TAG}"
|
|
75
|
+
|
|
76
|
+
- name: Build the gem
|
|
77
|
+
run: gem build paubox_ruby.gemspec
|
|
78
|
+
|
|
79
|
+
# Trusted publishing: exchanges GitHub's OIDC token for a short-lived
|
|
80
|
+
# RubyGems credential. There is no API key stored anywhere. RubyGems pins
|
|
81
|
+
# the trust to the repository and this workflow filename, so renaming
|
|
82
|
+
# this file breaks publishing until the trusted publisher entry for the
|
|
83
|
+
# `paubox` gem is updated to match.
|
|
84
|
+
- name: Configure RubyGems credentials
|
|
85
|
+
uses: rubygems/configure-rubygems-credentials@main
|
|
86
|
+
|
|
87
|
+
- name: Push the gem
|
|
88
|
+
run: gem push paubox-*.gem
|
data/.gitignore
CHANGED
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
## [1.0.0](https://github.com/Paubox/paubox-ruby/compare/v0.3.2...v1.0.0) (2026-08-21)
|
|
6
|
+
|
|
7
|
+
First stable release. RubyGems had been on `0.3.2` since October 2022.
|
|
8
|
+
|
|
9
|
+
### β BREAKING CHANGES
|
|
10
|
+
|
|
11
|
+
- Promotes the gem from `0.x` to a stable `1.0.0`. No public API is removed and existing code keeps working, but dependents pinned with a pessimistic `0.x` constraint will not resolve `1.0.0` without widening it. This affects `paubox_rails`, whose gemspec requires `paubox '~> 0.3'`
|
|
12
|
+
|
|
13
|
+
### π New Features
|
|
14
|
+
|
|
15
|
+
- Add `Paubox::FormsClient` for the Paubox Forms API, with `Paubox::Form` and `Paubox::FormSubmission` models
|
|
16
|
+
- Public endpoints, no credential attached: `get_form`, `submit_form`
|
|
17
|
+
- Form management with a scoped API key (`forms` scope, sent as `Authorization: Bearer <key>`): `list_forms`, `find_form`, `create_form`, `update_form`, `archive_form`, `unarchive_form`, `copy_form`, `form_stats`
|
|
18
|
+
- Submissions: `list_submissions`, `submissions_csv`, `submission_pdf`
|
|
19
|
+
- The Email API no longer requires `api_user` β an API key alone authenticates
|
|
20
|
+
|
|
21
|
+
### β οΈ Behavior Changes
|
|
22
|
+
|
|
23
|
+
- Email API base URLs move to `api.paubox.com`. `api_user` is accepted and ignored, and `Paubox::Client#api_user` is kept as a deprecated reader, so existing configuration keeps working
|
|
24
|
+
- The Forms API host is `api.paubox.com`, moved from the earlier `apx.paubox.com/forms`
|
|
25
|
+
|
|
26
|
+
### π Hardening
|
|
27
|
+
|
|
28
|
+
- Validate and encode caller-supplied values interpolated into Forms request paths. Authenticated endpoints require a UUID; public endpoints encode the segment instead of rejecting it
|
|
29
|
+
- Keep the Bearer token out of exception messages raised from Forms requests
|
|
30
|
+
|
|
31
|
+
### π Fixes
|
|
32
|
+
|
|
33
|
+
- Declare `base64` and `ostruct` as runtime dependencies. Both left the Ruby default gems (`base64` in 3.4, `ostruct` in 4.0) and `lib/` requires them, so the gem failed to load on Ruby 3.4 without them ([7299324](https://github.com/Paubox/paubox-ruby/commit/729932436a8982c11f2a71d0d2327265160317d3))
|
|
34
|
+
|
|
35
|
+
### π Enhancements
|
|
36
|
+
|
|
37
|
+
- Replace the dead Travis config with a GitHub Actions CI workflow running RSpec on Ruby 3.1 through 3.4
|
|
38
|
+
|
|
39
|
+
## v0.3.2 / 2022-10-06
|
|
40
|
+
|
|
41
|
+
### π New Features
|
|
42
|
+
|
|
43
|
+
- Add support for sending messages using dynamic templates ([#8](https://github.com/Paubox/paubox-ruby/pull/8))
|
|
44
|
+
|
|
45
|
+
## v0.3.0 / 2019-07-10
|
|
46
|
+
|
|
47
|
+
### π Enhancements
|
|
48
|
+
|
|
49
|
+
- Version bump and dependency maintenance
|
|
50
|
+
|
|
51
|
+
## v0.2.3 / 2018-10-04
|
|
52
|
+
|
|
53
|
+
### π Enhancements
|
|
54
|
+
|
|
55
|
+
- Relax the `mail` dependency to `>= 2.5`
|
|
56
|
+
- Declare a minimum Ruby version of 2.3
|
|
57
|
+
|
|
58
|
+
## v0.1.3 / 2018-04-30
|
|
59
|
+
|
|
60
|
+
### π Enhancements
|
|
61
|
+
|
|
62
|
+
- Relax the `mail` dependency to `>= 2.6`
|
|
63
|
+
|
|
64
|
+
## v0.1.1 / 2018-04-26
|
|
65
|
+
|
|
66
|
+
### π Fixes
|
|
67
|
+
|
|
68
|
+
- Packaging fixes following the initial release
|
|
69
|
+
|
|
70
|
+
## v0.1.0 / 2018-04-17
|
|
71
|
+
|
|
72
|
+
### π Major Release
|
|
73
|
+
|
|
74
|
+
First release of the Paubox Transactional Email SDK for Ruby.
|
data/CLAUDE.md
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# Paubox Ruby Gem β Developer Context
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
|
|
5
|
+
This is the official Ruby gem for the Paubox platform. It provides:
|
|
6
|
+
- **Email API**: send HIPAA-compliant email, manage dynamic templates, check delivery status
|
|
7
|
+
- **Forms API**: fetch form definitions, submit form responses, and manage forms and submissions
|
|
8
|
+
|
|
9
|
+
## Directory Structure
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
lib/
|
|
13
|
+
paubox.rb # Entry point: requires all lib files, holds Configuration
|
|
14
|
+
paubox_ruby.rb # Alias for paubox.rb
|
|
15
|
+
paubox/
|
|
16
|
+
version.rb # Gem version constant
|
|
17
|
+
client.rb # Email API client (authenticated, api.paubox.com)
|
|
18
|
+
forms_client.rb # Forms API client (api.paubox.com/forms; Bearer auth on management endpoints)
|
|
19
|
+
message.rb # Builds send-message API payload from a hash
|
|
20
|
+
templated_message.rb # Extends Message for template-based sends
|
|
21
|
+
mail_to_message.rb # Adapts Ruby Mail::Message to API payload
|
|
22
|
+
dynamic_templates.rb # CRUD for dynamic email templates
|
|
23
|
+
email_disposition.rb # Parses delivery/open status responses
|
|
24
|
+
form.rb # Parses form metadata responses
|
|
25
|
+
form_submission.rb # Parses form submission responses
|
|
26
|
+
format_helper.rb # Shared utilities: base64, key mapping, normalization
|
|
27
|
+
mail/
|
|
28
|
+
paubox.rb # Plugs Paubox into Ruby Mail as a delivery method
|
|
29
|
+
|
|
30
|
+
spec/
|
|
31
|
+
spec_helper.rb # RSpec + WebMock setup
|
|
32
|
+
paubox/ # Unit specs per class
|
|
33
|
+
mail/ # Specs for Ruby Mail integration
|
|
34
|
+
helpers/ # Shared fixtures (MessageHelper, FormHelper, etc.)
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Key Classes
|
|
38
|
+
|
|
39
|
+
| Class | Responsibility |
|
|
40
|
+
|---|---|
|
|
41
|
+
| `Paubox::Client` | Authenticated HTTP client for the Email API. Token auth via `Authorization: Token token=<key>`. Base URL: `https://api.paubox.com/v1`. |
|
|
42
|
+
| `Paubox::FormsClient` | HTTP client for the Forms API. Base URL: `https://api.paubox.com/forms`. Public endpoints (`get_form`, `submit_form`) send no auth headers; management endpoints (list/create/find/update/archive/copy forms, stats, submissions, CSV/PDF export) require a "forms"-scoped API key sent as `Authorization: Bearer <api_key>`. |
|
|
43
|
+
| `Paubox::Message` | Builds the JSON payload for `/messages`. Accepts `from`, `to`, `cc`, `bcc`, `subject`, `text_content`, `html_content`, `attachments`. |
|
|
44
|
+
| `Paubox::TemplatedMessage` | Extends `Message`; overrides `send_message_payload` to include `template_name` / `template_values`. |
|
|
45
|
+
| `Paubox::MailToMessage` | Converts a `Mail::Message` object into a Paubox API payload. |
|
|
46
|
+
| `Paubox::DynamicTemplates` | Manages template CRUD via class methods (`create`, `list`, `find`) and instance methods (`update`, `delete`). |
|
|
47
|
+
| `Paubox::EmailDisposition` | Parses the `/message_receipt` response into `MessageDelivery` and `MessageDeliveryStatus` structs. |
|
|
48
|
+
| `Paubox::Form` | Parses form responses (`/public/form_data/<id>`, `/api/forms` endpoints). Exposes predicate methods: `active?`, `deleted?`, `archived?`, `signable?`. |
|
|
49
|
+
| `Paubox::FormSubmission` | Parses a form submission from `/api/forms/<form_id>/submissions`. Exposes `id`, `form_id`, `form_data` (JSON string parsed to a Hash), `submitter_email`, `recipients`, attachment fields, `created_at`. |
|
|
50
|
+
| `Paubox::FormatHelper` | Mixed into message builders; handles base64 encoding, snake_caseβcamelCase key mapping, email list normalization. |
|
|
51
|
+
| `Mail::Paubox` | Delivery method for the Ruby Mail library. Delegates to `Paubox::Client`. |
|
|
52
|
+
|
|
53
|
+
## Adding a New Feature
|
|
54
|
+
|
|
55
|
+
### New API endpoint on the Email API
|
|
56
|
+
1. Add a method to `Paubox::Client` that calls `send_request` or `RestClient` directly.
|
|
57
|
+
2. If the response needs a structured model, create `lib/paubox/<model>.rb` following `EmailDisposition` as a pattern.
|
|
58
|
+
3. Require the new file in `lib/paubox.rb`.
|
|
59
|
+
4. Add specs in `spec/paubox/<feature>_spec.rb` using WebMock to stub HTTP.
|
|
60
|
+
|
|
61
|
+
### New API endpoint on the Forms API
|
|
62
|
+
1. Add a method to `Paubox::FormsClient`.
|
|
63
|
+
2. If needed, add a response model following `Paubox::Form`.
|
|
64
|
+
3. Require in `lib/paubox.rb`.
|
|
65
|
+
4. Add specs in `spec/paubox/forms_client_spec.rb` or a new file.
|
|
66
|
+
|
|
67
|
+
## Testing
|
|
68
|
+
|
|
69
|
+
**Framework:** RSpec 3 + WebMock
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
bundle exec rspec # run all specs
|
|
73
|
+
bundle exec rspec spec/paubox/form_spec.rb # run a single file
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
WebMock stubs outbound HTTP. All specs must stub any HTTP calls they trigger β no real network requests are made.
|
|
77
|
+
|
|
78
|
+
Fixtures live in `spec/helpers/` as includable modules (e.g. `Helpers::FormHelper`, `Helpers::MessageHelper`). Include them per spec file with `RSpec.configure { |c| c.include Helpers::XHelper }`.
|
|
79
|
+
|
|
80
|
+
## Authentication
|
|
81
|
+
|
|
82
|
+
- **Email API**: `Authorization: Token token=<api_key>` header on every request. The API key alone authenticates β no username/user segment is needed. Configured via `Paubox.configure` or `Paubox::Client.new(api_key:)`. `Configuration` keeps a deprecated `api_user` accessor for backward compatibility; it is ignored.
|
|
83
|
+
- **Forms API**: Public endpoints (`get_form`, `submit_form`) need no auth β `Paubox::FormsClient` sends no auth headers for them. Management endpoints require an API key with the "forms" scope (validated server-side, not by the gem), sent as `Authorization: Bearer <api_key>`. This is a separate key from the Email API key: configure it via `Paubox.configure { |c| c.forms_api_key = ... }` or `Paubox::FormsClient.new(api_key:)` β the client never falls back to `Paubox.configuration.api_key`. Calling a management endpoint without a key raises `ArgumentError`. Note: `list_forms` requires `customer_id` (must match the API key's customer, enforced server-side; the gem raises `ArgumentError` if it is missing).
|
|
84
|
+
|
|
85
|
+
## Dependencies
|
|
86
|
+
|
|
87
|
+
- `rest-client` (~> 2.0) β HTTP client
|
|
88
|
+
- `mail` (>= 2.5) β Ruby Mail integration
|
|
89
|
+
|
|
90
|
+
## Releases
|
|
91
|
+
|
|
92
|
+
Releases are automated with [release-please](https://github.com/googleapis/release-please). Merging to `master` refreshes a standing release PR; merging *that* PR bumps `lib/paubox/version.rb`, writes `CHANGELOG.md`, creates a bare `vX.Y.Z` tag and a GitHub release, and then **pushes the gem to RubyGems**.
|
|
93
|
+
|
|
94
|
+
Do **not** hand-edit `VERSION` or add a `CHANGELOG.md` entry β release-please owns both.
|
|
95
|
+
|
|
96
|
+
The next version comes from PR titles, so the title is the only thing that matters: `feat:` gives a minor bump, `fix:` a patch, and a `!` suffix or a `BREAKING CHANGE:` footer gives a major. `.github/workflows/pr-title.yml` rejects titles release-please cannot parse.
|
|
97
|
+
|
|
98
|
+
To force a specific version, land an empty commit carrying a `Release-As` footer. Put the release notes in that commit's body β a bare `chore: release X` produces an empty changelog entry, because the commits it would otherwise draw from get dropped if they are not conventional:
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
git commit --allow-empty -m "chore: release 1.0.0" -m "Release-As: 1.0.0"
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Publishing
|
|
105
|
+
|
|
106
|
+
Publishing uses RubyGems **trusted publishing** (OIDC) β there is no API key stored anywhere. RubyGems pins the trust to the repository and the workflow filename, so **renaming `release-please.yml` breaks publishing** until the trusted publisher entry for the `paubox` gem is updated to match.
|
|
107
|
+
|
|
108
|
+
If a push fails, re-run the failed `publish` job from the Actions tab. Note that a re-run uses the workflow file from the original commit, so it only helps when the fix is on the RubyGems side; a fix to the workflow itself needs a new release.
|
|
109
|
+
|
|
110
|
+
Version numbers on RubyGems are effectively permanent β a yank is only possible within 72 hours and never frees the number for reuse.
|
|
111
|
+
|
|
112
|
+
### Relationship to `paubox_rails`
|
|
113
|
+
|
|
114
|
+
`paubox_rails` depends on this gem. Its gemspec constraint has to allow whatever major version is current here, so a major bump in `paubox` requires a matching `paubox_rails` release that widens the constraint. Release `paubox` first.
|