|
@ -1,5 +0,0 @@
|
||||||
/node_modules
|
|
||||||
/static/feeds/*
|
|
||||||
!/static/feeds/.gitkeep
|
|
||||||
/static/alternate/*
|
|
||||||
!/static/alternate/.gitkeep
|
|
|
@ -1,16 +1,140 @@
|
||||||
on: push
|
on: push
|
||||||
jobs:
|
jobs:
|
||||||
main:
|
insiders-build:
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
os: [windows, macos, ubuntu]
|
||||||
|
include:
|
||||||
|
- os: windows
|
||||||
|
build: npx caxa --directory . --command "{{caxa}}/node_modules/.bin/node" "{{caxa}}/lib/index.js" --output "CourseLore--windows--${{ github.sha }}.exe"
|
||||||
|
artifact: CourseLore--windows--${{ github.sha }}.exe
|
||||||
|
- os: macos
|
||||||
|
build: |
|
||||||
|
npx caxa --directory . --command "{{caxa}}/node_modules/.bin/node" "{{caxa}}/lib/index.js" --output "CourseLore.app"
|
||||||
|
tar -czf "CourseLore--macos--${{ github.sha }}.app.tgz" "CourseLore.app"
|
||||||
|
artifact: CourseLore--macos--${{ github.sha }}.app.tgz
|
||||||
|
- os: ubuntu
|
||||||
|
build: |
|
||||||
|
npx caxa --directory . --command "{{caxa}}/node_modules/.bin/node" "{{caxa}}/lib/index.js" --output "courselore"
|
||||||
|
tar -czf "courselore--linux--${{ github.sha }}.tgz" "courselore"
|
||||||
|
artifact: courselore--linux--${{ github.sha }}.tgz
|
||||||
|
runs-on: ${{ matrix.os }}-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- uses: actions/setup-node@v1
|
||||||
|
with:
|
||||||
|
node-version: 15
|
||||||
|
- run: |
|
||||||
|
npm ci
|
||||||
|
${{ matrix.build }}
|
||||||
|
- uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: ${{ matrix.artifact }}
|
||||||
|
path: ${{ matrix.artifact }}
|
||||||
|
|
||||||
|
test:
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
os: [windows, macos, ubuntu]
|
||||||
|
runs-on: ${{ matrix.os }}-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- uses: actions/setup-node@v1
|
||||||
|
with:
|
||||||
|
node-version: 15
|
||||||
|
- run: npm install-ci-test
|
||||||
|
|
||||||
|
deploy:
|
||||||
|
if: github.ref == 'refs/heads/master'
|
||||||
|
needs: [insiders-build, test]
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: webfactory/ssh-agent@v0.5.0
|
||||||
|
with:
|
||||||
|
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- uses: actions/download-artifact@v2
|
||||||
|
with:
|
||||||
|
name: courselore--linux--${{ github.sha }}.tgz
|
||||||
|
- run: |
|
||||||
|
tar -xzf courselore--linux--${{ github.sha }}.tgz
|
||||||
|
|
||||||
|
cat >> ~/.ssh/known_hosts << "EOF"
|
||||||
|
courselore.org ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDWOjzHPP1v+6gEeRAVzEB7l/RH+mt31heowjiUVNjgTnpT1FDL/T4yqmztwPrzhXUdBAy7M16H+88Padxm+/rJ5qfbw2dH7KtOA4RALYy9ruBl6HFdCf59eh01A97Py/AmxlpXysGAVcdcVjLsr0PvfoEGOqMlohc0sBjCjhoFcqkP9P57Q4Q3gcqgwjNYaZ1BSbI2G6J6kihjN7+b8pFCHCw8fqs7xo+7pDUv/rvqfBTUAFV7sovwQU0bZK6Z8gWXYFGG0NpKVojsKOHCrZpM8pBBDmleisrJhXmnKQ+Lj/JvYuaEM6cHZh6+RH7ua6S9eqlL8EErXf7GZ4SPuTo1ghNJ5H9cR3k8Px4Op5bDIIdPP767jwGHabZJ5Z8l9QnQajq85gcE7E3vZ1yT2BDKQsIDJeNpg1etTgw6hSUlBQsKx8TNaI9nROSnKwKbSI+sGmZlwrx11XimEkvaMaFmSZfpN+ne/2kmjc81Pr0WKb82sIPf3X2KzmWeChkZus8=
|
||||||
|
courselore.org ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBOIhUnh2H/733XnnD4mvaEqKbxbEc9ov3UhlbG7gkQS7vM5TaSSuknZLOGUIx2VWB681y4jn4vG3Wsja9JYPCB0=
|
||||||
|
courselore.org ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBCGyIA9/oiJt/qrQNeNoIRNKA8CFc/ppPMnrtw2NW+7
|
||||||
|
EOF
|
||||||
|
|
||||||
|
ssh root@courselore.org "mkdir -p courselore"
|
||||||
|
rsync -a courselore root@courselore.org:courselore/courselore
|
||||||
|
rsync -a --delete customization-example/ root@courselore.org:courselore/customization/
|
||||||
|
rsync -a deployment-example/configuration.js root@courselore.org:courselore/configuration.js
|
||||||
|
rsync -a deployment-example/courselore.service root@courselore.org:/etc/systemd/system/courselore.service
|
||||||
|
|
||||||
|
ssh root@courselore.org << "EOF"
|
||||||
|
systemctl daemon-reload
|
||||||
|
systemctl enable courselore
|
||||||
|
systemctl restart courselore
|
||||||
|
EOF
|
||||||
|
|
||||||
|
npm-publish:
|
||||||
|
if: startsWith(github.ref, 'refs/tags/v')
|
||||||
|
needs: test
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- uses: webfactory/ssh-agent@v0.4.1
|
|
||||||
if: github.ref == 'refs/heads/master'
|
|
||||||
with:
|
|
||||||
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
|
|
||||||
- uses: actions/setup-node@v1
|
- uses: actions/setup-node@v1
|
||||||
with:
|
with:
|
||||||
node-version: 14
|
node-version: 15
|
||||||
- run: npm install-ci-test
|
registry-url: https://registry.npmjs.org/
|
||||||
- run: npm run deploy
|
- run: npm ci && npm publish
|
||||||
if: github.ref == 'refs/heads/master'
|
env:
|
||||||
|
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||||
|
|
||||||
|
release:
|
||||||
|
if: startsWith(github.ref, 'refs/tags/v')
|
||||||
|
needs: [insiders-build, test]
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/download-artifact@v2
|
||||||
|
with:
|
||||||
|
name: CourseLore--windows--${{ github.sha }}.exe
|
||||||
|
- uses: actions/download-artifact@v2
|
||||||
|
with:
|
||||||
|
name: CourseLore--macos--${{ github.sha }}.app.tgz
|
||||||
|
- uses: actions/download-artifact@v2
|
||||||
|
with:
|
||||||
|
name: courselore--linux--${{ github.sha }}.tgz
|
||||||
|
- run: echo "::set-output name=tag::${GITHUB_REF#refs/tags/}"
|
||||||
|
id: tag
|
||||||
|
- uses: actions/create-release@v1
|
||||||
|
id: create-release
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
with:
|
||||||
|
tag_name: ${{ steps.tag.outputs.tag }}
|
||||||
|
release_name: Release ${{ steps.tag.outputs.tag }}
|
||||||
|
- uses: actions/upload-release-asset@v1
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
with:
|
||||||
|
upload_url: ${{ steps.create-release.outputs.upload_url }}
|
||||||
|
asset_path: CourseLore--windows--${{ github.sha }}.exe
|
||||||
|
asset_name: CourseLore--windows--${{ steps.tag.outputs.tag }}.exe
|
||||||
|
asset_content_type: application/vnd.microsoft.portable-executable
|
||||||
|
- uses: actions/upload-release-asset@v1
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
with:
|
||||||
|
upload_url: ${{ steps.create-release.outputs.upload_url }}
|
||||||
|
asset_path: CourseLore--macos--${{ github.sha }}.app.tgz
|
||||||
|
asset_name: CourseLore--macos--${{ steps.tag.outputs.tag }}.app.tgz
|
||||||
|
asset_content_type: application/gzip
|
||||||
|
- uses: actions/upload-release-asset@v1
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
with:
|
||||||
|
upload_url: ${{ steps.create-release.outputs.upload_url }}
|
||||||
|
asset_path: courselore--linux--${{ github.sha }}.tgz
|
||||||
|
asset_name: courselore--linux--${{ steps.tag.outputs.tag }}.tgz
|
||||||
|
asset_content_type: application/gzip
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
/node_modules/
|
/node_modules/
|
||||||
/static/feeds/*
|
/lib/
|
||||||
!/static/feeds/.gitkeep
|
/kill-the-newsletter.db
|
||||||
/static/alternate/*
|
|
||||||
!/static/alternate/.gitkeep
|
|
||||||
|
|
|
@ -1,2 +0,0 @@
|
||||||
/static/typeface-pt-sans/
|
|
||||||
/static/typeface-pt-mono/
|
|
|
@ -1,7 +0,0 @@
|
||||||
kill-the-newsletter.com {
|
|
||||||
reverse_proxy localhost:8000
|
|
||||||
}
|
|
||||||
|
|
||||||
www.kill-the-newsletter.com {
|
|
||||||
redir https://kill-the-newsletter.com{uri}
|
|
||||||
}
|
|
21
Dockerfile
|
@ -1,21 +0,0 @@
|
||||||
FROM node:latest
|
|
||||||
|
|
||||||
WORKDIR /kill-the-newsletter
|
|
||||||
|
|
||||||
COPY package*.json ./
|
|
||||||
RUN npm ci --production
|
|
||||||
COPY . .
|
|
||||||
|
|
||||||
VOLUME /kill-the-newsletter/static/feeds/
|
|
||||||
VOLUME /kill-the-newsletter/static/alternate/
|
|
||||||
|
|
||||||
ENV WEB_PORT=8000
|
|
||||||
ENV EMAIL_PORT=2525
|
|
||||||
ENV BASE_URL=http://localhost:8000
|
|
||||||
ENV EMAIL_DOMAIN=localhost
|
|
||||||
ENV ISSUE_REPORT=mailto:kill-the-newsletter@leafac.com
|
|
||||||
|
|
||||||
EXPOSE 8000
|
|
||||||
EXPOSE 2525
|
|
||||||
|
|
||||||
CMD npm start
|
|
127
package.json
|
@ -1,81 +1,56 @@
|
||||||
{
|
|
||||||
"scripts": {
|
|
||||||
"start": "ts-node .",
|
|
||||||
"develop": "nodemon --ext ts --exec \"ts-node .\"",
|
|
||||||
"test": "prettier --check \"**/*.{ts,css}\" --end-of-line auto && jest",
|
|
||||||
"deploy": "pm2 deploy package.json production",
|
|
||||||
"deploy:setup": "pm2 deploy package.json production setup"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"@types/express": "^4.17.3",
|
|
||||||
"@types/jsdom": "^16.2.1",
|
|
||||||
"@types/mailparser": "^2.7.2",
|
|
||||||
"@types/node": "^13.9.8",
|
|
||||||
"@types/smtp-server": "^3.5.4",
|
|
||||||
"@types/write-file-atomic": "^3.0.0",
|
|
||||||
"caddy-npm": "^2.1.1",
|
|
||||||
"crypto-random-string": "^3.2.0",
|
|
||||||
"entities": "^2.0.0",
|
|
||||||
"escape-string-regexp": "^4.0.0",
|
|
||||||
"express": "^4.17.1",
|
|
||||||
"jsdom": "^16.2.2",
|
|
||||||
"mailparser": "^2.7.7",
|
|
||||||
"pm2": "^4.2.3",
|
|
||||||
"sanitize-xml-string": "^1.1.0",
|
|
||||||
"smtp-server": "^3.6.0",
|
|
||||||
"tagged-template-noop": "^2.1.1",
|
|
||||||
"ts-node": "^8.10.1",
|
|
||||||
"typescript": "^3.8.3",
|
|
||||||
"write-file-atomic": "^3.0.3"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@types/jest": "^25.1.4",
|
|
||||||
"@types/nodemailer": "^6.4.0",
|
|
||||||
"@types/qs": "^6.9.1",
|
|
||||||
"axios": "^0.21.1",
|
|
||||||
"jest": "^25.2.4",
|
|
||||||
"nodemailer": "^6.4.6",
|
|
||||||
"nodemon": "^2.0.2",
|
|
||||||
"prettier": "^2.0.2",
|
|
||||||
"qs": "^6.9.3",
|
|
||||||
"ts-jest": "^25.5.0"
|
|
||||||
},
|
|
||||||
"jest": {
|
|
||||||
"preset": "ts-jest",
|
|
||||||
"testEnvironment": "node"
|
|
||||||
},
|
|
||||||
"apps": [
|
|
||||||
{
|
{
|
||||||
"name": "kill-the-newsletter",
|
"name": "kill-the-newsletter",
|
||||||
"script": "npm start",
|
"version": "0.0.0",
|
||||||
"env": {
|
"description": "Convert email newsletters into Atom feeds",
|
||||||
"NODE_ENV": "production",
|
"main": "lib/index.js",
|
||||||
"WEB_PORT": "8000",
|
"types": "lib/index.d.ts",
|
||||||
"EMAIL_PORT": "25",
|
"bin": "lib/index.js",
|
||||||
"BASE_URL": "https://kill-the-newsletter.com",
|
"repository": "leafac/kill-the-newsletter",
|
||||||
"EMAIL_DOMAIN": "kill-the-newsletter.com",
|
"keywords": [
|
||||||
"ISSUE_REPORT": "mailto:kill-the-newsletter@leafac.com"
|
"newsletter",
|
||||||
}
|
"atom feeds",
|
||||||
},
|
"news"
|
||||||
{
|
|
||||||
"name": "caddy",
|
|
||||||
"script": "caddy run"
|
|
||||||
}
|
|
||||||
],
|
],
|
||||||
"deploy": {
|
"author": "Leandro Facchinetti <kill-the-newsletter@leafac.com> (https://leafac.com)",
|
||||||
"production": {
|
"license": "MIT",
|
||||||
"user": "root",
|
"bugs": "https://github.com/leafac/kill-the-newsletter/issues",
|
||||||
"host": "kill-the-newsletter.com",
|
"homepage": "https://github.com/leafac/kill-the-newsletter#readme",
|
||||||
"ref": "origin/master",
|
"scripts": {
|
||||||
"repo": "git@github.com:leafac/kill-the-newsletter.com.git",
|
"start": "ts-node-dev --poll src/index.ts",
|
||||||
"path": "/root/kill-the-newsletter.com",
|
"test": "prettier --check \"src/**/*\" --end-of-line auto && jest",
|
||||||
"pre-setup": "(curl -sL https://deb.nodesource.com/setup_14.x | bash -) && apt install -y nodejs build-essential && (ssh -o StrictHostKeyChecking=no git@github.com || true)",
|
"prepare": "tsc"
|
||||||
"post-setup": "npm ci --production && npx pm2 startup",
|
},
|
||||||
"post-deploy": "npm ci --production && npx pm2 startOrRestart package.json && npx pm2 save",
|
"dependencies": {
|
||||||
"ssh_options": [
|
"@leafac/css": "^0.0.1",
|
||||||
"ForwardAgent=yes",
|
"@leafac/html": "^1.3.0",
|
||||||
"StrictHostKeyChecking=no"
|
"@leafac/sqlite": "^1.1.2",
|
||||||
]
|
"@leafac/sqlite-migration": "^1.0.3",
|
||||||
}
|
"crypto-random-string": "^3.3.1",
|
||||||
|
"escape-string-regexp": "^4.0.0",
|
||||||
|
"express": "^4.17.1",
|
||||||
|
"mailparser": "^3.1.0",
|
||||||
|
"smtp-server": "^3.8.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/express": "^4.17.11",
|
||||||
|
"@types/jest": "^26.0.20",
|
||||||
|
"@types/mailparser": "^3.0.2",
|
||||||
|
"@types/node": "^14.14.33",
|
||||||
|
"@types/nodemailer": "^6.4.0",
|
||||||
|
"@types/smtp-server": "^3.5.6",
|
||||||
|
"caxa": "^1.0.0",
|
||||||
|
"got": "^11.8.2",
|
||||||
|
"jest": "^26.6.3",
|
||||||
|
"nodemailer": "^6.4.18",
|
||||||
|
"prettier": "^2.2.1",
|
||||||
|
"ts-jest": "^26.5.3",
|
||||||
|
"ts-node": "^9.1.1",
|
||||||
|
"ts-node-dev": "^1.1.6",
|
||||||
|
"typescript": "^4.2.3"
|
||||||
|
},
|
||||||
|
"jest": {
|
||||||
|
"rootDir": "src",
|
||||||
|
"preset": "ts-jest",
|
||||||
|
"testEnvironment": "node"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Before Width: | Height: | Size: 427 B After Width: | Height: | Size: 427 B |
Before Width: | Height: | Size: 985 B After Width: | Height: | Size: 985 B |
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 5.3 KiB |
Before Width: | Height: | Size: 5.8 KiB After Width: | Height: | Size: 5.8 KiB |
Before Width: | Height: | Size: 5.8 KiB After Width: | Height: | Size: 5.8 KiB |
Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 5.2 KiB |
|
@ -1,8 +1,16 @@
|
||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
|
"rootDir": "src",
|
||||||
|
"outDir": "lib",
|
||||||
|
|
||||||
"target": "ES2019",
|
"target": "ES2019",
|
||||||
"module": "commonjs",
|
"module": "commonjs",
|
||||||
"strict": true,
|
"esModuleInterop": true,
|
||||||
"esModuleInterop": true
|
|
||||||
|
"declaration": true,
|
||||||
|
"declarationMap": true,
|
||||||
|
"sourceMap": true,
|
||||||
|
|
||||||
|
"strict": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|