mirror of
https://github.com/bcomnes/deploy-to-neocities.git
synced 2026-01-16 22:56:28 +00:00
Update to the latest async-neocities 4.0
BREAKING CHANGE: api_token action input is renamed to api_key, please update this BREAKING CHANGE: added a required neocities_supporter action input to toggle unsupported file filtering BREAKING CHANGE: addad a preview_before_deploy action input to toggle informational deploy plans prior to deploys BREAKING CHANGE: completely rewrote the underlying library to provide better error handling and reporting BREAKING CHANGE: Remove a bunch of real time stats and progress meters. Deploys were finishing in seconds and these were very complicated to maintain.
This commit is contained in:
parent
f9a550fd47
commit
7b14798c89
4
.github/workflows/neocities.yml
vendored
4
.github/workflows/neocities.yml
vendored
@ -32,7 +32,9 @@ jobs:
|
|||||||
- name: Deploy to neocities
|
- name: Deploy to neocities
|
||||||
uses: bcomnes/deploy-to-neocities@master # dont use master in production
|
uses: bcomnes/deploy-to-neocities@master # dont use master in production
|
||||||
with:
|
with:
|
||||||
api_token: ${{ secrets.NEOCITIES_API_TOKEN }}
|
api_key: ${{ secrets.NEOCITIES_API_TOKEN }}
|
||||||
cleanup: true
|
cleanup: true
|
||||||
dist_dir: public
|
dist_dir: public
|
||||||
protected_files: 'dropbox/*'
|
protected_files: 'dropbox/*'
|
||||||
|
neocities_supporter: true # set this to true if you have a supporter account and want to bypass unsuported files filter.
|
||||||
|
preview_before_deploy: true
|
||||||
|
|||||||
1
.gitignore
vendored
1
.gitignore
vendored
@ -5,3 +5,4 @@ public
|
|||||||
node_modules
|
node_modules
|
||||||
tmp_modules
|
tmp_modules
|
||||||
package-lock.json
|
package-lock.json
|
||||||
|
coverage
|
||||||
|
|||||||
15
README.md
15
README.md
@ -10,6 +10,8 @@
|
|||||||
|
|
||||||
Efficiently deploy a website to [Neocities][nc] using [Github actions](https://github.com/features/actions). Uses content aware diffing to only update files that changed.
|
Efficiently deploy a website to [Neocities][nc] using [Github actions](https://github.com/features/actions). Uses content aware diffing to only update files that changed.
|
||||||
|
|
||||||
|
Alternatively, you can use the bin helper in [async-neocities](https://github.com/bcomnes/async-neocities) to deploy to neocities locally from your own machine as well as in CI.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
@ -30,23 +32,26 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
# Set up any tools and build steps here
|
# Set up any tools and build steps here
|
||||||
# This example uses a Node.js toolchain to build a site
|
# This example uses a Node.js toolchain to build a site
|
||||||
- name: Use Node.js
|
- name: Use Node.js
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: lts/*
|
node-version: lts/*
|
||||||
|
# If you have a different build process, replace this with your own build steps
|
||||||
- name: Install deps and build
|
- name: Install deps and build
|
||||||
run: |
|
run: |
|
||||||
npm i
|
npm i
|
||||||
npm run build
|
npm run build
|
||||||
# When the dist_dir is ready, deploy it to neocities
|
# When the dist_dir is ready, deploy it to neocities
|
||||||
- name: Deploy to neocities
|
- name: Deploy to neocities
|
||||||
uses: bcomnes/deploy-to-neocities@v2
|
uses: bcomnes/deploy-to-neocities@v3
|
||||||
with:
|
with:
|
||||||
api_token: ${{ secrets.NEOCITIES_API_TOKEN }}
|
api_key: ${{ secrets.NEOCITIES_API_TOKEN }}
|
||||||
cleanup: false
|
cleanup: false
|
||||||
|
neocities_supporter: false # set this to true if you have a supporter account and want to bypass unsuported files filter.
|
||||||
|
preview_before_deploy: true # print a deployment plan prior to waiting for files to upload.
|
||||||
dist_dir: public
|
dist_dir: public
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -73,7 +78,9 @@ You most likely only want to run this on the `master` branch so that only change
|
|||||||
|
|
||||||
- `api_token` (**REQUIRED**): The API token for your [Neocities][nc] website to deploy to.
|
- `api_token` (**REQUIRED**): The API token for your [Neocities][nc] website to deploy to.
|
||||||
- `dist_dir`: The directory to deploy to [Neocities][nc]. Default: `public`. Don't deploy your root repo directory (e.g. `./`). It contains `.git`, `.github` and other files that won't deploy properly to neocities. Keep it clean by keeping or building your site into a subdir and deploy that.
|
- `dist_dir`: The directory to deploy to [Neocities][nc]. Default: `public`. Don't deploy your root repo directory (e.g. `./`). It contains `.git`, `.github` and other files that won't deploy properly to neocities. Keep it clean by keeping or building your site into a subdir and deploy that.
|
||||||
|
- `neocoties_supporter`: Set this to `true` if you have a paid neocities account and want to bypass the [unsupported files filter](https://neocities.org/site_files/allowed_types).
|
||||||
- `cleanup`: Boolean string (`true` or `false`). If `true`, `deploy-to-neocities` will destructively delete files found on [Neocities][nc] not found in your `dist_dir`. Default: `false`.
|
- `cleanup`: Boolean string (`true` or `false`). If `true`, `deploy-to-neocities` will destructively delete files found on [Neocities][nc] not found in your `dist_dir`. Default: `false`.
|
||||||
|
- `preview_before_deploy`: Boolean string (`true` or `false`). If `true`, `deploy-to-neocities` will print a preview of the files that will be uploaded and deleted. Default: `true`.
|
||||||
- `protected_files`: An optional glob string used to mark files as protected. Protected files are never cleaned up. Test this option out with `cleanup` set to false before relying on it. Protected files are printed when `cleanup` is set to true or false. Glob strings are processed by [minimatch](https://github.com/isaacs/minimatch) against remote neocities file paths. Protected files can still be updated.
|
- `protected_files`: An optional glob string used to mark files as protected. Protected files are never cleaned up. Test this option out with `cleanup` set to false before relying on it. Protected files are printed when `cleanup` is set to true or false. Glob strings are processed by [minimatch](https://github.com/isaacs/minimatch) against remote neocities file paths. Protected files can still be updated.
|
||||||
|
|
||||||
### Outputs
|
### Outputs
|
||||||
|
|||||||
20
action.yml
20
action.yml
@ -4,20 +4,32 @@ branding:
|
|||||||
icon: aperture
|
icon: aperture
|
||||||
color: orange
|
color: orange
|
||||||
inputs:
|
inputs:
|
||||||
api_token: # api token for site to deploy to
|
api_key: # api token for site to deploy to
|
||||||
description: 'Neocities API token for site to deploy to'
|
description: 'Neocities API key for site to deploy to'
|
||||||
required: true
|
required: true
|
||||||
dist_dir:
|
dist_dir:
|
||||||
description: 'Local folder to deploy to neocities'
|
description: 'Local folder to deploy to neocities'
|
||||||
default: 'public'
|
default: 'public'
|
||||||
required: true
|
required: true
|
||||||
|
neocities_supporter:
|
||||||
|
description: 'Set to true if you are a Neocities supporter to bypass file type upload restrictions'
|
||||||
|
default: 'false'
|
||||||
|
required: true
|
||||||
cleanup:
|
cleanup:
|
||||||
description: Delete orphaned files on neocities that don't exist in distDir
|
description: Delete orphaned files on neocities that don't exist in distDir
|
||||||
default: false
|
default: 'false'
|
||||||
required: true
|
required: true
|
||||||
|
preview_before_deploy:
|
||||||
|
description: 'Set to true if you want to print deploy preview stats prior to deploying.'
|
||||||
|
default: 'true'
|
||||||
|
required: false
|
||||||
protected_files:
|
protected_files:
|
||||||
description: A glob string that prevents matched files from ever being deleted.
|
description: A glob string that prevents matched files from ever being deleted.
|
||||||
required: false
|
required: false
|
||||||
|
api_token: # api token for site to deploy to
|
||||||
|
description: 'Neocities API key for site to deploy to'
|
||||||
|
required: false
|
||||||
|
deprecationMessage: 'api_token is deprecated, use api_key instead'
|
||||||
runs:
|
runs:
|
||||||
using: 'node20'
|
using: 'node20'
|
||||||
main: 'dist/index.js'
|
main: 'dist/index.cjs'
|
||||||
|
|||||||
28814
dist/index.js → dist/index.cjs
vendored
28814
dist/index.js → dist/index.cjs
vendored
File diff suppressed because one or more lines are too long
7
dist/index.cjs.map
vendored
Normal file
7
dist/index.cjs.map
vendored
Normal file
File diff suppressed because one or more lines are too long
7
dist/index.js.map
vendored
7
dist/index.js.map
vendored
File diff suppressed because one or more lines are too long
8237
dist/meta.json
vendored
Normal file
8237
dist/meta.json
vendored
Normal file
File diff suppressed because it is too large
Load Diff
8
eslint.config.js
Normal file
8
eslint.config.js
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import neostandard, { resolveIgnoresFromGitignore } from 'neostandard'
|
||||||
|
|
||||||
|
export default neostandard({
|
||||||
|
ignores: [
|
||||||
|
...resolveIgnoresFromGitignore(),
|
||||||
|
'dist'
|
||||||
|
],
|
||||||
|
})
|
||||||
121
index.js
121
index.js
@ -1,57 +1,84 @@
|
|||||||
const core = require('@actions/core')
|
import core from '@actions/core'
|
||||||
// const github = require('@actions/github')
|
import {
|
||||||
const Neocities = require('async-neocities')
|
NeocitiesAPIClient,
|
||||||
const path = require('path')
|
printDeployText,
|
||||||
const ms = require('ms')
|
printPreviewText,
|
||||||
const assert = require('webassert').default
|
printResultsErrorDump,
|
||||||
const fsp = require('fs').promises
|
SimpleTimer
|
||||||
const { minimatch } = require('minimatch')
|
} from 'async-neocities'
|
||||||
const { stackWithCauses } = require('pony-cause')
|
import path from 'node:path'
|
||||||
|
import assert from 'node:assert'
|
||||||
|
import fs from 'node:fs/promises'
|
||||||
|
import { minimatch } from 'minimatch'
|
||||||
|
|
||||||
let cleanup
|
async function run () {
|
||||||
|
const key = core.getInput('api_key') || core.getInput('api_token')
|
||||||
async function doDeploy () {
|
|
||||||
const token = core.getInput('api_token')
|
|
||||||
const distDir = path.join(process.cwd(), core.getInput('dist_dir'))
|
const distDir = path.join(process.cwd(), core.getInput('dist_dir'))
|
||||||
cleanup = JSON.parse(core.getInput('cleanup'))
|
const cleanup = JSON.parse(core.getInput('cleanup'))
|
||||||
|
const neocitiesSupporter = JSON.parse(core.getInput('neocities_supporter'))
|
||||||
|
const previewDeploy = JSON.parse(core.getInput('preview_before_deploy'))
|
||||||
const protectedFilesGlob = core.getInput('protected_files')
|
const protectedFilesGlob = core.getInput('protected_files')
|
||||||
|
|
||||||
assert(typeof cleanup === 'boolean', 'Cleanup input must be a boolean "true" or "false"')
|
assert(typeof cleanup === 'boolean', '`cleanup` input must be a boolean "true" or "false"')
|
||||||
const stat = await fsp.stat(distDir)
|
assert(typeof neocitiesSupporter === 'boolean', '`neocities_supporter` input must be a boolean "true" or "false"')
|
||||||
assert(stat.isDirectory(), 'dist_dir must be a directory that exists')
|
assert(typeof previewDeploy === 'boolean', '`preview_before_deploy` input must be a boolean "true" or "false"')
|
||||||
|
|
||||||
const client = new Neocities(token)
|
const stat = await fs.stat(distDir)
|
||||||
|
|
||||||
const deployOpts = {
|
assert(stat.isDirectory(), '`dist_dir` input must be a path to a directory that exists')
|
||||||
cleanup,
|
|
||||||
statsCb: Neocities.statsHandler()
|
|
||||||
}
|
|
||||||
|
|
||||||
if (protectedFilesGlob) deployOpts.protectedFileFilter = minimatch.filter(protectedFilesGlob)
|
const client = new NeocitiesAPIClient(key)
|
||||||
|
|
||||||
const stats = await client.deploy(distDir, deployOpts)
|
if (previewDeploy) {
|
||||||
|
const previewTimer = new SimpleTimer()
|
||||||
|
console.log('Running deploy preview prior to deployment...\n\n')
|
||||||
|
|
||||||
console.log(`Deployed to Neocities in ${ms(stats.time)}:`)
|
const diff = await client.previewDeploy({
|
||||||
console.log(` Uploaded ${stats.filesToUpload.length} files`)
|
directory: distDir,
|
||||||
console.log(` ${cleanup ? 'Deleted' : 'Orphaned'} ${stats.filesToDelete.length} files`)
|
includeUnsupportedFiles: neocitiesSupporter,
|
||||||
console.log(` Skipped ${stats.filesSkipped.length} files`)
|
protectedFileFilter: protectedFilesGlob ? minimatch.filter(protectedFilesGlob) : undefined
|
||||||
console.log(` ${stats.protectedFiles.length} protected files:`)
|
})
|
||||||
if (stats.protectedFiles.length) {
|
|
||||||
console.log(stats.protectedFiles)
|
previewTimer.stop()
|
||||||
}
|
|
||||||
}
|
printPreviewText({
|
||||||
|
diff,
|
||||||
doDeploy().catch(err => {
|
timer: previewTimer,
|
||||||
console.error(stackWithCauses(err))
|
cleanup,
|
||||||
if (err.stats) {
|
includeUnsupportedFiles: neocitiesSupporter
|
||||||
console.log('Files to upload: ')
|
})
|
||||||
console.dir(err.stats.filesToUpload, { colors: true, depth: 999 })
|
}
|
||||||
|
|
||||||
if (cleanup) {
|
const deployTimer = new SimpleTimer()
|
||||||
console.log('Files to delete: ')
|
console.log('Deploying to Neocities...')
|
||||||
console.dir(err.stats.filesToDelete, { colors: true, depth: 999 })
|
|
||||||
}
|
const results = await client.deploy({
|
||||||
}
|
directory: distDir,
|
||||||
|
cleanup,
|
||||||
core.setFailed(err.message)
|
includeUnsupportedFiles: neocitiesSupporter,
|
||||||
|
protectedFileFilter: protectedFilesGlob ? minimatch.filter(protectedFilesGlob) : undefined
|
||||||
|
})
|
||||||
|
|
||||||
|
deployTimer.stop()
|
||||||
|
|
||||||
|
if (results.errors.length > 0) {
|
||||||
|
printResultsErrorDump({
|
||||||
|
results,
|
||||||
|
timer: deployTimer
|
||||||
|
})
|
||||||
|
core.setFailed('The deploy completed with errors.')
|
||||||
|
} else {
|
||||||
|
printDeployText({
|
||||||
|
results,
|
||||||
|
timer: deployTimer,
|
||||||
|
cleanup,
|
||||||
|
includeUnsupportedFiles: neocitiesSupporter
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
run().catch(err => {
|
||||||
|
console.log('Unexpected error/throw during deployment:\n\n')
|
||||||
|
console.dir(err, { colors: true, depth: 999 })
|
||||||
|
core.setFailed(err instanceof Error ? err.message : `An unexpected error occurred during deployment: ${err}`)
|
||||||
})
|
})
|
||||||
|
|||||||
33
package.json
33
package.json
@ -8,25 +8,25 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/core": "1.11.1",
|
"@actions/core": "1.11.1",
|
||||||
"async-neocities": "2.1.6",
|
"async-neocities": "4.0.3",
|
||||||
"minimatch": "10.0.1",
|
"minimatch": "10.0.1"
|
||||||
"ms": "2.1.3",
|
|
||||||
"pony-cause": "^2.1.4",
|
|
||||||
"webassert": "3.0.2"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@voxpelli/tsconfig": "^15.0.0",
|
||||||
"top-bun": "^10.0.0",
|
"top-bun": "^10.0.0",
|
||||||
"auto-changelog": "^2.0.0",
|
"auto-changelog": "^2.0.0",
|
||||||
"dependency-check": "^4.1.0",
|
|
||||||
"gh-release": "^7.0.0",
|
"gh-release": "^7.0.0",
|
||||||
"npm-run-all2": "^7.0.1",
|
"npm-run-all2": "^7.0.0",
|
||||||
"standard": "^17.0.0",
|
"neostandard": "^0.11.8",
|
||||||
"esbuild": "^0.24.0"
|
"c8": "^10.0.0",
|
||||||
|
"esbuild": "~0.24.0",
|
||||||
|
"typescript": "~5.6.2"
|
||||||
},
|
},
|
||||||
"homepage": "https://github.com/bcomnes/deploy-to-neocities#readme",
|
"homepage": "https://github.com/bcomnes/deploy-to-neocities#readme",
|
||||||
"keywords": [],
|
"keywords": [],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
|
"type": "module",
|
||||||
"private": true,
|
"private": true,
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
@ -34,23 +34,20 @@
|
|||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "npm run clean && run-p build:*",
|
"build": "npm run clean && run-p build:*",
|
||||||
"build:action": "rm -rf dist && esbuild index.js --bundle --platform=node --target=node16 --sourcemap=external --outdir=dist",
|
"build:action": "rm -rf dist && esbuild index.js --bundle --platform=node --sourcemap=external --outdir=dist --metafile=dist/meta.json --out-extension:.js=.cjs",
|
||||||
"build:site": "tb --src . --dest public",
|
"build:site": "tb --src . --dest public --ignore dist,coverage",
|
||||||
|
"dist-pkg": "echo \"{ \\\"type\\\": \\\"commonjs\\\" }\" > dist/package.json",
|
||||||
"clean": "rm -rf public && mkdir -p public",
|
"clean": "rm -rf public && mkdir -p public",
|
||||||
"release": "git push --follow-tags && gh-release -y",
|
"release": "git push --follow-tags && gh-release -y",
|
||||||
"start": "npm run watch",
|
"start": "npm run watch",
|
||||||
"test": "run-s test:*",
|
"test": "run-s test:*",
|
||||||
"test:deps": "dependency-check . --no-dev --no-peer",
|
"test:lint": "eslint",
|
||||||
"test:standard": "standard",
|
"test:tsc": "tsc",
|
||||||
|
"test:node": "c8 node --test",
|
||||||
"version": "run-s version:*",
|
"version": "run-s version:*",
|
||||||
"version:build": "npm run build:action && git add dist",
|
"version:build": "npm run build:action && git add dist",
|
||||||
"version:changelog": "auto-changelog -p --template keepachangelog auto-changelog --breaking-pattern 'BREAKING CHANGE:' && git add CHANGELOG.md",
|
"version:changelog": "auto-changelog -p --template keepachangelog auto-changelog --breaking-pattern 'BREAKING CHANGE:' && git add CHANGELOG.md",
|
||||||
"watch": "npm run clean && run-p watch:*",
|
"watch": "npm run clean && run-p watch:*",
|
||||||
"watch:site": "npm run build:site -- -w"
|
"watch:site": "npm run build:site -- -w"
|
||||||
},
|
|
||||||
"standard": {
|
|
||||||
"ignore": [
|
|
||||||
"dist"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
7
test.js
7
test.js
@ -1,5 +1,6 @@
|
|||||||
const tap = require('tap')
|
import assert from 'node:assert'
|
||||||
|
import test from 'node:test'
|
||||||
|
|
||||||
tap.test('test', async t => {
|
test('test', async _t => {
|
||||||
t.ok(true)
|
assert.ok(true)
|
||||||
})
|
})
|
||||||
|
|||||||
14
tsconfig.json
Normal file
14
tsconfig.json
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"extends": "@voxpelli/tsconfig/node20.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"skipLibCheck": true
|
||||||
|
},
|
||||||
|
"include": [
|
||||||
|
"**/*"
|
||||||
|
],
|
||||||
|
"exclude": [
|
||||||
|
"node_modules",
|
||||||
|
"public",
|
||||||
|
"dist"
|
||||||
|
]
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user