Ship prebuilt binaries, deb, rpm and apk packages on Cloudsmith, a GHCR image, and Homebrew, Scoop and AUR packages with each release
This commit is contained in:
@@ -0,0 +1,61 @@
|
|||||||
|
name: Packages
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_call:
|
||||||
|
inputs:
|
||||||
|
tag:
|
||||||
|
type: string
|
||||||
|
required: true
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
tag:
|
||||||
|
description: The released tag to package, such as v0.1.0
|
||||||
|
type: string
|
||||||
|
required: true
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
packages:
|
||||||
|
name: Binaries, packages and image for ${{ inputs.tag }}
|
||||||
|
runs-on: ubuntu-26.04
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
packages: write
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v7
|
||||||
|
with:
|
||||||
|
ref: ${{ inputs.tag }}
|
||||||
|
path: src
|
||||||
|
fetch-depth: 0
|
||||||
|
persist-credentials: false
|
||||||
|
# The packaging config comes from the workflow's commit, so a tag cut before it
|
||||||
|
# existed can still be packaged.
|
||||||
|
- uses: actions/checkout@v7
|
||||||
|
with:
|
||||||
|
path: tooling
|
||||||
|
persist-credentials: false
|
||||||
|
- uses: docker/setup-buildx-action@v4
|
||||||
|
- uses: docker/login-action@v4
|
||||||
|
with:
|
||||||
|
registry: ghcr.io
|
||||||
|
username: ${{ github.actor }}
|
||||||
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
- uses: goreleaser/goreleaser-action@v7
|
||||||
|
with:
|
||||||
|
version: v2.18.3
|
||||||
|
workdir: src
|
||||||
|
args: release --clean --config ../tooling/release-tooling/goreleaser.yaml
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
TAP_GITHUB_TOKEN: ${{ secrets.TAP_GITHUB_TOKEN }}
|
||||||
|
AUR_KEY: ${{ secrets.AUR_KEY }}
|
||||||
|
- name: Upload to the Cloudsmith repositories
|
||||||
|
env:
|
||||||
|
CLOUDSMITH_API_KEY: ${{ secrets.CLOUDSMITH_API_KEY }}
|
||||||
|
run: |
|
||||||
|
pip install --quiet cloudsmith-cli==1.27.0
|
||||||
|
for f in dist/*.deb; do cloudsmith push deb --republish larvit/fejkdata/any-distro/any-version "$f"; done
|
||||||
|
for f in dist/*.rpm; do cloudsmith push rpm --republish larvit/fejkdata/any-distro/any-version "$f"; done
|
||||||
|
for f in dist/*.apk; do cloudsmith push alpine --republish larvit/fejkdata/alpine/any-version "$f"; done
|
||||||
@@ -58,13 +58,27 @@ jobs:
|
|||||||
runs-on: ubuntu-26.04
|
runs-on: ubuntu-26.04
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
|
outputs:
|
||||||
|
tag: ${{ steps.publish.outputs.tag }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v7
|
- uses: actions/checkout@v7
|
||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
- run: python3 release-tooling/publish_release.py
|
- id: publish
|
||||||
|
run: python3 release-tooling/publish_release.py
|
||||||
env:
|
env:
|
||||||
FORGE_API_URL: ${{ github.api_url }}
|
FORGE_API_URL: ${{ github.api_url }}
|
||||||
FORGE_REPOSITORY: ${{ github.repository }}
|
FORGE_REPOSITORY: ${{ github.repository }}
|
||||||
FORGE_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
FORGE_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
SHA: ${{ github.sha }}
|
SHA: ${{ github.sha }}
|
||||||
|
|
||||||
|
packages:
|
||||||
|
needs: release
|
||||||
|
if: needs.release.outputs.tag != ''
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
packages: write
|
||||||
|
uses: ./.github/workflows/packages.yml
|
||||||
|
with:
|
||||||
|
tag: ${{ needs.release.outputs.tag }}
|
||||||
|
secrets: inherit
|
||||||
|
|||||||
@@ -4,6 +4,15 @@ Format: [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). A release's
|
|||||||
`Breaking` section comes first and names each rejected spelling with its
|
`Breaking` section comes first and names each rejected spelling with its
|
||||||
replacement, and each removed path, column or flag.
|
replacement, and each removed path, column or flag.
|
||||||
|
|
||||||
|
## [Unreleased]
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Prebuilt binaries for Linux, macOS and Windows on amd64 and arm64, packages for apt,
|
||||||
|
dnf, apk, Homebrew, Scoop and the AUR, and the image `ghcr.io/larvit/fejkdata`, so
|
||||||
|
the CLI installs without Go. 0.1.0 ships them too; the README's
|
||||||
|
[Install](https://github.com/larvit/fejkdata#install) lists each command.
|
||||||
|
|
||||||
## [0.1.0] - 2026-10-13
|
## [0.1.0] - 2026-10-13
|
||||||
|
|
||||||
The first release: a Go library and a CLI that render locale-aware fake data from JSON
|
The first release: a Go library and a CLI that render locale-aware fake data from JSON
|
||||||
|
|||||||
+3
-2
@@ -16,8 +16,9 @@ COPY release-tooling/ /release-tooling/
|
|||||||
RUN python3 -m unittest discover -s /release-tooling -p '*_test.py' && touch /tested
|
RUN python3 -m unittest discover -s /release-tooling -p '*_test.py' && touch /tested
|
||||||
|
|
||||||
FROM goreleaser/goreleaser:v2.18.3 AS packaging
|
FROM goreleaser/goreleaser:v2.18.3 AS packaging
|
||||||
COPY release-tooling/goreleaser.yaml /goreleaser.yaml
|
WORKDIR /check
|
||||||
RUN goreleaser check --config /goreleaser.yaml && touch /tested
|
COPY release-tooling/goreleaser.yaml ./
|
||||||
|
RUN git init -q && goreleaser check --config goreleaser.yaml && touch /tested
|
||||||
|
|
||||||
FROM portable
|
FROM portable
|
||||||
# BuildKit skips a stage nothing copies from.
|
# BuildKit skips a stage nothing copies from.
|
||||||
|
|||||||
@@ -29,10 +29,32 @@ echo '{/sv_SE.person}' | fejkdata # Sara Eriksson
|
|||||||
- **Reproducible:** the same seed, version and data give the same output, when one goroutine
|
- **Reproducible:** the same seed, version and data give the same output, when one goroutine
|
||||||
draws it.
|
draws it.
|
||||||
|
|
||||||
[CLI](#cli) · [Library](#library) · [Data](#data) · [Data format (templates)](#data-format) ·
|
[Install](#install) · [CLI](#cli) · [Library](#library) · [Data](#data) · [Data format (templates)](#data-format) ·
|
||||||
[Functions](#functions) · [Versioning](#versioning) · [Audience](#audience) ·
|
[Functions](#functions) · [Versioning](#versioning) · [Audience](#audience) ·
|
||||||
[Goals](#goals) · [Development](#development) · [License](#license)
|
[Goals](#goals) · [Development](#development) · [License](#license)
|
||||||
|
|
||||||
|
## Install
|
||||||
|
|
||||||
|
```sh
|
||||||
|
brew install larvit/tap/fejkdata # macOS, Linux
|
||||||
|
scoop bucket add larvit https://github.com/larvit/scoop-bucket && scoop install fejkdata # Windows
|
||||||
|
yay -S fejkdata-bin # Arch, from the AUR
|
||||||
|
docker run --rm -i ghcr.io/larvit/fejkdata < template.json # any OS with Docker
|
||||||
|
go install github.com/larvit/fejkdata/cmd/fejkdata@latest # any OS with Go
|
||||||
|
```
|
||||||
|
|
||||||
|
Debian, Ubuntu, Fedora, RHEL and Alpine install from fejkdata's Cloudsmith repository,
|
||||||
|
after one setup script adds it and its signing key:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
curl -1sLf https://dl.cloudsmith.io/public/larvit/fejkdata/cfg/setup/bash.deb.sh | sudo -E bash && sudo apt install fejkdata
|
||||||
|
curl -1sLf https://dl.cloudsmith.io/public/larvit/fejkdata/cfg/setup/bash.rpm.sh | sudo -E bash && sudo dnf install fejkdata
|
||||||
|
curl -1sLf https://dl.cloudsmith.io/public/larvit/fejkdata/cfg/setup/bash.alpine.sh | sudo -E bash && sudo apk add fejkdata
|
||||||
|
```
|
||||||
|
|
||||||
|
Each [release](https://github.com/larvit/fejkdata/releases) also carries the binaries for
|
||||||
|
Linux, macOS and Windows on amd64 and arm64, and the `.deb`, `.rpm` and `.apk` packages.
|
||||||
|
|
||||||
## CLI
|
## CLI
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
@@ -1133,7 +1155,7 @@ internal/rows/ a table's rows: the TSV, the options proved over it, the links b
|
|||||||
data/ the shipped modules, each a Go package embedding its categories (JSON, and a TSV per table) and its manifest; and Modules, which lists them
|
data/ the shipped modules, each a Go package embedding its categories (JSON, and a TSV per table) and its manifest; and Modules, which lists them
|
||||||
data-import/ the scripts that rebuild each sourced table (see DATA-LICENSES.md), and the modules they share
|
data-import/ the scripts that rebuild each sourced table (see DATA-LICENSES.md), and the modules they share
|
||||||
docs/ the decision log, the register research behind the shipped data, the survey of other libraries, panels' scores and rulings on how readable the code is, and what each chunk cost an agent to read
|
docs/ the decision log, the register research behind the shipped data, the survey of other libraries, panels' scores and rulings on how readable the code is, and what each chunk cost an agent to read
|
||||||
release-tooling/ the release CI publishes from the changelog heading
|
release-tooling/ the release CI publishes from the changelog heading, and the binaries, packages and image built for it
|
||||||
testdata/ the pinned shipped shape (see Versioning)
|
testdata/ the pinned shipped shape (see Versioning)
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -1229,7 +1251,12 @@ docker compose run --rm --user "$(id -u):$(id -g)" data-import data-import/usera
|
|||||||
To release, head `CHANGELOG.md` with the version's section in place of `Unreleased`
|
To release, head `CHANGELOG.md` with the version's section in place of `Unreleased`
|
||||||
and merge: once `main` passes the gate, CI tags that commit `vX.Y.Z` and publishes
|
and merge: once `main` passes the gate, CI tags that commit `vX.Y.Z` and publishes
|
||||||
the GitHub release with the section as its body. A top heading of `[Unreleased]`
|
the GitHub release with the section as its body. A top heading of `[Unreleased]`
|
||||||
publishes nothing.
|
publishes nothing. The new release then runs the Packages workflow, which attaches the
|
||||||
|
binaries and packages, pushes the image, uploads to Cloudsmith and updates the Homebrew
|
||||||
|
tap, the Scoop bucket and the AUR. It reads the repository secrets `TAP_GITHUB_TOKEN`,
|
||||||
|
a token that can push to `larvit/homebrew-tap` and `larvit/scoop-bucket`, `AUR_KEY`,
|
||||||
|
the AUR account's SSH key, and `CLOUDSMITH_API_KEY`. To package a release again, run
|
||||||
|
the workflow by hand with its tag; it replaces what it uploaded before.
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
|
|||||||
@@ -903,6 +903,8 @@ By the maintainer's decision of 2026-10-09, every 0.1.0 chunk ships under the fl
|
|||||||
|
|
||||||
Shipped under that decision: item 89, the last of 0.1.0, at 52e0304. Its paired ruling against 90ffcff was better. The release's scoring run read Navigation 7.00, Locality 5.75, Shape 6.38, Self-sufficiency 6.50 and overall 6.25; its seats named places items 170 to 172 and 178 hold, and `isPath`, filed as item 251.
|
Shipped under that decision: item 89, the last of 0.1.0, at 52e0304. Its paired ruling against 90ffcff was better. The release's scoring run read Navigation 7.00, Locality 5.75, Shape 6.38, Self-sufficiency 6.50 and overall 6.25; its seats named places items 170 to 172 and 178 hold, and `isPath`, filed as item 251.
|
||||||
|
|
||||||
|
Shipped under the floor by the maintainer's decision of 2026-10-13: item 58, prebuilt binaries and packages, as the distribution of 0.1.0 rather than a 0.2.0 item. It changes no Go code.
|
||||||
|
|
||||||
Shipped by the maintainer's decision of 2026-10-11 with its ratchet waived: item 182, the shipped data as Go packages, at a632a92. Its last paired ruling against bf1becb was same overall, Mid A better and Junior A worse, with Shape fallen, three seats against the namespace mount in `internal/datafiles/mount.go` and the `at` field of `datafiles.Source`; the scoring run that would rule it worse under the floor was not run. `todo.md` item 197 replaces that mount.
|
Shipped by the maintainer's decision of 2026-10-11 with its ratchet waived: item 182, the shipped data as Go packages, at a632a92. Its last paired ruling against bf1becb was same overall, Mid A better and Junior A worse, with Shape fallen, three seats against the namespace mount in `internal/datafiles/mount.go` and the `at` field of `datafiles.Source`; the scoring run that would rule it worse under the floor was not run. `todo.md` item 197 replaces that mount.
|
||||||
|
|
||||||
Shipped under the floor before that by the maintainer's decisions of 2026-10-07, each with the scoring run and its ratchet waived: the CLI reading its template from stdin; and goal 5.7 loading whatever is well-formed and means one thing, dropping every refusal that guessed at a mistake.
|
Shipped under the floor before that by the maintainer's decisions of 2026-10-07, each with the scoring run and its ratchet waived: the CLI reading its template from stdin; and goal 5.7 loading whatever is well-formed and means one thing, dropping every refusal that guessed at a mistake.
|
||||||
|
|||||||
@@ -0,0 +1,109 @@
|
|||||||
|
# The packages workflow runs this from a checkout of the release's tag, in src/, beside
|
||||||
|
# this repository's tooling/ checkout: the paths below are relative to src/. A dist/
|
||||||
|
# inside src/ would make Go stamp the binaries' version +dirty.
|
||||||
|
version: 2
|
||||||
|
|
||||||
|
project_name: fejkdata
|
||||||
|
dist: ../dist
|
||||||
|
|
||||||
|
builds:
|
||||||
|
- main: ./cmd/fejkdata
|
||||||
|
binary: fejkdata
|
||||||
|
env:
|
||||||
|
- CGO_ENABLED=0
|
||||||
|
flags:
|
||||||
|
- -trimpath
|
||||||
|
ldflags:
|
||||||
|
- -s -w
|
||||||
|
goos: [linux, darwin, windows]
|
||||||
|
goarch: [amd64, arm64]
|
||||||
|
|
||||||
|
archives:
|
||||||
|
- formats: [tar.gz]
|
||||||
|
format_overrides:
|
||||||
|
- goos: windows
|
||||||
|
formats: [zip]
|
||||||
|
files:
|
||||||
|
- LICENSE
|
||||||
|
- DATA-LICENSES.md
|
||||||
|
- README.md
|
||||||
|
- CHANGELOG.md
|
||||||
|
|
||||||
|
checksum:
|
||||||
|
name_template: checksums.txt
|
||||||
|
|
||||||
|
changelog:
|
||||||
|
disable: true
|
||||||
|
|
||||||
|
release:
|
||||||
|
github:
|
||||||
|
owner: larvit
|
||||||
|
name: fejkdata
|
||||||
|
mode: keep-existing
|
||||||
|
replace_existing_artifacts: true
|
||||||
|
|
||||||
|
nfpms:
|
||||||
|
- package_name: fejkdata
|
||||||
|
vendor: Larvit
|
||||||
|
homepage: https://github.com/larvit/fejkdata
|
||||||
|
maintainer: Lilleman auf Larv <lilleman@larvit.se>
|
||||||
|
description: Render locale-aware fake data from JSON templates.
|
||||||
|
license: MIT
|
||||||
|
formats: [deb, rpm, apk]
|
||||||
|
contents:
|
||||||
|
- src: LICENSE
|
||||||
|
dst: /usr/share/doc/fejkdata/LICENSE
|
||||||
|
- src: DATA-LICENSES.md
|
||||||
|
dst: /usr/share/doc/fejkdata/DATA-LICENSES.md
|
||||||
|
|
||||||
|
dockers_v2:
|
||||||
|
- images:
|
||||||
|
- ghcr.io/larvit/fejkdata
|
||||||
|
tags:
|
||||||
|
- "{{ .Version }}"
|
||||||
|
- latest
|
||||||
|
dockerfile: ../tooling/release-tooling/image.Dockerfile
|
||||||
|
labels:
|
||||||
|
org.opencontainers.image.source: https://github.com/larvit/fejkdata
|
||||||
|
org.opencontainers.image.version: "{{ .Version }}"
|
||||||
|
org.opencontainers.image.licenses: MIT
|
||||||
|
|
||||||
|
homebrew_casks:
|
||||||
|
- name: fejkdata
|
||||||
|
binaries: [fejkdata]
|
||||||
|
homepage: https://github.com/larvit/fejkdata
|
||||||
|
description: Render locale-aware fake data from JSON templates
|
||||||
|
license: MIT
|
||||||
|
repository:
|
||||||
|
owner: larvit
|
||||||
|
name: homebrew-tap
|
||||||
|
token: "{{ .Env.TAP_GITHUB_TOKEN }}"
|
||||||
|
hooks:
|
||||||
|
post:
|
||||||
|
install: |
|
||||||
|
if OS.mac?
|
||||||
|
system_command "/usr/bin/xattr", args: ["-dr", "com.apple.quarantine", "#{staged_path}/fejkdata"]
|
||||||
|
end
|
||||||
|
|
||||||
|
scoops:
|
||||||
|
- name: fejkdata
|
||||||
|
homepage: https://github.com/larvit/fejkdata
|
||||||
|
description: Render locale-aware fake data from JSON templates.
|
||||||
|
license: MIT
|
||||||
|
repository:
|
||||||
|
owner: larvit
|
||||||
|
name: scoop-bucket
|
||||||
|
token: "{{ .Env.TAP_GITHUB_TOKEN }}"
|
||||||
|
|
||||||
|
aurs:
|
||||||
|
- name: fejkdata-bin
|
||||||
|
homepage: https://github.com/larvit/fejkdata
|
||||||
|
description: Render locale-aware fake data from JSON templates
|
||||||
|
license: MIT
|
||||||
|
maintainers:
|
||||||
|
- Lilleman auf Larv <lilleman@larvit.se>
|
||||||
|
private_key: "{{ .Env.AUR_KEY }}"
|
||||||
|
git_url: ssh://aur@aur.archlinux.org/fejkdata-bin.git
|
||||||
|
commit_author:
|
||||||
|
name: Lilleman auf Larv
|
||||||
|
email: lilleman@larvit.se
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
FROM scratch
|
||||||
|
ARG TARGETPLATFORM
|
||||||
|
COPY $TARGETPLATFORM/fejkdata /fejkdata
|
||||||
|
ENTRYPOINT ["/fejkdata"]
|
||||||
@@ -2,7 +2,8 @@
|
|||||||
"""Publish the release that CHANGELOG.md's top heading names, tagging SHA.
|
"""Publish the release that CHANGELOG.md's top heading names, tagging SHA.
|
||||||
|
|
||||||
A top heading of `[Unreleased]`, or a version already released, publishes nothing.
|
A top heading of `[Unreleased]`, or a version already released, publishes nothing.
|
||||||
Env: FORGE_API_URL, FORGE_REPOSITORY (owner/repo), FORGE_TOKEN, SHA.
|
Env: FORGE_API_URL, FORGE_REPOSITORY (owner/repo), FORGE_TOKEN, SHA, and GITHUB_OUTPUT,
|
||||||
|
where a published release writes `tag=vX.Y.Z`.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import json
|
import json
|
||||||
@@ -58,6 +59,8 @@ def main() -> int:
|
|||||||
raise
|
raise
|
||||||
release = request("releases", {"body": body, "name": tag, "tag_name": tag, "target_commitish": sha})
|
release = request("releases", {"body": body, "name": tag, "tag_name": tag, "target_commitish": sha})
|
||||||
print(release["html_url"])
|
print(release["html_url"])
|
||||||
|
with open(os.environ["GITHUB_OUTPUT"], "a", encoding="utf-8") as f:
|
||||||
|
f.write(f"tag={tag}\n")
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -65,7 +65,6 @@
|
|||||||
|
|
||||||
| ID | Release | Exempt | Item | R | S | A | G | Goals | Score |
|
| ID | Release | Exempt | Item | R | S | A | G | Goals | Score |
|
||||||
|---|---|---|---|---|---|---|---|---|---|
|
|---|---|---|---|---|---|---|---|---|---|
|
||||||
| 58 | 0.2.0 | | **Ship prebuilt binaries, a container image, and packages for Homebrew, Scoop and the biggest Linux package managers, so the CLI needs no Go.** | 3 | 7 | 8 | 9 | 1.1, 7 | 29.2 |
|
|
||||||
| 243 | 0.2.0 | | **Add `en_US.ein`, drawing only the prefixes the IRS assigns.** | 2 | 2 | 7 | 8 | 2.1, 4 | 26.7 |
|
| 243 | 0.2.0 | | **Add `en_US.ein`, drawing only the prefixes the IRS assigns.** | 2 | 2 | 7 | 8 | 2.1, 4 | 26.7 |
|
||||||
| 230 | 0.2.0 | | **Add `sv_SE.organisationsnummer`, whose first digit is its legal form's group digit and whose last is a Luhn check digit, and `sv_SE.vat`, `SE` + the number + `01`.** | 2 | 3 | 7 | 8 | 2.1, 4 | 26.4 |
|
| 230 | 0.2.0 | | **Add `sv_SE.organisationsnummer`, whose first digit is its legal form's group digit and whose last is a Luhn check digit, and `sv_SE.vat`, `SE` + the number + `01`.** | 2 | 3 | 7 | 8 | 2.1, 4 | 26.4 |
|
||||||
| 210 | 0.2.0 | | **Add `fr_FR` with its `geo/FR` tree.** | 3 | 8 | 8 | 8 | 2 | 26.2 |
|
| 210 | 0.2.0 | | **Add `fr_FR` with its `geo/FR` tree.** | 3 | 8 | 8 | 8 | 2 | 26.2 |
|
||||||
@@ -215,10 +214,6 @@
|
|||||||
|
|
||||||
## Details
|
## Details
|
||||||
|
|
||||||
### 58. Ship prebuilt binaries, a container image, and packages for Homebrew, Scoop and the biggest Linux package managers, so the CLI needs no Go.
|
|
||||||
|
|
||||||
GoReleaser attaches the binaries to the release the tag workflow publishes, and builds deb and rpm packages, an Alpine APK and an AUR package beside Homebrew and Scoop. The binaries carry the stamped tag, which `--version` prints. v0.1.0 ships first, so it can be tested before it is packaged.
|
|
||||||
|
|
||||||
### 243. Add `en_US.ein`, drawing only the prefixes the IRS assigns.
|
### 243. Add `en_US.ein`, drawing only the prefixes the IRS assigns.
|
||||||
|
|
||||||
The IRS's prefix list is facts. [Source research](docs/research/research-sources-world.md).
|
The IRS's prefix list is facts. [Source research](docs/research/research-sources-world.md).
|
||||||
|
|||||||
Reference in New Issue
Block a user