Skip to content

Commit effed8f

Browse files
committed
Merge branch 'main' into comms-steps
2 parents a8131d6 + 73cb104 commit effed8f

40 files changed

Lines changed: 721 additions & 173 deletions

‎.github/workflows/release.yml‎

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -77,9 +77,20 @@ jobs:
7777
exit 1
7878
fi
7979
80+
# A release's loader must load its own packages (decision 158).
81+
if [ "$publish" = "true" ]; then
82+
node release/check-minimum-loader.js --version "$version"
83+
fi
84+
8085
prerelease=false
8186
[[ "$version" == *-* ]] && prerelease=true
82-
releases=$(jq -c '[.releases[] | { version, ref }]' release/rock-releases.json)
87+
88+
# One Rock release per major release, whose packages go under rock-{major} (decision 52).
89+
releases=$(jq -c '[.releases[] | { version, ref, major: (.version | split(".")[0] | tonumber) }]' release/rock-releases.json)
90+
if [ "$(jq '[.[].major] | length != (unique | length)' <<< "$releases")" = "true" ]; then
91+
echo "::error::release/rock-releases.json lists two Rock releases for one major release."
92+
exit 1
93+
fi
8394
{
8495
echo "version=$version"
8596
echo "publish=$publish"
@@ -101,6 +112,7 @@ jobs:
101112
rock: ${{ fromJSON(needs.plan.outputs.releases) }}
102113
env:
103114
ROCK_VERSION: ${{ matrix.rock.version }}
115+
ROCK_MAJOR: ${{ matrix.rock.major }}
104116
ROCK_REF: ${{ matrix.rock.ref }}
105117
steps:
106118
- uses: actions/checkout@v4
@@ -187,20 +199,21 @@ jobs:
187199
- name: Check SQL Server sign-in
188200
run: sqlcmd -S localhost -E -C -Q "SELECT @@VERSION, SUSER_SNAME() AS [Login], IS_SRVROLEMEMBER('sysadmin') AS [IsSysAdmin];"
189201

202+
# Each package serves every dot release of its major, so it is written and published under rock-{major}.
190203
- name: Write the packages
191-
run: dotnet run --project builder -c Release -- --rock "$env:ROCK_PATH" --out "packages/rock-$env:ROCK_VERSION"
204+
run: dotnet run --project builder -c Release -- --rock "$env:ROCK_PATH" --out "packages/rock-$env:ROCK_MAJOR"
192205

193206
- name: Verify the packages
194-
run: dotnet run --project verify -c Release -- --rock "$env:ROCK_PATH" --packages "packages/rock-$env:ROCK_VERSION" --run ci
207+
run: dotnet run --project verify -c Release -- --rock "$env:ROCK_PATH" --packages "packages/rock-$env:ROCK_MAJOR" --run ci
195208

196209
- name: Publishing gate
197-
run: dotnet run --project verify -c Release --no-build -- --check-receipts "packages/rock-$env:ROCK_VERSION"
210+
run: dotnet run --project verify -c Release --no-build -- --check-receipts "packages/rock-$env:ROCK_MAJOR"
198211

199212
- uses: actions/upload-artifact@v4
200213
if: always()
201214
with:
202-
name: rock-${{ matrix.rock.version }}
203-
path: packages/rock-${{ matrix.rock.version }}
215+
name: rock-${{ matrix.rock.major }}
216+
path: packages/rock-${{ matrix.rock.major }}
204217
if-no-files-found: warn
205218
retention-days: 14
206219

‎README.md‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ and push. Ask me before anything that removes or rewrites history.
151151
- **Every campus has businesses** that give, each with one or two contacts. The main campus has at least 6 and every other campus at least 2.
152152
- **Dates are generated at install**, counted back from install day, so "last 12 months" reports are always full.
153153
- **Realism is measured.** The same scripts that measure real churches grade our data. Today 91% of measured values fall within tolerance, including serving, connections, and prayer.
154-
- **Correctness is proven against Rock itself.** Before a package is published, the verify tool loads it into a clean copy of its exact Rock release, checks it against Rock's schema, runs rule checks, and has Rock's own Rock Cleanup job look for anything to fix. See [Verification](docs/verification.md).
154+
- **Correctness is proven against Rock itself.** Before a package is published, the verify tool loads it into a clean copy of the Rock release it is built on, checks it against Rock's schema, runs rule checks, and has Rock's own Rock Cleanup job look for anything to fix. See [Verification](docs/verification.md).
155155
- **People have notes** in six note types, secured to staff. Cast notes are hand-written and tied to each family's story, and they show more and better note use than most churches have today.
156156
- **A building campaign is under way.** Built on the Rock is about 38% through on install day, with pledges from people and businesses in every state Pledge Analytics can show.
157157
- **Giving analytics work on install.** Giving attributes, journey stages, and a year of giving alerts are filled in the way Rock computes them, and a version guard catches Rock changing that math.
@@ -171,7 +171,7 @@ and push. Ask me before anything that removes or rewrites history.
171171
| [builder/](builder/README.md) | The .NET tool that turns this repository into one dataset package per dataset. |
172172
| [loader/](loader/README.md), `loader-cli/`, `loader-compat-check/` | The loader library that installs a package into a Rock database (for .NET 10 and for Rock's .NET Framework, as the `SparkDevNetwork.Rock.SampleData.Loader` NuGet package), its command line for developers and test harnesses, and the check that both builds compute the same keys. |
173173
| [validation/](validation/README.md) | Tolerances and the script that grades generated data, plus the invariants, contract, and standards check the verify tool uses. |
174-
| [verify/](verify/README.md) | The tool that proves each package works on one exact Rock and writes its receipt. Publishing needs a passing receipt. |
174+
| [verify/](verify/README.md) | The tool that proves each package works on the Rock it is built on and writes its receipt. Publishing needs a passing receipt. |
175175
| [release/](release/README.md) | The Rock releases each release builds for, and the script that merges a release into the hosted package index. `.github/workflows/release.yml` publishes the packages and the loader on a version tag. How to release, what has shipped, and how to fix a failed run: [Publishing a release](docs/maintaining.md#publishing-a-release). |
176176
| [datasets/](datasets/README.md) | One manifest per dataset, with its settings. |
177177
| [content/](content/README.md) | Fonts for check images, and later the text pools. |
@@ -194,11 +194,11 @@ You need the .NET 10 SDK, Node.js 20 or later, and SQL Server with a freshly ins
194194
dotnet run -- --rock C:\Development\Rock
195195
```
196196

197-
3. Load Core 1 into a fresh Rock database. Add `--dry-run` to roll everything back at the end. If your database is on a different migration than the checkout, add `--any-rock`.
197+
3. Load Core 1 into a fresh Rock database. `--rock` names your built Rock checkout, so the loader can read its version from `RockWeb\bin\Rock.Version.dll`. Add `--dry-run` to roll everything back at the end. If your database is on another Rock major release than the checkout, add `--any-rock`.
198198

199199
```
200200
cd ../loader-cli
201-
dotnet run -- --package ../packages/core-1.zip --connection "Server=localhost;Database=RockSample;Integrated Security=true;TrustServerCertificate=true"
201+
dotnet run -- --package ../packages/core-1.zip --rock C:\Development\Rock --connection "Server=localhost;Database=RockSample;Integrated Security=true;TrustServerCertificate=true"
202202
```
203203

204204
4. Grade the result against the profile. See [Validation](validation/README.md) for the three commands.

‎builder/PackageWriter.cs‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,8 +144,9 @@ void AddFolder( string folder, string extension = null )
144144
files["README.md"] = Normalize( "README.md", Utf8( repository.ReadText( "builder/package-readme.md" )
145145
.Replace( "{{name}}", datasetManifest.Name )
146146
.Replace( "{{dataset}}", dataset )
147+
.Replace( "{{rockMajor}}", rock?.Major.ToString() ?? "(unknown)" )
147148
.Replace( "{{rockVersion}}", rock?.Version ?? "(unknown)" )
148-
.Replace( "{{rockMigration}}", rock?.Migration ?? "(unknown)" ) ) );
149+
.Replace( "{{minimumLoaderVersion}}", SampleDataPackage.MinimumLoaderVersion ) ) );
149150

150151
var manifest = new PackageManifest
151152
{
@@ -154,7 +155,8 @@ void AddFolder( string folder, string extension = null )
154155
Name = datasetManifest.Name,
155156
Profile = profileName,
156157
Source = ReadSource( root ),
157-
Rock = rock
158+
Rock = rock,
159+
MinimumLoaderVersion = SampleDataPackage.MinimumLoaderVersion
158160
};
159161
foreach ( var (path, bytes) in files )
160162
{

‎builder/Program.cs‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,9 @@ dotnet run -- --deliver-photos <batch.json> [--root <repository folder>]
6262
}
6363
}
6464

65-
// Otherwise, write packages. Every package is for one exact Rock: the version and newest migration
66-
// come from a Rock checkout (--rock, or ROCK_PATH), or are given directly.
65+
// Otherwise, write packages. Every package is for one Rock major release (decision 52): the version,
66+
// whose first number is the major, and the newest migration come from a Rock checkout (--rock, or
67+
// ROCK_PATH), or are given directly.
6768
try
6869
{
6970
var rock = RockCheckout.Read(

‎builder/README.md‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,12 @@ From the `builder` folder:
1010
dotnet run -- --rock C:\Development\Rock
1111
```
1212

13-
That writes every dataset's package to `../packages/` (git ignores it). Each package is for the Rock in the checkout you name.
13+
That writes every dataset's package to `../packages/` (git ignores it). Each package is for the major release of the Rock in the checkout you name, such as Rock 21, and serves every dot release of it (decision 52).
1414

1515
| Option | Meaning |
1616
|---|---|
17-
| `--rock <folder>` | A Rock checkout. The package records its version (from `Directory.Build.props`) and its newest migration (from `Rock.Migrations/Migrations`). The `ROCK_PATH` environment variable does the same. Required unless both values below are given. |
18-
| `--rock-version` | The Rock version, for example `21.0.1`. Wins over the checkout's. |
17+
| `--rock <folder>` | A Rock checkout. The package records its version (from `Directory.Build.props`), whose first number is the major release, and its newest migration (from `Rock.Migrations/Migrations`). The `ROCK_PATH` environment variable does the same. Required unless both values below are given. |
18+
| `--rock-version` | The Rock version, for example `21.0.2`. Its first number is the package's major release. Wins over the checkout's. |
1919
| `--rock-migration` | The newest migration Id, for example `202609222138362_AddWorkflowBuilder`. Wins over the checkout's. |
2020
| `--dataset` | One dataset (`core-1`, `core-3`, or `full-7`), or `all` (the default). |
2121
| `--out <folder>` | Where to write packages. Defaults to `../packages`. |
@@ -28,7 +28,7 @@ A package is a zip of data, never SQL (decision 41). Files keep their paths from
2828

2929
| Path | What it holds |
3030
|---|---|
31-
| `package.json` | The format version, the dataset, the source commit, the one Rock it is for (decision 52), and the SHA-256 of every other file. |
31+
| `package.json` | The format version, the dataset, the source commit, the Rock major release it is for and the exact Rock it was built on (decision 52), the oldest loader that can load it (decision 158), and the SHA-256 of every other file. |
3232
| `configuration/*.json` | The church setup, unchanged. |
3333
| `cast/households/*.json`, `cast/groups/*.json` | The Cast and its small group plans, unchanged. |
3434
| `datasets/{key}.json` | The dataset's settings and its [card](../datasets/README.md#the-dataset-card). |

‎builder/RockCheckout.cs‎

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,15 @@
1818
using System.Text.RegularExpressions;
1919
using System.Xml.Linq;
2020

21+
using RockSampleData.Loader;
2122
using RockSampleData.Loader.Packages;
2223

2324
namespace RockSampleData.Builder
2425
{
2526
/// <summary>
26-
/// Reads which Rock a package is for from a Rock checkout: the version in Directory.Build.props
27-
/// and the newest Entity Framework migration in Rock.Migrations.
27+
/// Reads which Rock a package is for from a Rock checkout: the version in Directory.Build.props,
28+
/// whose first number is the major release the package serves (decision 52), and the
29+
/// newest Entity Framework migration in Rock.Migrations.
2830
/// </summary>
2931
internal static class RockCheckout
3032
{
@@ -47,7 +49,9 @@ public static PackageRock Read( string checkoutPath, string version, string migr
4749
throw new InvalidOperationException( "A package must say which Rock it is for. Pass --rock <Rock checkout> (or set ROCK_PATH), or both --rock-version and --rock-migration." );
4850
}
4951

50-
return new PackageRock { Version = version, Migration = migration };
52+
var major = RockVersionInfo.MajorOf( version )
53+
?? throw new InvalidOperationException( $"The Rock version {version} does not start with a major release number, such as 21 in 21.0.2." );
54+
return new PackageRock { Major = major, Version = version, Migration = migration };
5155
}
5256

5357
/// <summary>

‎builder/package-readme.md‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# {{name}} sample data package
22

3-
This package installs the **{{name}}** dataset (`{{dataset}}`) of Rock Sample Data into a fresh Rock database. It is for Rock {{rockVersion}} (newest migration `{{rockMigration}}`). The loader refuses any other Rock.
3+
This package installs the **{{name}}** dataset (`{{dataset}}`) of Rock Sample Data into a fresh Rock database. It is for every Rock {{rockMajor}} release, and was verified on Rock {{rockVersion}}. The loader refuses any other major release of Rock. It needs loader {{minimumLoaderVersion}} or newer.
44

55
All the people, families, and organizations in it are fictional.
66

@@ -17,7 +17,7 @@ The package holds the inputs, not the records. It has no attendance rows, gifts,
1717
| `addresses/pool.json` | Real-street addresses with house numbers that do not exist |
1818
| `photos/` | Profile photos, and a photo of each Cast small group |
1919
| `content/fonts/` | Fonts for the scanned check images, with their licenses |
20-
| `package.json` | The format version, the Rock this package is for, and a SHA-256 for every file |
20+
| `package.json` | The format version, the Rock major release this package is for, the oldest loader that can load it, and a SHA-256 for every file |
2121
| `LICENSE.md` | The license for this data |
2222

2323
## What the loader makes from it
@@ -52,7 +52,7 @@ The loader library (`RockSampleData.Loader`) and its command line both install p
5252
rock-sample-data-load --package {{dataset}}.zip --connection "<connection string>" [--anchor yyyy-MM-dd] [--seed text]
5353
```
5454

55-
Before it writes anything, the loader checks the format version, every file's SHA-256, that the database has no people beyond a new Rock install, and that it is Rock {{rockVersion}}. The load runs in one transaction, so a failure leaves nothing behind. Every row it writes carries `ForeignKey = SampleData:{{dataset}}`.
55+
Before it writes anything, the loader checks the format version, that it is loader {{minimumLoaderVersion}} or newer, every file's SHA-256, that the database has no people beyond a new Rock install, and that its Rock is a Rock {{rockMajor}} release. It reads Rock's version from `Rock.Version.dll`. The load runs in one transaction, so a failure leaves nothing behind. Every row it writes carries `ForeignKey = SampleData:{{dataset}}`.
5656

5757
## More
5858

‎calibration/profiles/sample-church.json‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
{ "path": "communicationDetail.unsubscribesYear.perThousandMassRecipients.Recipient preference", "reason": "Too few unsubscribes to use." }
4949
],
5050
"overrides": [
51+
{ "path": "people.ageMix", "value": { "00-05": 3.94, "06-11": 9.61, "12-17": 18.64, "18-24": 18.51, "25-34": 15.27, "35-44": 15.72, "45-54": 9.37, "55-64": 5.35, "65-74": 2.9, "75+": 0.78 }, "reason": "Assumption. The measured age mix counts only people with a birth date, and 17.9% of measured people have none (people.pctNoBirthDate), but every sample person has one (decision 156). These are the measured shares restated as shares of all people, assuming the people with no birth date are adults spread like the adults who have one: each child band is the measured share times 0.821, and each adult band the measured share times 1.115. Every band keeps its measured ratio to the others in its group, so the generator, which reads these shares as weights, draws almost exactly the same ages as before." },
5152
{ "path": "groups.smallGroups.pctDidAttend", "value": 65, "reason": "Design choice. Small group attendance sits between the measured rate and a livelier demo church (docs/small-groups.md)." },
5253
{ "path": "groups.smallGroups.weightedMedianSize", "value": 12, "reason": "Design choice. Small groups have about 12 members (decision 33)." },
5354
{ "path": "groups.smallGroups.pctLeaders", "value": 8.3, "reason": "Design choice. Each small group has one leader, about 1 in 12 members (decision 33)." },

‎docs/crowd.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ The Cast is hand-designed. Everyone else is generated: the **Crowd** gives Full
99
3. Names come from public-domain frequency data and never depend on photo ethnicity.
1010
4. Crowd households have no photos. About half of Core 3's companions get photos from the pool (see [Datasets](../datasets/README.md)).
1111
5. Core 3's companions use a more involved connection status mix than the Crowd, set in the dataset manifest, so more of them attend, give, and join groups (decision 142). Core 1 and Core 3 also scale up checks as a payment method, so check batches and check images have enough to show (decision 143).
12+
6. Every generated person has a birth date. Measured age mixes count only people with a birth date, so the profile states the age mix as shares of all people, and validation grades it against people with a birth date, which is nearly all of them (decision 156).
13+
7. A child on their own, in a one-person family, is a student aged 12 to 17 (decision 157).
1214

1315
## How big the Crowd is
1416

0 commit comments

Comments
 (0)