crawlscope 0.8.0 → 0.9.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4b830667c3f7647baba6ca372e78daa5f4116e2178fc585aff4f387671e71b81
4
- data.tar.gz: 357a5ceab12f86addda14927ba03be7357f20d301ddeb58b72a87527133653ce
3
+ metadata.gz: 94c540760a23969d9abd10c27866c6c14a7caf520a261e2f6a213ffabe5440de
4
+ data.tar.gz: f1caacfe42dc2e4cb398d1732b1a265761c0aabffc951647a93972479501835d
5
5
  SHA512:
6
- metadata.gz: 954a7f1044ae369e01fc571331acbf0b9ebd47f56d8047d028c6967a85cf5caefa673a3bfa05b782a814d3233f883ea13ca98a3ab961d2e8de47d788804f6158
7
- data.tar.gz: 8a59e970c7191847a25b855e7342d0ebaab7b881540d41ac78b9b558460ffd9a679fbfff3c54ef78e22f2bd287d8009f9d58961128b9c4b74ac3773ce8dc82dd
6
+ metadata.gz: e24e81f82b40938cb48182aef3657b3d49a273269900a5d47edeccd35f34081293044b1f9e0fb7e5bd6fbad26d18b0ec0f897b21b2935031d0601b081f1c0f2b
7
+ data.tar.gz: af73839632a975bc34145dbb821a02d953175cd5d6fa7c0af419ba7f488e02d043a946aeea8c338de1e338bc6864744a3a6ac23bbcaed6fa3ecf708ff2a4005c
data/CHANGELOG.md CHANGED
@@ -5,6 +5,32 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.9.0] - 2026-11-04
9
+
10
+ ### Changed
11
+
12
+ - Require Ruby 4.0 or newer.
13
+ - Use published Gemkit 0.1.0 for shared verification and release PRs, with workflow callers pinned to the same release commit.
14
+
15
+ ### Added
16
+
17
+ - Support optional host-installed Rails 8 (`>= 8.0`, `< 9`), including explicit `crawlscope/rails` loading after the core.
18
+ - Reuse all packaged audit tasks in the repository, including indexability and content-quality checks.
19
+
20
+ ### Removed
21
+
22
+ - Remove Railties as a runtime dependency so the Ruby library and CLI work without Rails.
23
+ - Replace local tagging and hook bypasses with reviewed release PRs published by GitHub Actions.
24
+
25
+ ## [0.8.1] - 2026-10-06
26
+
27
+
28
+ ### Fixed
29
+
30
+ - clarify findings and prevent redirect false positives
31
+
32
+
33
+
8
34
  ## [0.8.0] - 2026-07-24
9
35
 
10
36
 
data/README.md CHANGED
@@ -32,7 +32,8 @@ The default rule set includes:
32
32
 
33
33
  ## Installation
34
34
 
35
- Crawlscope requires Ruby 3.3 or newer.
35
+ Crawlscope requires Ruby 4.0 or newer. Rails is optional; the CLI and Ruby
36
+ library run without it. Rails integration requires host-installed Rails 8.
36
37
 
37
38
  Add this line to your application's Gemfile:
38
39
 
@@ -106,21 +107,32 @@ Base URL: https://example.com
106
107
  Sitemap: https://example.com/sitemap.xml
107
108
  URLs: 24
108
109
  Pages: 24
109
- Status: FAILED
110
- Issues: 3 3 warnings
110
+ Status: WARNINGS
111
+ Issues: 3 total (3 warnings)
111
112
 
112
- Summary:
113
- links 2
114
- metadata 1
113
+ Links: Too few incoming links without nofollow (2 warnings)
114
+ - /pricing incoming links without nofollow: 1; minimum 2
115
+ linked from: /
116
+ - /features incoming links without nofollow: 1; minimum 2
117
+ linked from: /
115
118
 
116
- links / low_dofollow_inlinks: 2
117
- - /pricing inbound 1/2 sources: /
118
- - /features inbound 1/2 sources: /
119
-
120
- metadata / missing_title: 1
119
+ Metadata: Missing title (1 warning)
121
120
  - /draft missing <title>
