@ossy/deployment-tools 3.7.0 → 3.13.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.
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,24 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
# [3.13.0](https://github.com/ossy-se/ossy/compare/v3.12.0...v3.13.0) (2026-09-06)
|
|
7
|
+
|
|
8
|
+
### Features
|
|
9
|
+
|
|
10
|
+
* **platform:** download GeoLite2-Country at startServer boot ([#804](https://github.com/ossy-se/ossy/issues/804)) ([#818](https://github.com/ossy-se/ossy/issues/818)) ([6629ad0](https://github.com/ossy-se/ossy/commit/6629ad07277cfa8350759f2a775110a00743c393))
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
# [3.12.0](https://github.com/ossy-se/ossy/compare/v3.11.1...v3.12.0) (2026-09-06)
|
|
14
|
+
|
|
15
|
+
### Bug Fixes
|
|
16
|
+
|
|
17
|
+
* default the API to same-origin and drop api.ossy.se ([#794](https://github.com/ossy-se/ossy/issues/794)) ([397a06f](https://github.com/ossy-se/ossy/commit/397a06f88b01e297fb76f35c429f3e687bdd6af9))
|
|
18
|
+
|
|
19
|
+
### Features
|
|
20
|
+
|
|
21
|
+
* **analytics:** Host visitor locations from connection geo ([#772](https://github.com/ossy-se/ossy/issues/772)) ([a565c1b](https://github.com/ossy-se/ossy/commit/a565c1b5078219ef412148d77dc33697f2079612)), closes [#769](https://github.com/ossy-se/ossy/issues/769) [#797](https://github.com/ossy-se/ossy/issues/797) [#797](https://github.com/ossy-se/ossy/issues/797) [#797](https://github.com/ossy-se/ossy/issues/797) [#797](https://github.com/ossy-se/ossy/issues/797) [#769](https://github.com/ossy-se/ossy/issues/769) [#797](https://github.com/ossy-se/ossy/issues/797) [#769](https://github.com/ossy-se/ossy/issues/769)
|
|
22
|
+
|
|
23
|
+
|
|
6
24
|
# [3.7.0](https://github.com/ossy-se/ossy/compare/v3.6.2...v3.7.0) (2026-08-22)
|
|
7
25
|
|
|
8
26
|
### Features
|
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@ Infrastructure and CDK tooling for the Ossy platform.
|
|
|
9
9
|
```
|
|
10
10
|
Internet → CloudFront (ACM TLS, us-east-1) → WAF → ALB (:80)
|
|
11
11
|
├── host rules from platforms.json `services[].hosts|domain`
|
|
12
|
-
│ e.g. ossy.se
|
|
12
|
+
│ e.g. ossy.se → website-ossy Fargate service
|
|
13
13
|
├── other known hosts / *.ossy.se → platform-runtime Fargate service
|
|
14
14
|
└── default action → platform-runtime
|
|
15
15
|
```
|
|
@@ -35,7 +35,7 @@ Every deployable Ossy HTTP image exposes an unauthenticated liveness probe at **
|
|
|
35
35
|
|
|
36
36
|
**ALB target groups** probe `GET /health`. **ECS container health checks** run an exec-form Node one-liner (`ecsContainerHealthCheckCommand`) that `fetch`es the same path on `PORT` and aborts after `HEALTHCHECK_FETCH_TIMEOUT_MS` (4s). Do not point probes at `/`, `/status`, or authenticated routes.
|
|
37
37
|
|
|
38
|
-
Task definitions also set plain env `PORT`, `OSSY_SERVICE_NAME`, `NODE_ENV`,
|
|
38
|
+
Task definitions also set plain env `PORT`, `OSSY_SERVICE_NAME`, `NODE_ENV`, media bucket vars, and `GEOLITE2_COUNTRY_MMDB` (`/tmp/GeoLite2-Country.mmdb`, #804) via `containerEnvironment`. Those keys are **filtered out** of Secrets Manager injection (`secretEnvKeysForEcsContainer`) so ECS cannot reject duplicate environment/secret keys.
|
|
39
39
|
|
|
40
40
|
## Configuration — `platforms.json`
|
|
41
41
|
|
|
@@ -64,7 +64,7 @@ HTTP services (default) become Fargate services with ALB host rules. The contain
|
|
|
64
64
|
"name": "ossy-website-ossy",
|
|
65
65
|
"domain": "ossy.se",
|
|
66
66
|
"image": "ghcr.io/ossy-se/website-ossy:latest",
|
|
67
|
-
"hosts": ["ossy.se"
|
|
67
|
+
"hosts": ["ossy.se"]
|
|
68
68
|
}
|
|
69
69
|
]
|
|
70
70
|
```
|
|
@@ -73,7 +73,7 @@ HTTP services (default) become Fargate services with ALB host rules. The contain
|
|
|
73
73
|
|---|---|
|
|
74
74
|
| `name` | Unique service name — Secrets Manager / ECS key strips a leading `ossy-` (`website-ossy`). |
|
|
75
75
|
| `domain` | Primary hostname (default ALB host when `hosts` is omitted). |
|
|
76
|
-
| `hosts` | Optional ALB host-header list. Example: `["ossy.se"
|
|
76
|
+
| `hosts` | Optional ALB host-header list. Example: `["ossy.se"]` so the website image serves the apex. Defaults to `[domain]`. |
|
|
77
77
|
| `image` | Docker image to pull and run (GHCR). |
|
|
78
78
|
|
|
79
79
|
**Built-in (always present):**
|
|
@@ -264,6 +264,10 @@ Other common env vars:
|
|
|
264
264
|
| `AWS_SECRET_ACCESS_KEY` | API | AWS credentials for S3 |
|
|
265
265
|
| `OSSY_API_KEY` | Platform, websites | API JWT for CMS reads |
|
|
266
266
|
| `OSSY_COOKIE_SECRET` | Websites | Cookie signing secret |
|
|
267
|
+
| `GEOLITE2_COUNTRY_MMDB` | App (`@ossy/analytics` location projection) | Absolute path to MaxMind GeoLite2-Country `.mmdb` (#769 / #804). Set on every ECS task as `/tmp/GeoLite2-Country.mmdb`. `startServer` downloads the file there when `MAXMIND_LICENSE_KEY` is set. Optional; without the file `countryCode` is omitted (IP still stored on the event). |
|
|
268
|
+
| `MAXMIND_LICENSE_KEY` | App (`startServer` GeoLite2 download) | MaxMind license key. Add to `platforms.json` `env` and `npm run sync-secrets` so **every** website image (ossy.se, plexus-sanitas, …) can download GeoLite2-Country at boot (#804). Free signup: https://www.maxmind.com/en/geolite2/signup |
|
|
269
|
+
| `MAXMIND_ACCOUNT_ID` | App (`startServer` GeoLite2 download) | Optional MaxMind account id. When set with the license key, download uses the permalink + HTTP Basic auth API. |
|
|
270
|
+
| `OSSY_TRUST_PROXY_HOPS` | Platform / websites | Express `trust proxy` hop count behind CloudFront→ALB (default: `2`). |
|
|
267
271
|
| `OPENAI_API_KEY` | Worker | OpenAI API key |
|
|
268
272
|
| `OPENAI_ORGANIZATION` | Worker | OpenAI organisation ID |
|
|
269
273
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ossy/deployment-tools",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.13.0",
|
|
4
4
|
"description": "Collection of scripts and tools to aid deployment of containers and static files to Amazon Web Services through GitHub Actions",
|
|
5
5
|
"source": "./src/index.js",
|
|
6
6
|
"main": "./src/index.js",
|
|
@@ -24,5 +24,5 @@
|
|
|
24
24
|
"devDependencies": {
|
|
25
25
|
"jest": "^30.4.2"
|
|
26
26
|
},
|
|
27
|
-
"gitHead": "
|
|
27
|
+
"gitHead": "7a02d1e056b731aa36f72e3f8d6df941101dbd50"
|
|
28
28
|
}
|
|
@@ -31,8 +31,12 @@ const CONTAINER_ENVIRONMENT_KEYS = Object.freeze([
|
|
|
31
31
|
'OSSY_SERVICE_NAME',
|
|
32
32
|
'MEDIA_REPOSITORY',
|
|
33
33
|
'MEDIA_CDN_DOMAIN_NAME',
|
|
34
|
+
'GEOLITE2_COUNTRY_MMDB',
|
|
34
35
|
])
|
|
35
36
|
|
|
37
|
+
/** Keep in sync with `@ossy/platform` `GEOLITE2_COUNTRY_MMDB_PATH` (#804). */
|
|
38
|
+
const GEOLITE2_COUNTRY_MMDB_PATH = '/tmp/GeoLite2-Country.mmdb'
|
|
39
|
+
|
|
36
40
|
/**
|
|
37
41
|
* @typedef {Object} PlatformEcsService
|
|
38
42
|
* @property {string} key - short key (`runtime`, `website-ossy`, …) — matches Secrets Manager
|
|
@@ -96,6 +100,7 @@ function containerEnvironment({
|
|
|
96
100
|
OSSY_SERVICE_NAME: serviceKey,
|
|
97
101
|
MEDIA_REPOSITORY: mediaRepository,
|
|
98
102
|
MEDIA_CDN_DOMAIN_NAME: mediaCdnDomainName,
|
|
103
|
+
GEOLITE2_COUNTRY_MMDB: GEOLITE2_COUNTRY_MMDB_PATH,
|
|
99
104
|
...(nodeOptions ? { NODE_OPTIONS: nodeOptions } : {}),
|
|
100
105
|
}
|
|
101
106
|
}
|
|
@@ -212,6 +217,7 @@ module.exports = {
|
|
|
212
217
|
CONTAINER_PORT,
|
|
213
218
|
HEALTH_PATH,
|
|
214
219
|
HEALTHCHECK_FETCH_TIMEOUT_MS,
|
|
220
|
+
GEOLITE2_COUNTRY_MMDB_PATH,
|
|
215
221
|
CONTAINER_ENVIRONMENT_KEYS,
|
|
216
222
|
secretEnvKeysForEcsContainer,
|
|
217
223
|
containerEnvironment,
|
|
@@ -6,6 +6,7 @@ const {
|
|
|
6
6
|
CONTAINER_PORT,
|
|
7
7
|
HEALTH_PATH,
|
|
8
8
|
HEALTHCHECK_FETCH_TIMEOUT_MS,
|
|
9
|
+
GEOLITE2_COUNTRY_MMDB_PATH,
|
|
9
10
|
RUNTIME_IMAGE,
|
|
10
11
|
containerEnvironment,
|
|
11
12
|
ecsContainerHealthCheckCommand,
|
|
@@ -27,6 +28,17 @@ describe('shared health constants', () => {
|
|
|
27
28
|
})
|
|
28
29
|
})
|
|
29
30
|
|
|
31
|
+
describe('GeoLite2-Country path (#804)', () => {
|
|
32
|
+
it('stays aligned with @ossy/platform geolite2-country-path.js', () => {
|
|
33
|
+
const src = fs.readFileSync(
|
|
34
|
+
path.join(__dirname, '../../../platform/src/geoip/geolite2-country-path.js'),
|
|
35
|
+
'utf8'
|
|
36
|
+
)
|
|
37
|
+
expect(src).toContain(`export const GEOLITE2_COUNTRY_MMDB_PATH = '${GEOLITE2_COUNTRY_MMDB_PATH}'`)
|
|
38
|
+
expect(GEOLITE2_COUNTRY_MMDB_PATH).toBe('/tmp/GeoLite2-Country.mmdb')
|
|
39
|
+
})
|
|
40
|
+
})
|
|
41
|
+
|
|
30
42
|
describe('ecsContainerHealthCheckCommand', () => {
|
|
31
43
|
it('probes HEALTH_PATH with Node fetch and abort timeout', () => {
|
|
32
44
|
const command = ecsContainerHealthCheckCommand()
|
|
@@ -60,6 +72,7 @@ describe('containerEnvironment', () => {
|
|
|
60
72
|
OSSY_SERVICE_NAME: 'website-ossy',
|
|
61
73
|
MEDIA_REPOSITORY: 'media-bucket',
|
|
62
74
|
MEDIA_CDN_DOMAIN_NAME: 'https://cdn.example',
|
|
75
|
+
GEOLITE2_COUNTRY_MMDB: '/tmp/GeoLite2-Country.mmdb',
|
|
63
76
|
})
|
|
64
77
|
})
|
|
65
78
|
|
|
@@ -92,6 +105,7 @@ describe('secretEnvKeysForEcsContainer', () => {
|
|
|
92
105
|
'TOKEN_SECRET',
|
|
93
106
|
'NODE_ENV',
|
|
94
107
|
'MEDIA_REPOSITORY',
|
|
108
|
+
'GEOLITE2_COUNTRY_MMDB',
|
|
95
109
|
'NODE_OPTIONS',
|
|
96
110
|
'DB_URL',
|
|
97
111
|
])).toEqual(['TOKEN_SECRET', 'DB_URL'])
|
|
@@ -106,8 +120,8 @@ describe('hostsFromServiceEntry', () => {
|
|
|
106
120
|
it('uses hosts when provided', () => {
|
|
107
121
|
expect(hostsFromServiceEntry({
|
|
108
122
|
domain: 'ossy.se',
|
|
109
|
-
hosts: ['ossy.se', '
|
|
110
|
-
})).toEqual(['ossy.se', '
|
|
123
|
+
hosts: ['ossy.se', 'www.ossy.se'],
|
|
124
|
+
})).toEqual(['ossy.se', 'www.ossy.se'])
|
|
111
125
|
})
|
|
112
126
|
|
|
113
127
|
it('falls back to domain', () => {
|
|
@@ -120,7 +134,6 @@ describe('listPlatformEcsServices', () => {
|
|
|
120
134
|
const services = listPlatformEcsServices({
|
|
121
135
|
platformName: 'ossybot',
|
|
122
136
|
domains: [
|
|
123
|
-
'api.ossy.se',
|
|
124
137
|
'ossy.se',
|
|
125
138
|
'*.ossy.se',
|
|
126
139
|
'www.plexus-sanitas.com',
|
|
@@ -130,7 +143,7 @@ describe('listPlatformEcsServices', () => {
|
|
|
130
143
|
{
|
|
131
144
|
name: 'ossy-website-ossy',
|
|
132
145
|
domain: 'ossy.se',
|
|
133
|
-
hosts: ['ossy.se'
|
|
146
|
+
hosts: ['ossy.se'],
|
|
134
147
|
image: 'ghcr.io/ossy-se/website-ossy:latest',
|
|
135
148
|
cpu: 1024,
|
|
136
149
|
memoryLimitMiB: 4096,
|
|
@@ -165,7 +178,7 @@ describe('listPlatformEcsServices', () => {
|
|
|
165
178
|
|
|
166
179
|
const website = services.find(s => s.key === 'website-ossy')
|
|
167
180
|
expect(website.isDefault).toBe(false)
|
|
168
|
-
expect(website.hosts).toEqual(['ossy.se'
|
|
181
|
+
expect(website.hosts).toEqual(['ossy.se'])
|
|
169
182
|
expect(website.image).toBe('ghcr.io/ossy-se/website-ossy:latest')
|
|
170
183
|
expect(website.secretName).toBe('ossybot/website-ossy')
|
|
171
184
|
expect(website.cpu).toBe(1024)
|
|
@@ -193,7 +193,7 @@ class PlatformEcsStack extends Stack {
|
|
|
193
193
|
streamPrefix: service.key,
|
|
194
194
|
logGroup,
|
|
195
195
|
}),
|
|
196
|
-
// Labels `/health` via OSSY_SERVICE_NAME;
|
|
196
|
+
// Labels `/health` via OSSY_SERVICE_NAME; GeoLite2 path (#804). Keys stay in CONTAINER_ENVIRONMENT_KEYS.
|
|
197
197
|
environment: containerEnvironment({
|
|
198
198
|
serviceKey: service.key,
|
|
199
199
|
containerPort: service.containerPort,
|
|
@@ -281,7 +281,7 @@ class PlatformEcsStack extends Stack {
|
|
|
281
281
|
})
|
|
282
282
|
|
|
283
283
|
// Lower priority number = evaluated first. Specific hosts before wildcards
|
|
284
|
-
// so `
|
|
284
|
+
// so `ossy.se` is not swallowed by `*.ossy.se`.
|
|
285
285
|
// Priorities are hash-stable per host — sequential 10,11,12… renumbers
|
|
286
286
|
// every insert and CloudFormation cannot swap ALB priorities in one update.
|
|
287
287
|
const usedPriorities = new Set()
|