122
121
  ```
123
122
 
123
+ Reports include all issues and related URLs. Errors appear before warnings and
124
+ notices. Each related URL has a label, such as `linked from`, `links to`, or
125
+ `page`. JSON-LD errors appear below the page URL with the type, field, and
126
+ constraint. Same-origin URLs use paths; other URLs retain their scheme and host.
127
+ For automation in Ruby, use `result.issues` and each issue's `code`, `severity`,
128
+ `url`, and `details` rather than matching the report text.
129
+
130
+ Metadata length limits appear in the group heading; each row shows the measured
131
+ length. The default maximums are 160 characters for a meta description and 110
132
+ characters for an Article JSON-LD `headline`. These are separate Crawlscope
133
+ validation limits for separate fields. Server timing lists pages only when the
134
+ reported duration exceeds 50 ms; aggregate statistics include all responses.
135
+
124
136
  ## Ruby Usage
125
137
 
126
138
  ```ruby
@@ -211,6 +223,10 @@ metric names and reports each metric independently.
211
223
 
212
224
  ## Rails Usage
213
225
 
226
+ Install Rails 8 in the host application; Crawlscope does not install Railties.
227
+ For a process that loads Crawlscope before Rails, require `crawlscope/rails`
228
+ after Rails is available. The Ruby and CLI entry points remain independent of Rails.
229
+
214
230
  Run the install generator after adding the gem:
215
231
 
216
232
  ```bash
@@ -421,68 +437,92 @@ That makes `crawlscope` useful as the audit engine while the app remains the own
421
437
 
422
438
  ## Development
423
439
 
424
- ```bash
440
+ Shared development tooling comes from published `ethos-gemkit` 0.1.0. The Gemfile
441
+ and workflow callers use the same release: the gem version is exact, and Actions
442
+ references pin its full commit SHA.
443
+
444
+ ```sh
425
445
  git clone https://github.com/ethos-link/crawlscope.git
426
446
  cd crawlscope
427
-
428
447
  bundle install
429
- bundle exec rake test
430
- bundle exec rake standard
431
- bundle exec rake
448
+ bundle exec lefthook install
449
+ bundle exec rake verify
432
450
  ```
433
451
 
434
- ### Git hooks
452
+ `rake verify` runs Standard, all Minitest tests, package validation and a git-cliff
453
+ smoke check. `rake` runs the same checks. Individual `rake test` and `rake standard`
454
+ tasks remain available, along with the `crawlscope:*` audit tasks above.
435
455
 
436
- We use [lefthook](https://lefthook.dev/) with the Ruby
437
- [commitlint](https://github.com/arandilopez/commitlint) gem to enforce
438
- Conventional Commits on every commit. We also use
439
- [Standard Ruby](https://standardrb.com/) to keep code style consistent. CI
440
- validates commit messages, Standard Ruby, tests, and git-cliff changelog
441
- generation on pull requests and pushes to main/master.
456
+ Hooks use Gemkit to block direct commits to main/master and validate Conventional
457
+ Commits. CI uses the same lint, test, package, changelog and commit checks.
458
+ GitLab sync has no caller because no target URL is configured.
442
459
 
443
- Run the hook installer once per clone:
460
+ To install a development build locally, run `bundle exec rake install`.
444
461
 
445
- ```bash
446
- bundle exec lefthook install
447
- ```
462
+ ## Release
448
463
 
449
- ### Install locally
464
+ Use `release:prepare` from clean, up-to-date `main`. It creates a conventional
465
+ release branch and review PR. **Merging the release PR starts publication through
466
+ GitHub Actions**; ordinary development PRs run verification only.
450
467
 
451
- ```bash
452
- rake install
453
- ```
468
+ ### RubyGems setup
454
469
 
455
- ## Release
470
+ Configure **crawlscope → Trusted publishers** on RubyGems with these values:
456
471
 
457
- Releases are tag-driven and published by GitHub Actions to RubyGems.
458
- Local release commands never publish directly.
472
+ | RubyGems field | Value |
473
+ |---|---|
474
+ | Repository owner | `ethos-link` |
475
+ | Repository name | `crawlscope` |
476
+ | Workflow filename | `release.yml` |
477
+ | Environment | `rubygems` |
478
+ | Workflow Repository Owner | `ethos-link` |
479
+ | Workflow Repository Name | `ethos-gemkit` |
459
480
 
460
- Install [git-cliff](https://git-cliff.org/) locally before preparing a
461
- release. The release task prepends the next `CHANGELOG.md` section from
462
- Conventional Commits.
481
+ The Workflow Repository fields are required because the publishing workflow lives
482
+ in Gemkit. Gemkit's own publisher does not authorize Crawlscope. The account ID
483
+ passed by the caller does not create publisher authorization.
463
484
 
464
- Before preparing a release, make sure you are on `main` or `master` with a
465
- clean worktree. If the release contains a breaking public-contract change,
466
- update `UPGRADE.md` with the host-app migration steps first.
485
+ Install Git, git-cliff and GitHub CLI, authenticate with `gh auth login`, and
486
+ install hooks as shown above. The `rubygems` GitHub environment must allow main
487
+ and version tags; repository rules must permit the workflow's annotated tags.
467
488
 
468
- Then run one of:
489
+ ### Prepare and publish
469
490
 
470
- ```bash
491
+ Update `UPGRADE.md` with host-app migration steps for contract changes before
492
+ preparing a release. Then run:
493
+
494
+ ```sh
495
+ git switch main
496
+ git pull --ff-only
497
+ bundle install
471
498
  bundle exec rake 'release:prepare[patch]'
472
- bundle exec rake 'release:prepare[minor]'
473
- bundle exec rake 'release:prepare[major]'
474
- bundle exec rake 'release:prepare[0.1.0]'
475
499
  ```
476
500
 
477
- The task will:
501
+ The default target is `patch`; `minor`, `major` and explicit versions are also
502
+ supported. The task updates the version, changelog and lockfile, verifies the gem,
503
+ commits with hooks enabled, pushes `chore/release-vX.Y.Z` and opens a release PR.
504
+ Review its metadata and notes, and wait for CI before merging.
505
+
506
+ The workflow verifies and builds the exact release merge commit, creates an
507
+ annotated tag, publishes the same artifact and creates GitHub release notes.
508
+ No local publication or manual tag step is needed. Existing manually pushed
509
+ annotated version tags remain supported.
510
+
511
+ ### Failed publication
478
512
 
479
- 1. Prepend the next `CHANGELOG.md` section with `git-cliff`.
480
- 1. Update `lib/crawlscope/version.rb`.
481
- 1. Commit the release changes.
482
- 1. Create and push the `vX.Y.Z` tag.
513
+ If credential setup reports `No trusted publisher configured for this workflow`
514
+ and `gem push` was skipped, correct the publisher fields above and rerun only
515
+ failed jobs in the original run:
516
+
517
+ ```sh
518
+ gh run rerun RUN_ID --repo ethos-link/crawlscope --failed
519
+ ```
483
520
 
484
- The `Release` workflow then runs tests, publishes the gem to RubyGems,
485
- and creates the GitHub release from the changelog entry.
521
+ The existing verified artifact and tag are reused. Do not run `release:prepare`
522
+ again, bump the version or replace the tag to recover from that authentication
523
+ failure. Failed release notes also use a failed-jobs retry without republishing.
524
+ For uploads with uncertain results, already-published versions or expired
525
+ artifacts, follow the [Gemkit recovery guide](https://github.com/ethos-link/ethos-gemkit#failures-and-retries).
486
526
 
487
527
  ## Contributing
488
528
 
data/UPGRADE.md ADDED
@@ -0,0 +1,138 @@
1
+ # Upgrade Guide
2
+
3
+ Use this file for host-app migration notes when a release changes public
4
+ contracts, required setup, component locals, generated assets, or runtime
5
+ behavior.
6
+
7
+ ## 0.9.0
8
+
9
+ ### Ruby 4 and optional Rails 8
10
+
11
+ Upgrade Ruby to 4.0 or newer before updating Crawlscope. Rails integrations now
12
+ require Rails 8 (`>= 8.0`, `< 9`). Upgrade the host Rails application when using
13
+ the generator or Railtie; plain Ruby and CLI callers do not need Rails.
14
+
15
+ Railties is no longer a runtime dependency. Rails applications must declare
16
+ Rails or Railties themselves. If Crawlscope loads before Rails, explicitly
17
+ require `crawlscope/rails` after the framework is available. Existing generated
18
+ initializers and `require "crawlscope/tasks"` loaders remain supported.
19
+
20
+ ### Release preparation
21
+
22
+ Development uses published Gemkit 0.1.0. Install the bundle and hooks with
23
+ `bundle install` and `bundle exec lefthook install`.
24
+ Run `release:prepare` from current main to open a verified release PR; merging
25
+ that PR triggers workflow publication. Local preparation no longer tags, pushes
26
+ main or bypasses hooks. Configure Crawlscope's RubyGems publisher as documented
27
+ in the README; the shared workflow does not inherit another gem's permission.
28
+
29
+ ## Next Release
30
+
31
+ ### Structured-data length errors include the measured size
32
+
33
+ String-length schema errors now include an optional `length` field with the
34
+ actual character count. Text reports show the measurement and limit, such as
35
+ `Article.headline: 125 characters; maximum 110`. Existing `field`, `issue`, and
36
+ `type` fields remain available, and `issue` retains the original validator
37
+ message. Applications that enforce exact error-object keys must accept `length`.
38
+
39
+ ### One warning per redirect or canonical mismatch
40
+
41
+ Sitemap redirects now emit only `sitemap_redirect_url`, rather than also emitting
42
+ `redirected_page`. Applications that match `redirected_page` must switch to
43
+ `sitemap_redirect_url`; `final_url` and final HTTP `status` remain in details.
44
+
45
+ Metadata and canonical-target checks skip redirect aliases, so the destination's
46
+ canonical is not compared with the redirect's original URL. Metadata checks still
47
+ run when the destination is itself in the crawl.
48
+
49
+ A directly served page with a different canonical emits one warning:
50
+ `non_canonical_page_in_sitemap` when it is in the sitemap, or `canonical_mismatch`
51
+ otherwise. Applications that previously counted both warnings should handle
52
+ either code as one mismatch.
53
+
54
+ Metadata length reports put the field and limit in the group heading; rows show
55
+ only the measured length. Server timing's page list now includes only durations
56
+ strictly greater than 50 ms. Aggregate timing statistics still include all
57
+ responses, and `result.server_timing_summary` retains all timing data.
58
+
59
+ ### Redirect URLs are excluded from uniqueness checks
60
+
61
+ Uniqueness checks now compare only HTML pages whose normalized requested and
62
+ final URLs match. Redirect aliases no longer produce duplicate-title,
63
+ duplicate-description, duplicate-text, or similar-text warnings from the
64
+ destination's content. Redirect issues remain in the crawl report. Separate
65
+ pages that serve identical content without a redirect are still checked.
66
+
67
+ No host-app configuration changes are required. Applications that count
68
+ uniqueness issues should expect fewer warnings when sitemap URLs redirect.
69
+
70
+ ### Clearer audit messages
71
+
72
+ Text reports now use plain-language group headings with severity counts and
73
+ show errors before warnings and notices. The repeated category summary is
74
+ removed. Structured-data errors show the type, field, and constraint on separate
75
+ lines (for example, `Article.headline: 125 characters; maximum 110`). Sitemap
76
+ redirects show the destination and its final HTTP status once, without the host
77
+ for same-origin URLs.
78
+ Canonical warnings now identify the canonical target and explain the mismatch.
79
+ Link warnings use `linked from` and `links to` to identify each URL's role.
80
+ Length and ratio warnings include the limit and units. Reports show every issue
81
+ and every related URL on separate lines. Duplicate-title and description values
82
+ are shown in full. Link rules retain all source and target URLs rather than
83
+ three samples. Missing-sitemap issues keep `source_url` and also provide
84
+ `source_urls` with all pages that link to the missing URL. Server timing retains
85
+ full descriptions and lists every page whose duration exceeds 50 ms.
86
+
87
+ Host applications that parse report text or issue messages must update their
88
+ matching patterns. Prefer issue codes and structured `details` for automation;
89
+ these retain their existing fields, including the original schema errors,
90
+ redirect status and final URL, and canonical href. No configuration changes are
91
+ required.
92
+
93
+ The former report limits `Reporter::MAX_ISSUES_PER_GROUP` and
94
+ `Rules::Links::MAX_SOURCES_IN_ERROR` are removed. Host applications that reference
95
+ these constants must remove those references.
96
+
97
+ ### Default sitemap is fetched over HTTP
98
+
99
+ Crawlscope no longer prefers `public/sitemap.xml` when validating a localhost
100
+ application. Without an explicit `SITEMAP` or configured `sitemap_path`, it now
101
+ fetches `/sitemap.xml` from the configured base URL so the crawl observes the
102
+ live application and database state.
103
+
104
+ The Rails installer now generates the same HTTP default. Regenerate or update
105
+ existing initializers that use `Rails.public_path.join("sitemap.xml")`.
106
+ Explicit local sitemap paths remain supported through `SITEMAP`, `--sitemap`,
107
+ or `config.sitemap_path`.
108
+
109
+ `CRAWLSCOPE_PROFILE_TOKEN` is now the portable default for standalone CLI, Rake,
110
+ Rails, and plain Ruby usage. Explicit `config.profile_token` values still take
111
+ precedence.
112
+
113
+ ### Server-Timing report output
114
+
115
+ No host configuration is required. When one or more responses publish a
116
+ `Server-Timing` header, the text report now includes an optional `Server Timing`
117
+ section. Host applications that parse report text should accept this additional
118
+ section.
119
+
120
+ Parsed metrics are available through `page.server_timing`, and aggregate data is
121
+ available through `result.server_timing_summary`. Crawlscope interprets `dur`
122
+ values as milliseconds and ignores malformed entries while reporting their
123
+ count.
124
+
125
+ ### Ruby 3.3 is now required
126
+
127
+ Crawlscope now depends on the current Async runtime for production async HTTP
128
+ fetching. Host applications must run Ruby 3.3 or newer before upgrading.
129
+
130
+ Recommended migration:
131
+
132
+ 1. Upgrade the host application runtime to Ruby 3.3 or newer.
133
+ 2. Run `bundle update crawlscope async async-http async-http-faraday`.
134
+ 3. Crawlscope now uses `FETCH_EXECUTOR=async` by default for HTTP crawling.
135
+ 4. Set `FETCH_EXECUTOR=threaded` or pass `--fetch-executor threaded` for a
136
+ conservative rollout or for explicit thread-pool execution.
137
+ 5. Browser rendering continues to use threaded execution by default because
138
+ async fetch execution is only supported with HTTP rendering.
@@ -114,7 +114,6 @@ module Crawlscope
114
114
  elsif !@allowed_statuses.include?(page.status)
115
115
  issues.add(code: :unexpected_status, severity: :error, category: :crawl, url: page.url, message: "HTTP #{page.status}", details: {status: page.status})
116
116
  elsif redirected?(page)
117
- issues.add(code: :redirected_page, severity: :warning, category: :crawl, url: page.url, message: "redirects to #{page.final_url}", details: {final_url: page.final_url, status: page.status})
118
117
  issues.add(code: :sitemap_redirect_url, severity: :warning, category: :sitemaps, url: page.url, message: "sitemap URL redirects to #{page.final_url}", details: {final_url: page.final_url, status: page.status})
119
118
  end
120
119
  end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails"
4
+ require "rails/railtie"
5
+ require "crawlscope"
6
+ require "crawlscope/railtie"
@@ -1,5 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "rails"
4
+ require "rails/railtie"
5
+
6
+ unless Gem::Requirement.new(">= 8.0", "< 9").satisfied_by?(Gem.loaded_specs.fetch("railties").version)
7
+ raise LoadError, "crawlscope integration requires Rails 8.0 or newer within Rails 8"
8
+ end
9
+
3
10
  module Crawlscope
4
11
  class Railtie < Rails::Railtie
5
12
  rake_tasks do