Compare commits

...

80 Commits

Author SHA1 Message Date
Sam Kirkland
8e83cea867 v4.3.5 2024-03-02 00:37:46 -06:00
Davide Trainini
c15ea8f529
Update migration.md (#389)
Improved pagination, add missing punctuation, delete useless separation lines, improve bullet lists, add link to README and releases page
2023-03-23 11:06:48 -05:00
Sam Kirkland
8a24039354
v4.3.4 (#385)
- updated basic-ftp
- new vx.x.x tags
2023-03-15 00:50:07 -05:00
Sam Kirkland
89e533f02c
Merge pull request #352 from Trainax/glob-tester-link-fix
Glob tester README link fix
2023-02-28 20:23:56 -06:00
Sam Kirkland
cf1b406626
Update README.md 2023-02-28 20:22:37 -06:00
Sam Kirkland
60edb12d91
Merge pull request #342 from Trainax/master
Update actions/checkout to v3
2023-01-20 01:23:24 -06:00
Davide Trainini
28fb6c755c
Glob tester README link fix 2022-12-15 17:42:38 +01:00
Davide Trainini
08c527ecdf Update actions/checkout to v3 2022-12-08 18:47:03 +01:00
Sam Kirkland
cfcb39fa3c
Merge pull request #321 from wcoder/patch-1
Update default timeout info
2022-12-02 10:45:56 -06:00
SamKirkland
1d198bef28 v4.3.3 2022-12-02 10:44:37 -06:00
Sam Kirkland
b8e4443bb0
Merge pull request #338 from the-snowwhite/nodejs_update
Update from node12 to node16
2022-12-02 10:30:34 -06:00
the-snowwhite
84f66893ce Update from node12 to node16
Signed-off-by: the-snowwhite <producer@holotronic.dk>
2022-11-18 21:07:09 +01:00
Yauheni Pakala
0734c4dc18
Update default timeout info
Based on latest 3c410ee1b4/README.md
2022-09-12 23:26:17 +03:00
SamKirkland
ec28745b59 blue marketplace icon 2022-09-03 17:40:42 -05:00
SamKirkland
1b21034a8d v4.3.2 2022-09-03 17:37:57 -05:00
Sam Kirkland
ed91728692
Merge pull request #317 from Marvimoto/patch-1
Add timeout to valid inputs to resolve #316
2022-08-30 09:06:05 -05:00
Marvimoto
118eb423de
Add timeout to valid inputs 2022-08-29 19:14:03 +02:00
Sam Kirkland
e8964f3093
Merge pull request #313 from SamKirkland/4.3.1
4.3.1
2022-08-21 21:28:39 -05:00
SamKirkland
f458cc0704 Merge branch 'master' into 4.3.1 2022-08-21 21:24:37 -05:00
Sam Kirkland
01dea7c17f
Merge pull request #282 from unverbraucht/master
Allow setting the timeout.
2022-08-21 21:24:08 -05:00
SamKirkland
16956be3a6 4.3.1 release
Upgrade basic-ftp library
Update npm libraries
Resolves #308
2022-08-21 21:21:46 -05:00
Kevin Read
4f0dc298db Allow setting the timeout. 2022-04-19 14:36:22 +02:00
Sam Kirkland
d0aa838726
Merge pull request #265 from SamKirkland/v4.3.0-beta
Version 4.3.0
2022-02-19 15:06:06 -06:00
SamKirkland
f55279346a exclude defaults bug fix 2022-01-31 00:44:08 -06:00
SamKirkland
93a0898871 rolling back nested exclude path 2022-01-31 00:11:43 -06:00
SamKirkland
1d31526b7a v4.3.0 2022-01-30 23:37:43 -06:00
SamKirkland
d3fa328f10 550 bug fix 2022-01-30 23:36:06 -06:00
Sam Kirkland
d6ad227aa5
readme example - node version bump (12 -> 14) 2021-12-09 22:26:03 -06:00
SamKirkland
c7bb3d9877 removing clean state 2021-11-22 10:34:05 -06:00
SamKirkland
a7da5e54d2 fixing tests 2021-11-22 10:31:59 -06:00
Sam Kirkland
a9644610a0
Merge pull request #245 from SamKirkland/v4.2.0-beta
V4.2.0
2021-11-22 10:13:59 -06:00
SamKirkland
825d1b8f3b allowing no ecludes 2021-11-13 16:42:30 -06:00
SamKirkland
ba86a1bf13 v4.2.0 beta
- fixes for 550 folder issue
- updated excludes option format
2021-10-13 01:18:45 -05:00
Sam Kirkland
65c6a8f943
Add link to glob testing tool to readme
Fixes #179
2021-06-23 09:11:21 -05:00
Sam Kirkland
d2724c6194
Update ftps.yml 2021-06-23 00:22:15 -05:00
SamKirkland
59992de6c6 v4.1.0
Cert issue - Fixes #149 and Fixes #127
Exceptions now bubble up - Fixes #123
Resolves local-dir incorrect usage - Fixes #145
2021-06-22 23:59:51 -05:00
SamKirkland
408fa95d1f readme: checkout version update 2021-05-16 23:20:17 -05:00
SamKirkland
223d805d5b Reduce image sizes 2021-05-16 23:11:26 -05:00
SamKirkland
3695ee6be8 exclude git example update 2021-05-16 23:06:44 -05:00
Sam Kirkland
ca38d85340
Merge pull request #187 from clarkchentw/patch-1
Fix typo
2021-05-16 23:03:11 -05:00
Clark Chen
a7d2862205
Fix typo 2021-05-09 12:52:30 -05:00
Sam Kirkland
1cffb780cf
Fixing readme local-dir description
fixes #136
2020-12-02 00:16:48 -06:00
Sam Kirkland
2d118d9190
Adding example for exclude 2020-11-23 10:11:50 -06:00
SamKirkland
2a4e9b1312 Resolving sync state issue, added tests
fixes #124
fixes #122
fixes #120
2020-11-23 01:22:34 -06:00
Sam Kirkland
bc95d3edc3
Merge pull request #119 from SamKirkland/4.0.1-patch
4.0.1 patch
2020-11-13 13:58:32 -06:00
SamKirkland
5aee445d73 Update index.js 2020-11-13 13:49:44 -06:00
SamKirkland
3384765d40 removing array log 2020-11-13 13:49:12 -06:00
SamKirkland
6d1a190aef Fixing server sync state location 2020-11-13 13:42:37 -06:00
SamKirkland
8da6fdde60 exclude param - array parsing 2020-11-13 13:25:32 -06:00
SamKirkland
f0ef8012ea local-dir path, excludes param logging 2020-11-13 12:12:25 -06:00
Sam Kirkland
649aa38be8
Merge pull request #117 from SamKirkland/beta-v4
Version 4.0.0
2020-11-13 01:07:57 -06:00
SamKirkland
07d05bff14 version 4 2020-11-13 00:32:29 -06:00
SamKirkland
26175f3bf0 Added badge section 2020-10-25 01:55:55 -05:00
SamKirkland
63b04d6546 updated ftp-deploy with dryrun patch 2020-10-25 00:41:02 -05:00
SamKirkland
928e32c59b back to building with ncc 2020-10-24 00:56:44 -05:00
SamKirkland
c14c34b02c updated ftp-deploy version 2020-10-23 23:41:37 -05:00
SamKirkland
b6b6e42be5 updating ftp-deploy to v0.9.6 2020-09-07 14:57:56 -05:00
SamKirkland
62b6382e92 ftp-deploy update
solved caching issue
updated ftp-deploy library
2020-09-05 01:33:58 -05:00
SamKirkland
c6e7e7c2db Fixed another quote 2020-08-30 23:49:59 -05:00
SamKirkland
64416173e6 fixing yaml quote 2020-08-30 23:45:46 -05:00
SamKirkland
81ee749b94 updating readme 2020-08-30 23:25:49 -05:00
SamKirkland
a923da71e8 updating package 2020-08-30 00:17:42 -05:00
SamKirkland
4fe6844638 more optional props 2020-08-30 00:05:41 -05:00
SamKirkland
fc9de49cd2 import fix, pacakge updates 2020-08-28 01:11:57 -05:00
SamKirkland
afd59edb41 hooked up additional props
added npm badges
Updated readme
2020-08-27 23:43:10 -05:00
SamKirkland
64fd8ab1ea Merge branch 'beta-v4' of https://github.com/SamKirkland/FTP-Deploy-Action into beta-v4 2020-08-27 23:30:48 -05:00
Sam Kirkland
b87fb43f2d
Update index.js 2020-08-26 01:53:25 -05:00
SamKirkland
9e3379feb0 Update index.js 2020-08-26 01:48:20 -05:00
Sam Kirkland
6d051eb8e8
Update README.md 2020-08-26 01:40:07 -05:00
SamKirkland
3576f3af9c v4 beta 2020-08-26 01:28:40 -05:00
Sam Kirkland
1053c3278e
Merge pull request #93 from tflight/patch-2
Add pbcopy tip for macOS users
2020-07-17 18:32:31 -05:00
tflight
acdf4a21c3
Add pbcopy tip for macOS users
This copies the key directly to your clipboard on macOS.
2020-07-17 11:14:16 -04:00
Sam Kirkland
79e6bdd312
Merge pull request #81 from ciex/master
Fix problem setting up known-hosts
2020-07-16 11:09:30 -05:00
Vincent Ahrend
4aadb4a381 Fix known hosts example to include known-hosts arg 2020-06-05 14:32:27 +02:00
Vincent Ahrend
c47227925c Fix missing argument in action.yml 2020-06-05 14:29:03 +02:00
SamKirkland
da0d77ff39 v3.1.1
Bug fix: argument escaping for spaces within passwords
2020-05-17 17:28:14 -05:00
SamKirkland
1af692f7d5 Updating linux testing instructions 2020-05-17 17:25:20 -05:00
SamKirkland
ae5262e007 using act for local debugging
Added act library for local debugging
Attempting to use exec argument escaping
2020-05-17 16:57:25 -05:00
Sam Kirkland
b698c49eac
Merge pull request #72 from Helias/patch-1
Add Linux istructions
2020-05-07 00:25:44 -05:00
Stefano Borzì
ccf756b42e
Add Linux istructions 2020-05-06 18:21:47 +02:00
28 changed files with 13777 additions and 5906 deletions

2
.eslintignore Normal file
View File

@ -0,0 +1,2 @@
dist/
node_modules/

56
.eslintrc.json Normal file
View File

@ -0,0 +1,56 @@
{
"plugins": [
"jest",
"@typescript-eslint"
],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": 8,
"sourceType": "module",
"project": "./tsconfig.json"
},
"rules": {
"eslint-comments/no-use": "off",
"import/no-namespace": "off",
"no-unused-vars": "off",
"@typescript-eslint/no-unused-vars": "error",
"@typescript-eslint/explicit-member-accessibility": [
"error",
{
"accessibility": "no-public"
}
],
"@typescript-eslint/no-require-imports": "error",
"@typescript-eslint/array-type": "error",
"@typescript-eslint/await-thenable": "error",
"@typescript-eslint/func-call-spacing": [
"error",
"never"
],
"@typescript-eslint/no-array-constructor": "error",
"@typescript-eslint/no-empty-interface": "error",
"@typescript-eslint/no-extraneous-class": "error",
"@typescript-eslint/no-for-in-array": "error",
"@typescript-eslint/no-inferrable-types": "error",
"@typescript-eslint/no-misused-new": "error",
"@typescript-eslint/no-namespace": "error",
"@typescript-eslint/no-non-null-assertion": "warn",
"@typescript-eslint/no-unnecessary-qualifier": "error",
"@typescript-eslint/no-unnecessary-type-assertion": "error",
"@typescript-eslint/no-useless-constructor": "error",
"@typescript-eslint/no-var-requires": "error",
"@typescript-eslint/prefer-for-of": "warn",
"@typescript-eslint/prefer-function-type": "warn",
"@typescript-eslint/prefer-includes": "error",
"@typescript-eslint/prefer-string-starts-ends-with": "error",
"@typescript-eslint/promise-function-async": "error",
"@typescript-eslint/require-array-sort-compare": "error",
"@typescript-eslint/restrict-plus-operands": "error",
"@typescript-eslint/type-annotation-spacing": "error"
},
"env": {
"node": true,
"es6": true,
"jest/globals": true
}
}

2
.gitattributes vendored
View File

@ -1,2 +0,0 @@
# Auto detect text files and perform LF normalization
* text=auto

View File

@ -12,12 +12,16 @@ A clear and concise description of what the bug is.
**My Action Config**
```yaml
on:
push:
on: push
name: Publish Website
jobs:
web-deploy:
name: 🚀 Deploy website every commit
# !!!!!!! TODO Fill Out !!!!!!!
```
**My Action Log**
```
# Paste Log here
# you may want enable verbose logging with log-level: verbose
```

20
.github/workflows/ftp.yml vendored Normal file
View File

@ -0,0 +1,20 @@
name: FTP Test
on:
push:
branches: [master]
jobs:
deploy:
name: 🚀 Deploy website every commit
runs-on: ubuntu-latest
steps:
- name: 🚚 Get latest code
uses: actions/checkout@v4
- name: 📂 Sync files
uses: ./
with:
server: ftp.samkirkland.com
username: test@samkirkland.com
password: ${{ secrets.ftp_password }}

21
.github/workflows/ftps.yml vendored Normal file
View File

@ -0,0 +1,21 @@
name: FTPS Test
on:
push:
branches: [master]
jobs:
deploy:
name: 🚀 Deploy website every commit
runs-on: ubuntu-latest
steps:
- name: 🚚 Get latest code
uses: actions/checkout@v4
- name: 📂 Sync files
uses: ./
with:
server: ftp.samkirkland.com
username: test@samkirkland.com
password: ${{ secrets.ftp_password }}
protocol: ftps

View File

@ -1,16 +0,0 @@
on: push
name: Test FTP Deploy
jobs:
FTP-Deploy-Action:
name: FTP-Deploy-Action
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2.1.0
with:
fetch-depth: 2
- name: FTP-Deploy-Action
uses: SamKirkland/FTP-Deploy-Action@master
with:
ftp-server: ftp://ftp.samkirkland.com/
ftp-username: ${{ secrets.ftp_username }}
ftp-password: ${{ secrets.ftp_password }}

View File

@ -1,18 +0,0 @@
on: push
name: Test SFTP Deploy
jobs:
FTP-Deploy-Action:
name: FTP-Deploy-Action
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2.1.0
with:
fetch-depth: 2
- name: FTP-Deploy-Action
uses: SamKirkland/FTP-Deploy-Action@master
with:
# deploy to a folder named "sftp-deploy-test.samkirkland.com" on my server
ftp-server: sftp://ftp.samkirkland.com:7822/home/samkirkland/sftp-deploy-test.samkirkland.com/
ftp-username: ${{ secrets.sftp_username }}
ftp-password: ${{ secrets.sftp_password }}
git-ftp-args: --insecure

10
.gitignore vendored
View File

@ -1,7 +1,5 @@
__tests__/runner/*
# comment out in distribution branches
node_modules/
# Dependency directory
node_modules
# Rest pulled from https://github.com/github/gitignore/blob/master/Node.gitignore
# Logs
@ -91,3 +89,7 @@ typings/
# DynamoDB Local files
.dynamodb/
# OS metadata
.DS_Store
Thumbs.db

View File

@ -1,5 +0,0 @@
{
"files.exclude": {
"**/node_modules": true
}
}

View File

@ -1,14 +0,0 @@
FROM debian:stable-slim
LABEL repository="https://github.com/SamKirkland/FTP-Deploy-Action"
LABEL maintainer="Sam Kirkland <FTP-Deploy-Action@samkirkland.com>"
RUN apt-get update
RUN apt-get install -y git
RUN apt-get install -y git-ftp
RUN apt-get install -y nodejs
COPY dist/index.js /deploy.js
RUN chmod +x deploy.js
ENTRYPOINT ["node", "../../deploy.js"]

535
README.md
View File

@ -1,335 +1,238 @@
<p align="center">
<img alt="FTP Deploy - Continuous integration for everyone" src="images/ftp-upload-logo-small.png">
<img alt="FTP Deploy Action - Continuous integration for everyone" src="images/ftp-deploy-logo-small.png">
</p>
Automate deploying websites and more with this GitHub action
Automate deploying websites and more with this GitHub action. **It's free!**
![Test FTP Deploy](https://github.com/SamKirkland/FTP-Deploy-Action/workflows/Test%20FTP%20Deploy/badge.svg) ![Test SFTP Deploy](https://github.com/SamKirkland/FTP-Deploy-Action/workflows/Test%20SFTP%20Deploy/badge.svg)
![FTP test](https://github.com/SamKirkland/FTP-Deploy-Action/workflows/FTP%20Test/badge.svg)
![FTPS test](https://github.com/SamKirkland/FTP-Deploy-Action/workflows/FTPS%20Test/badge.svg)
---
### Usage Example
Place the following in `Your_Project/.github/workflows/main.yml`
Place the following in `/.github/workflows/main.yml`
```yml
on: push
name: Publish Website
name: 🚀 Deploy website on push
jobs:
FTP-Deploy-Action:
name: FTP-Deploy-Action
web-deploy:
name: 🎉 Deploy
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2.1.0
- name: 🚚 Get latest code
uses: actions/checkout@v4
- name: 📂 Sync files
uses: SamKirkland/FTP-Deploy-Action@v4.3.5
with:
fetch-depth: 2
- name: FTP-Deploy-Action
uses: SamKirkland/FTP-Deploy-Action@3.1.0
with:
ftp-server: ftp://ftp.samkirkland.com/
ftp-username: myFtpUserName
ftp-password: ${{ secrets.FTP_PASSWORD }}
server: ftp.samkirkland.com
username: myFtpUserName
password: ${{ secrets.ftp_password }}
```
---
### Requirements
- You must have ftp access to your server. If your host allows or requires ssh please use my [web-deploy](https://github.com/SamKirkland/web-deploy) action
- Some web hosts change the default port (21), check with your host for your port number
---
### Setup Steps
1. Select the repository you want to add the action to
2. Select the `Actions` tab
3. Select `Blank workflow file` or `Set up a workflow yourself`, if you don't see these options manually create a yaml file `Your_Project/.github/workflows/main.yml`
4. Paste the example above into your yaml file and save
5. Now you need to add a key to the `secrets` section in your project. To add a `secret` go to the `Settings` tab in your project then select `Secrets`. Add a new `Secret` for `ftp-password`
5. Now you need to add a key to the `secrets` section in your project. To add a `secret` go to the `Settings` tab in your project then select `Secrets`. Add a new `Secret` for `password`
6. Update your yaml file settings
__Note: Only tracked files will be published by default. If you want to publish files that don't exist in github (example: files generated during the action run) you must add those files/folders to `.git-ftp-include`__
Migrating from v2? See the [migration guide](v2-v3-migration.md)
7. If you appreciate this github action give it a :star: or show off with one of the [badges below](#badge).
---
### Settings
Keys can be added directly to your .yml config file or referenced from your project `Secrets` storage.
To add a `secret` go to the `Settings` tab in your project then select `Secrets`.
I recommend you store your `ftp-password` as a secret.
I strongly recommend you store your `password` as a secret.
| Key Name | Required? | Example | Default | Description |
|----------------|-----------|-----------------------------------------------|---------|----------------------------------------------------------|
| `ftp-server` | Yes | ftp://ftp.samkirkland.com/destinationPath/ | | Deployment destination server & path. Formatted as `protocol://domain.com:port/destinationPath/` protocol can be `ftp`, `ftps`, or `sftp`. Port is optional, when not specified it will default to 21 when using ftp, 22 when using sftp, and 990 when using ftps |
| `ftp-username` | Yes | username@samkirkland.com | | FTP account username |
| `ftp-password` | Yes | CrazyUniquePassword&%123 | | FTP account password |
| `local-dir` | No | deploy/ | ./ | Which local folder to deploy, path should be relative to the root and should include trailing slash. `./` is the root of the project |
| `git-ftp-args` | No | See `git-ftp-args` section below | | Custom git-ftp arguments, this field is passed through directly into the git-ftp script |
| `known-hosts` | No | hostname ssh-rsa AAAAB3NzaC1y ... | | The desired contents of your .ssh/known_hosts file. See [known hosts setup](#known-hosts-setup) |
| Key Name | Required | Example | Default Value | Description |
|-------------------------|----------|-------------------------------|-------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `server` | Yes | `ftp.samkirkland.com` | | Deployment destination server |
| `username` | Yes | `username@samkirkland.com` | | FTP user name |
| `password` | Yes | `CrazyUniquePassword&%123` | | FTP password, be sure to escape quotes and spaces |
| `port` | No | `990` | `21` | Server port to connect to (read your web hosts docs) |
| `protocol` | No | `ftps` | `ftp` | `ftp`: provides no encryption, `ftps`: full encryption newest standard (aka "explicit" ftps), `ftps-legacy`: full encryption legacy standard (aka "implicit" ftps) |
| `local-dir` | No | `./myFolderToPublish/` | `./` | Folder to upload from, must end with trailing slash `/` |
| `server-dir` | No | `public_html/www/` | `./` | Folder to upload to (on the server), must end with trailing slash `/` |
| `state-name` | No | `folder/.sync-state.json` | `.ftp-deploy-sync-state.json` | Path and name of the state file - this file is used to track which files have been deployed |
| `dry-run` | No | `true` | `false` | Prints which modifications will be made with current config options, but doesn't actually make any changes |
| `dangerous-clean-slate` | No | `true` | `false` | Deletes ALL contents of server-dir, even items in excluded with 'exclude' argument |
| `exclude` | No | [See Example](#exclude-files) | [See Example](#exclude-files) | An array of glob patterns, these files will not be included in the publish/delete process. [List MUST be in this format](#exclude-files). You can use [a glob tester](https://www.digitalocean.com/community/tools/glob?comments=true&glob=%2A%2A%2F.git%2A%2F%2A%2A&matches=false&tests=test%2Fsam&tests=.git%2F%0D&tests=.github%2F%0D&tests=.git%2Ftest%0D&tests=.gitattributes%0D&tests=.gitignore%0D&tests=.git%2Fconfig%0D&tests=.git%2Ftest%2Ftest&tests=.github%2Fworkflows%2Fmain.yml&tests=node_modules%2Ffolder%2F%0D&tests=node_modules%2Fotherfolder%2F%0D&tests=subfolder%2Fnode_modules%2F) to test your pattern(s). |
| `log-level` | No | `minimal` | `standard` | `minimal`: only important info, `standard`: important info and basic file changes, `verbose`: print everything the script is doing |
| `security` | No | `strict` | `loose` | `strict`: Reject any connection which is not authorized with the list of supplied CAs. `loose`: Allow connection even when the domain is not certificate |
| `timeout` | No | `60000` | `30000` | Timeout in milliseconds for FTP operations |
#### Advanced options using `git-ftp-args`
Custom arguments, this field is passed through directly into the git-ftp script. See [git-ftp's manual](https://github.com/git-ftp/git-ftp/blob/master/man/git-ftp.1.md) for all options.
You can use as many arguments as you want, seperate them with a space
Below is an incomplete list of commonly used args:
| Argument | Description |
|------------------------|------------------------------------------------------------------------------------------------------|
| `--dry-run` | Does not upload or delete anything, but tries to get the .git-ftp.log file from remote host |
| `--silent` | Be silent |
| `--all` | Transfer all files, even seemingly the same as the target site (default is differences only). Note: Only files committed to github are uploaded, if you'd like to upload files generated during the action run see `.git-ftp-include` |
| `--lock` | Locks remote files from being modified while a deployment is running |
| `--remote-root` | Specifies the remote root directory to deploy to. The remote path in the URL is ignored |
| `--key` | SSH private key file name for SFTP |
| `--branch` | Push a specific branch. I recommend [creating a yaml action for each branch instead](https://github.com/SamKirkland/FTP-Deploy-Action/issues/37#issuecomment-579819486) |
| `--pubkey` | SSH public key file name. Used with `--key` option |
| `--insecure` | Don't verify server's certificate |
| `--cacert <file>` | Use as CA certificate store. Useful when a server has a self-signed certificate |
### Ignore specific files when deploying
Add patterns to `.git-ftp-ignore` and all matching file names will be ignored. The patterns are interpreted as shell glob patterns.
Here are some glob pattern examples:
#### Ignore git related files:
```gitattributes
.gitignore
*/.gitignore # ignore files in sub directories
*/.gitkeep
.git-ftp-ignore
.git-ftp-include
.gitlab-ci.yml
```
#### Ignore a single file called `foobar.txt`
```gitattributes
foobar.txt
```
#### Ignore all files having extension .txt
```gitattributes
*.txt
```
#### Ignore everything in a directory named `config`
```gitattributes
config/*
```
### Force upload specific files
The `.git-ftp-include` file specifies intentionally untracked files to should upload. If you have a file that should always be uploaded, add a line beginning with `!` followed by the file's name.
#### Always upload the file `VERSION.txt`
```gitattributes
!VERSION.txt
```
#### Always upload the folder `build`
```gitattributes
!build/
```
If you have a file that should be uploaded whenever a tracked file changes, add a line beginning with the untracked file's name followed by a colon and the tracked file's name.
#### Upload CSS file compiled from an SCSS file
```gitattributes
css/style.css:scss/style.scss
```
If you have multiple source files, you can add multiple lines for each of them. Whenever one of the tracked files changes, the upload of the paired untracked file will be triggered.
```gitattributes
css/style.css:scss/style.scss
css/style.css:scss/mixins.scss
```
If a local untracked file is deleted, any change of a paired tracked file will trigger the deletion of the remote file on the server.
All paths are usually relative to the Git working directory. When using the `local-dir` option, paths of tracked files (right side of the colon) are relative to the set `local-dir`.
```gitattributes
# upload "html/style.css" triggered by html/style.scss
# with local-dir "html"
html/style.css:style.scss
```
If your source file is outside the `local-dir`, prefix it with a / and define a path relative to the Git working directory.
#### Uploading a file outside of `local-dir`
```gitattributes
# upload "dist/style.css" with local-dir "dist"
dist/style.css:/src/style.scss
```
It is also possible to upload whole directories. For example, if you use a package manager like composer, you can upload all vendor packages when the file composer.lock changes:
```gitattributes
vendor/:composer.lock
```
But keep in mind that this will upload all files in the vendor folder, even those that are on the server already. And it will not delete files from that directory if local files are deleted.
---
# Common Examples
Read more about the differences between these protocols [https://www.sftp.net/sftp-vs-ftps](https://www.sftp.net/sftp-vs-ftps)
### FTP (File Transfer Protocol)
`ftp://ftp.samkirkland.com:21/mypath`
FTP has existed since 1971, it's an ancient protocol with near universal support.
```yml
on: push
name: Publish Website
jobs:
FTP-Deploy-Action:
name: FTP-Deploy-Action
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2.1.0
with:
fetch-depth: 2
- name: FTP-Deploy-Action
uses: SamKirkland/FTP-Deploy-Action@3.1.0
with:
ftp-server: ftp://ftp.samkirkland.com/
ftp-username: myFtpUserName
ftp-password: ${{ secrets.FTP_PASSWORD }}
```
### FTPS (File Transfer Protocol over SSL)
`ftps://ftp.samkirkland.com:21/mypath`
Use the legacy FTP over a secure encrypted connection.
Notes about ftps:
- Most hosts don't offer FTPS, it's more common on windows/.net hosts and less common on linux hosting
- Most hosts don't have a correct certificate setup for ftp domains, [even my host doesn't do it right](https://ftp.samkirkland.com/). This means you'll likely have to add `--insecure` to `git-ftp-args`
```yml
on: push
name: Publish Website over FTPS
jobs:
FTP-Deploy-Action:
name: FTP-Deploy-Action
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2.1.0
with:
fetch-depth: 2
- name: FTP-Deploy-Action
uses: SamKirkland/FTP-Deploy-Action@3.1.0
with:
ftp-server: ftps://ftp.samkirkland.com:21/
ftp-username: myFTPSUsername
ftp-password: ${{ secrets.FTPS_PASSWORD }}
git-ftp-args: --insecure # if your certificate is setup correctly this can be removed
```
### SFTP (SSH File Transfer Protocol)
`sftp://ftp.samkirkland.com:22/mypath`
Similar in name to FTP but this protocol is entirely new and requires SSH access to the server.
##### Notes about SFTP:
- **You CANNOT use a FTP account - they are not the same!**
- You must have shell access to your server, please read you webhosts documentation
- You will need to create a **SSH** user to deploy over SFTP. Normally this is your cpanel or hosting providers username and password
- Most web hosts change the default port (21), check with your host for your port number
### Known Hosts Setup
**Windows**
In powershell run `ssh-keyscan -p <sshport> <hostname>` and copy the hash output
Example for samkirkland.com `ssh-keyscan -p 7822 samkirkland.com`
**Linux, or OSX (using homebrew)**
Install the OpenSSH packages and use `ssh-keyscan <hostname>` and copy the hash output
Add the `known-hosts` argument with your hosts hash
Example: `knownhosts: ssh-rsa AAAAB3Nza...H1Q5Spw==`
*Note: If you receive a `Connection refused` error, you must specify the ssh port to your host*
```yml
on: push
name: Publish Website over SFTP
jobs:
FTP-Deploy-Action:
name: FTP-Deploy-Action
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2.1.0
with:
fetch-depth: 2
- name: FTP-Deploy-Action
uses: SamKirkland/FTP-Deploy-Action@3.1.0
with:
ftp-server: sftp://ftp.samkirkland.com:7280/
ftp-username: mySFTPUsername
ftp-password: ${{ secrets.SFTP_PASSWORD }}
git-ftp-args: --insecure # if your certificate is setup correctly this can be removed (see known-hosts argument)
```
### Build and Publish React/Angular/Vue Website
#### Build and Publish React/Angular/Vue Website
Make sure you have an npm script named 'build'. This config should work for most node built websites.
> #### If you don't commit your `build` folder to github you MUST create a `.git-ftp-include` file with the content `!build/` so the folder is always uploaded!
```yml
on: push
name: Build and Publish Front End Framework Website
name: 🚀 Deploy website on push
jobs:
FTP-Deploy-Action:
name: FTP-Deploy-Action
web-deploy:
name: 🎉 Deploy
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2.1.0
with:
fetch-depth: 2
- name: 🚚 Get latest code
uses: actions/checkout@v4
- name: Use Node.js 12.x
uses: actions/setup-node@v1
- name: Use Node.js 16
uses: actions/setup-node@v2
with:
node-version: '12.x'
- name: Build Project
node-version: '16'
- name: 🔨 Build Project
run: |
npm install
npm run build --if-present
- name: List output files
run: ls
- name: FTP-Deploy-Action
uses: SamKirkland/FTP-Deploy-Action@3.1.0
npm run build
- name: 📂 Sync files
uses: SamKirkland/FTP-Deploy-Action@v4.3.5
with:
ftp-server: ftp://ftp.samkirkland.com/
ftp-username: myFTPUsername
ftp-password: ${{ secrets.FTP_PASSWORD }}
local-dir: build # This folder is NOT going to upload by default unless you add it to .git-ftp-include
server: ftp.samkirkland.com
username: myFtpUserName
password: ${{ secrets.password }}
```
### Log only dry run: Use this mode for testing
#### FTPS
```yml
on: push
name: 🚀 Deploy website on push
jobs:
web-deploy:
name: 🎉 Deploy
runs-on: ubuntu-latest
steps:
- name: 🚚 Get latest code
uses: actions/checkout@v4
- name: 📂 Sync files
uses: SamKirkland/FTP-Deploy-Action@v4.3.5
with:
server: ftp.samkirkland.com
username: myFtpUserName
password: ${{ secrets.password }}
protocol: ftps
port: 1234 # todo replace with your web hosts ftps port
```
#### Log only dry run: Use this option for testing
Ouputs a list of files that will be created/modified to sync your source without making any actual changes
```yml
on: push
name: Publish Website Dry Run
name: 🚀 Deploy website on push
jobs:
FTP-Deploy-Action:
name: FTP-Deploy-Action
web-deploy:
name: 🎉 Deploy
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2.1.0
with:
fetch-depth: 2
- name: 🚚 Get latest code
uses: actions/checkout@v4
- name: FTP-Deploy-Action
uses: SamKirkland/FTP-Deploy-Action@3.1.0
- name: 📂 Sync files
uses: SamKirkland/FTP-Deploy-Action@v4.3.5
with:
ftp-server: ftp://ftp.samkirkland.com/
ftp-username: myFTPUsername
ftp-password: ${{ secrets.FTP_PASSWORD }}
git-ftp-args: --dry-run
server: ftp.samkirkland.com
username: myFtpUserName
password: ${{ secrets.password }}
dry-run: true
```
_Want another example? Let me know by creating a github issue_
#### Exclude files
Excludes files
```yml
on: push
name: 🚀 Deploy website on push
jobs:
web-deploy:
name: 🎉 Deploy
runs-on: ubuntu-latest
steps:
- name: 🚚 Get latest code
uses: actions/checkout@v4
- name: 📂 Sync files
uses: SamKirkland/FTP-Deploy-Action@v4.3.5
with:
server: ftp.samkirkland.com
username: myFtpUserName
password: ${{ secrets.password }}
exclude: |
**/.git*
**/.git*/**
**/node_modules/**
fileToExclude.txt
```
`exclude` has the following default value
```yml
exclude: |
**/.git*
**/.git*/**
**/node_modules/**
```
if you overwrite the default value you will probably want to respecify them
---
_Want another example? Let me know by creating a [github issue](https://github.com/SamKirkland/FTP-Deploy-Action/issues/new)_
---
## Badge
If you appreciate this github action give it a :star: or show off with one of the badges below. Feel free to edit the text or color.
[<img alt="Deployed with FTP Deploy Action" src="https://img.shields.io/badge/Deployed With-FTP DEPLOY ACTION-%3CCOLOR%3E?style=for-the-badge&color=0077b6">](https://github.com/SamKirkland/FTP-Deploy-Action)
```md
[<img alt="Deployed with FTP Deploy Action" src="https://img.shields.io/badge/Deployed With-FTP DEPLOY ACTION-%3CCOLOR%3E?style=for-the-badge&color=0077b6">](https://github.com/SamKirkland/FTP-Deploy-Action)
```
[<img alt="Deployed with FTP Deploy Action" src="https://img.shields.io/badge/Deployed With-FTP DEPLOY ACTION-%3CCOLOR%3E?style=for-the-badge&color=2b9348">](https://github.com/SamKirkland/FTP-Deploy-Action)
```md
[<img alt="Deployed with FTP Deploy Action" src="https://img.shields.io/badge/Deployed With-FTP DEPLOY ACTION-%3CCOLOR%3E?style=for-the-badge&color=2b9348">](https://github.com/SamKirkland/FTP-Deploy-Action)
```
[<img alt="Deployed with FTP Deploy Action" src="https://img.shields.io/badge/Deployed With-FTP DEPLOY ACTION-%3CCOLOR%3E?style=for-the-badge&color=d00000">](https://github.com/SamKirkland/FTP-Deploy-Action)
```md
[<img alt="Deployed with FTP Deploy Action" src="https://img.shields.io/badge/Deployed With-FTP DEPLOY ACTION-%3CCOLOR%3E?style=for-the-badge&color=d00000">](https://github.com/SamKirkland/FTP-Deploy-Action)
```
---
[<img alt="Website Deployed for Free with FTP Deploy Action" src="https://img.shields.io/badge/Website deployed for free with-FTP DEPLOY ACTION-%3CCOLOR%3E?style=for-the-badge&color=297FA9">](https://github.com/SamKirkland/FTP-Deploy-Action)
```md
[<img alt="Website Deployed for Free with FTP Deploy Action" src="https://img.shields.io/badge/Website deployed for free with-FTP DEPLOY ACTION-%3CCOLOR%3E?style=for-the-badge&color=297FA9">](https://github.com/SamKirkland/FTP-Deploy-Action)
```
[<img alt="Website Deployed for Free with FTP Deploy Action" src="https://img.shields.io/badge/Website deployed for free with-FTP DEPLOY ACTION-%3CCOLOR%3E?style=for-the-badge&color=2b9348">](https://github.com/SamKirkland/FTP-Deploy-Action)
```md
[<img alt="Website Deployed for Free with FTP Deploy Action" src="https://img.shields.io/badge/Website deployed for free with-FTP DEPLOY ACTION-%3CCOLOR%3E?style=for-the-badge&color=2b9348">](https://github.com/SamKirkland/FTP-Deploy-Action)
```
[<img alt="Website Deployed for Free with FTP Deploy Action" src="https://img.shields.io/badge/Website deployed for free with-FTP DEPLOY ACTION-%3CCOLOR%3E?style=for-the-badge&color=d00000">](https://github.com/SamKirkland/FTP-Deploy-Action)
```md
[<img alt="Website Deployed for Free with FTP Deploy Action" src="https://img.shields.io/badge/Website deployed for free with-FTP DEPLOY ACTION-%3CCOLOR%3E?style=for-the-badge&color=d00000">](https://github.com/SamKirkland/FTP-Deploy-Action)
```
---
@ -337,21 +240,22 @@ _Want another example? Let me know by creating a github issue_
<details>
<summary>How to exclude .git files from the publish</summary>
See the [`.git-ftp-ignore`](#ignore-specific-files-when-deploying) example section
Git files are excluded by default! If you customize the `exclude` option make sure you re-add the default options.
</details>
<details>
<summary>All files are being uploaded instead of just different files</summary>
<summary>How to exclude a specific file or folder</summary>
By default only different files are uploaded.
You can use the `exclude` option to ignore specific files/folders from the publish. Keep in mind you will need to re-add the default exclude options if you want to keep them. For example the below option excludes all `.txt` files.
Verify you have `with: fetch-depth: 2` in your `actions/checkout@v2.1.0` step. The last 2 checkins are required in order to determine differences
```yml
exclude:
- *.txt
```
If you've had multiple git commits without deploying, all files will be uploaded to get back in sync
Verify you **don't** have the `--all` git-ftp-args flag set
</details>
<details>
<summary>How do I set a upload timeout?</summary>
@ -361,8 +265,8 @@ github has a built-in `timeout-minutes` option, see customized example below
on: push
name: Publish Website
jobs:
FTP-Deploy-Action:
name: FTP-Deploy-Action
web-deploy:
name: web-deploy
runs-on: ubuntu-latest
timeout-minutes: 15 # time out after 15 minutes (default is 360 minutes)
steps:
@ -370,62 +274,13 @@ jobs:
```
</details>
---
## Debugging your config locally
This action is a basic wrapper around my `@samkirkland/ftp-deploy` npm package. To test your config you can install [@samkirkland/ftp-deploy](https://github.com/SamKirkland/ftp-deploy) and then convert your config to a yml action. Settings are one-to-one, this action is only a wrapper.
## Common Errors
<details id="failed-to-upload">
<summary>Failed to upload files</summary>
* **Fix 1:** Verify your login credentials are correct, download a ftp client and test with the exact same host/username/password
* **Fix 2:** Remember if you are using SFTP or FTPS you cannot use a normal FTP account username/password. You must use a elevated account. Each host has a different process to setup a FTPS or SFTP account. Please contact your host for help.
* **Fix 3:** If you are using sftp or ftps you should add `git-ftp-args: --insecure`, most hosts setup certificates incorrectly :(
</details>
<details id="cant-access-remote-sftp">
<summary>Can't access remote 'sftp://', exiting...</summary>
See ["Failed to upload files"](#failed-to-upload) section above
</details>
<details id="cant-access-remote-ftps">
<summary>Can't access remote 'ftps://', exiting...</summary>
See ["Failed to upload files"](#failed-to-upload) section above
</details>
<details id="files-arent_uploading">
<summary>My files aren't uploading</summary>
V3+ uses github to determine when files have changes and only publish differences. This means files that aren't committed to github will not upload by default.
To change this behavior please see [`.git-ftp-ignore`](#ignore-specific-files-when-deploying) documentation.
</details>
<details id="prohibited-file-name">
<summary>rm: Access failed: 553 Prohibited file name: ./.ftpquota</summary>
The `.ftpquota` file is created by some FTP Servers and cannot be modified by the user
Add `.ftpquota` to your [`.git-ftp-ignore`](#ignore-specific-files-when-deploying) file
</details>
<details id="ssl-peer-certificate">
<summary>Error: SSL peer certificate or SSH remote key was not OK</summary>
Whitelist your host via the `known-hosts` configuration option (see [known hosts setup](#known-hosts-setup) in SFTP) or add the `--insecure` argument
</details>
---
## Debugging locally
##### Instructions for debugging on windows
- Install docker for windows
- Open powershell
- Navigate to the repo folder
- Run `docker build --tag action .`
- Run `docker run action`
##### Instructions for debugging on linux
- Please submit a PR for linux instructions :)
#### Pull Requests Welcome!
## Contributing to this project
To test this action locally you will need to setup **docker** and **act** to run a environment similar to the one github uses for actions.
- Download/install docker for windows, make sure it is running
- `choco install act-cli` install [act](https://github.com/nektos/act)
- Install the npm package using `npm install --dev-only @samkirkland/ftp-deploy`
- Update the `deploy` script in `package.json` with a actual server/username/password
- You can run the script using the following command `npm run deploy` (run this in the folder that has the `package.json` file)

View File

@ -1,27 +1,52 @@
name: 'FTP Deploy'
description: 'Syncs files via FTP/SFTP to a remote server'
author: 'Sam Kirkland'
name: "FTP Deploy"
description: "Automate deploying websites and more with this GitHub action via FTP and FTPS"
author: "Sam Kirkland"
inputs:
ftp-server:
description: 'Deployment destination server & path. Formatted as protocol://domain.com:port/full/destination/path/'
server:
required: true
ftp-username:
description: 'FTP account username'
description: "ftp server"
username:
required: true
ftp-password:
description: 'FTP account password'
description: "ftp username"
password:
required: true
description: "ftp password"
port:
required: false
description: "Server port to connect to (read your web hosts docs)"
protocol:
required: false
description: "protocol to deploy with - ftp, ftps, or ftps-legacy"
local-dir:
description: 'The local folder to copy, defaults to root project folder'
default: ./
required: false
git-ftp-args:
description: 'Passes through options into git-ftp'
default:
description: "Folder to upload from, must end with trailing slash /"
server-dir:
required: false
description: "Path to upload to on the server. Must end with trailing slash /"
state-name:
required: false
description: "Path and name of the state file - this file is used to track which files have been deployed"
dry-run:
required: false
description: "Prints which modifications will be made with current config options, but doesnt actually make any changes"
dangerous-clean-slate:
required: false
description: "Deletes ALL contents of server-dir, even items in excluded with exclude argument"
exclude:
required: false
description: "An array of glob patterns, these files will not be included in the publish/delete process"
log-level:
required: false
description: "How verbose should the information be - minimal, standard, or verbose"
security:
required: false
description: "strict or loose"
timeout:
required: false
description: "Timeout in milliseconds for FTP operations"
runs:
using: 'docker'
image: 'Dockerfile'
using: "node20"
main: "dist/index.js"
branding:
icon: 'upload-cloud'
color: 'orange'
icon: "upload-cloud"
color: "blue"

10413
dist/index.js vendored

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

40
migration.md Normal file
View File

@ -0,0 +1,40 @@
# How to migrate between versions
## Migrating from v4.1.0 to v4.2.0
`v4.2.0` parses the `exclude` option in a more standard way. Going forward the `exclude` option **must** be in the following format:
```yml
exclude: |
**/.git*
**/.git*/**
**/node_modules/**
fileToExclude.txt
```
## Migrating from v3 to v4
Migrating from v3 to v4 should be fairly straightforward. Version 4 was designed with speed and ease of initial setup in mind. Going forward version 4 will be the only supported version.
### Those who can't upgrade
Most features have been carried forward and improved upon. However, some features did not make the cut:
- **`sftp` is no longer supported**. If you have `sftp` access you are using `ssh`, that means you have access to a much more modern and capable protocol. I plan on releasing a separate github action that will deploy over `sftp`/`ssh` using `rsync`. Until then you can continue using version 3.
- The `include` argument has been removed. I didn't see much need for it in the initial release. If you need this feature please create a support ticket.
### How to upgrade
1. Remove `with: fetch-depth: 2`. It is no longer needed and removing it will _slightly_ speed up deployments.
2. Change the version to `v4.X.X`, for example `SamKirkland/FTP-Deploy-Action@v4.3.5` (please check the [README](https://github.com/SamKirkland/FTP-Deploy-Action/blob/master/README.md) or the [releases page](https://github.com/SamKirkland/FTP-Deploy-Action/releases/latest) for the latest version).
3. If you have a `.git-ftp-include` file you should delete it. Version 4 tracks files differently and no longer needs this config file.
4. If you have a `.git-ftp-ignore` file, you should transfer the options to the new `exclude` argument. **Note:** version 4 excludes any `.git*` and `node_modules/` files / folders by default.
5. Update your arguments to reflect the following changes:
- `ftp-server` was split into 4 arguments:
- `server`
- `port`
- `protocol`
- `server-dir`
- `ftp-username` was renamed to `username`.
- `ftp-password` was renamed to `password`.
- `local-dir` and `server-dir` now **must** end with `/`.
- `git-ftp-args` and `known-hosts` arguments were removed.

7952
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,40 +1,44 @@
{
"name": "typescript-action",
"version": "1.0.0",
"name": "ftp-deploy-action",
"version": "4.3.5",
"private": true,
"description": "TypeScript template action",
"main": "dist/main.js",
"engines": {
"node": ">=12.0.0"
},
"description": "Automate deploying websites and more with this GitHub action",
"main": "dist/index.js",
"scripts": {
"build:dev": "tsc",
"build:production": "ncc build src/main.ts -o dist",
"build:docker": "docker build --tag action .",
"run:docker": "docker run action --build-arg FTP_SERVER=example.com FTP_USERNAME=test@example.com FTP_PASSWORD=passwordExample"
"build": "ncc build src/main.ts --no-cache",
"test": "jest",
"lint": "eslint src/**/*.ts"
},
"repository": {
"type": "git",
"url": "git+https://github.com/actions/typescript-action.git"
"url": "git+https://github.com/SamKirkland/FTP-Deploy-Action.git"
},
"keywords": [
"actions",
"node",
"setup"
"ftp",
"website deploy",
"continuous integration",
"ftps"
],
"author": "SamKirkland",
"author": "Sam Kirkland",
"license": "MIT",
"dependencies": {
"@actions/core": "1.2.4",
"@actions/exec": "1.0.4"
"@actions/core": "^1.9.1",
"@samkirkland/ftp-deploy": "^1.2.4",
"@types/jest": "^29.4.1",
"jest": "^29.5.0",
"ts-jest": "^29.0.5",
"ts-node-dev": "^2.0.0"
},
"devDependencies": {
"@types/jest": "25.2.1",
"@types/node": "12.12.8",
"@zeit/ncc": "0.22.1",
"jest": "25.5.3",
"jest-circus": "25.5.3",
"ts-jest": "25.4.0",
"typescript": "3.8.3"
"@types/node": "^20.11.24",
"@typescript-eslint/eslint-plugin": "^5.33.1",
"@typescript-eslint/parser": "^5.33.1",
"@vercel/ncc": "^0.34.0",
"eslint": "^8.22.0",
"eslint-plugin-jest": "^26.8.7",
"typescript": "^4.7.4"
},
"jest": {
"preset": "ts-jest"
}
}

12
project.code-workspace Normal file
View File

@ -0,0 +1,12 @@
{
"folders": [
{
"path": "."
}
],
"settings": {
"files.exclude": {
"**/node_modules": true
}
}
}

105
src/main.test.ts Normal file
View File

@ -0,0 +1,105 @@
import { optionalBoolean, optionalInt, optionalLogLevel, optionalProtocol, optionalSecurity, optionalString } from "./parse";
describe("boolean", () => {
test("false", () => {
expect(optionalBoolean("test", "false")).toBe(false);
});
test("FALSE", () => {
expect(optionalBoolean("test", "FALSE")).toBe(false);
});
test("true", () => {
expect(optionalBoolean("test", "true")).toBe(true);
});
test("TRUE", () => {
expect(optionalBoolean("test", "TRUE")).toBe(true);
});
test("optional", () => {
expect(optionalBoolean("test", "")).toBe(undefined);
});
});
describe("string", () => {
test("empty", () => {
expect(optionalString("")).toBe(undefined);
});
test("populated", () => {
expect(optionalString("test")).toBe("test");
});
});
describe("int", () => {
test("empty", () => {
expect(optionalInt("test", "")).toBe(undefined);
});
test("0", () => {
expect(optionalInt("test", "0")).toBe(0);
});
test("1", () => {
expect(optionalInt("test", "1")).toBe(1);
});
test("500", () => {
expect(optionalInt("test", "500")).toBe(500);
});
test("non-int", () => {
expect(() => optionalInt("test", "12.345")).toThrow();
});
});
describe("protocol", () => {
test("empty", () => {
expect(optionalProtocol("test", "")).toBe(undefined);
});
test("ftp", () => {
expect(optionalProtocol("test", "ftp")).toBe("ftp");
});
test("ftps", () => {
expect(optionalProtocol("test", "ftps")).toBe("ftps");
});
test("ftps-legacy", () => {
expect(optionalProtocol("test", "ftps-legacy")).toBe("ftps-legacy");
});
});
describe("log level", () => {
test("empty", () => {
expect(optionalLogLevel("test", "")).toBe(undefined);
});
test("minimal", () => {
expect(optionalLogLevel("test", "minimal")).toBe("minimal");
});
test("standard", () => {
expect(optionalLogLevel("test", "standard")).toBe("standard");
});
test("verbose", () => {
expect(optionalLogLevel("test", "verbose")).toBe("verbose");
});
});
describe("security", () => {
test("empty", () => {
expect(optionalSecurity("test", "")).toBe(undefined);
});
test("loose", () => {
expect(optionalSecurity("test", "loose")).toBe("loose");
});
test("strict", () => {
expect(optionalSecurity("test", "strict")).toBe("strict");
});
});

View File

@ -1,80 +1,32 @@
import * as core from '@actions/core';
import * as exec from '@actions/exec';
import fs from 'fs';
import { promisify } from 'util';
import { IActionArguments } from './types';
import * as core from "@actions/core";
import { deploy } from "@samkirkland/ftp-deploy";
import { IFtpDeployArguments } from "@samkirkland/ftp-deploy/dist/types";
import { optionalInt, optionalProtocol, optionalString, optionalBoolean, optionalStringArray, optionalLogLevel, optionalSecurity } from "./parse";
const writeFileAsync = promisify(fs.writeFile);
const errorDeploying = "⚠️ Error deploying";
async function run() {
async function runDeployment() {
try {
const userArguments = getUserArguments();
await configureHost(userArguments);
await syncFiles(userArguments);
const args: IFtpDeployArguments = {
server: core.getInput("server", { required: true }),
username: core.getInput("username", { required: true }),
password: core.getInput("password", { required: true }),
port: optionalInt("port", core.getInput("port")),
protocol: optionalProtocol("protocol", core.getInput("protocol")),
"local-dir": optionalString(core.getInput("local-dir")),
"server-dir": optionalString(core.getInput("server-dir")),
"state-name": optionalString(core.getInput("state-name")),
"dry-run": optionalBoolean("dry-run", core.getInput("dry-run")),
"dangerous-clean-slate": optionalBoolean("dangerous-clean-slate", core.getInput("dangerous-clean-slate")),
"exclude": optionalStringArray("exclude", core.getMultilineInput("exclude")),
"log-level": optionalLogLevel("log-level", core.getInput("log-level")),
"security": optionalSecurity("security", core.getInput("security")),
"timeout": optionalInt("timeout", core.getInput("timeout"))
};
console.log("✅ Deploy Complete");
await deploy(args);
}
catch (error) {
console.error(errorDeploying);
core.setFailed(error.message);
catch (error: any) {
core.setFailed(error);
}
}
run();
async function configureHost(args: IActionArguments): Promise<void> {
if (args.knownHosts === "") {
return;
}
try {
const sshFolder = `${process.env['HOME']}/.ssh`;
await exec.exec(`mkdir -v -p ${sshFolder}`);
await exec.exec(`chmod 700 ${sshFolder}`);
writeFileAsync(`${sshFolder}/known_hosts`, args.knownHosts);
await exec.exec(`chmod 755 ${sshFolder}/known_hosts`);
console.log("✅ Configured known_hosts");
}
catch (error) {
console.error("⚠️ Error configuring known_hosts");
core.setFailed(error.message);
}
}
function getUserArguments(): IActionArguments {
return {
ftp_server: core.getInput("ftp-server", { required: true }),
ftp_username: core.getInput("ftp-username", { required: true }),
ftp_password: core.getInput("ftp-password", { required: true }),
local_dir: withDefault(core.getInput("local-dir"), "./"),
gitFtpArgs: withDefault(core.getInput("git-ftp-args"), ""),
knownHosts: withDefault(core.getInput("known-hosts"), "")
};
}
function withDefault(value: string, defaultValue: string) {
if (value === "" || value === null || value === undefined) {
return defaultValue;
}
return value;
}
/**
* Sync changed files
*/
async function syncFiles(args: IActionArguments) {
try {
await core.group("Uploading files", async () => {
return await exec.exec(`git ftp push --force --auto-init --verbose --syncroot ${args.local_dir} --user ${args.ftp_username} --passwd ${args.ftp_password} ${args.gitFtpArgs} ${args.ftp_server}`);
});
}
catch (error) {
console.error("⚠️ Failed to upload files");
core.setFailed(error.message);
}
}
runDeployment();

103
src/parse.ts Normal file
View File

@ -0,0 +1,103 @@
export function optionalString(rawValue: string): string | undefined {
if (rawValue.length === 0) {
return undefined;
}
return rawValue;
}
export function optionalBoolean(argumentName: string, rawValue: string): boolean | undefined {
if (rawValue.length === 0) {
return undefined;
}
const cleanValue = rawValue.toLowerCase();
if (cleanValue === "true") {
return true;
}
if (cleanValue === "false") {
return false;
}
throw new Error(`${argumentName}: invalid parameter - please use a boolean, you provided "${rawValue}". Try true or false instead.`);
}
export function optionalProtocol(argumentName: string, rawValue: string): "ftp" | "ftps" | "ftps-legacy" | undefined {
if (rawValue.length === 0) {
return undefined;
}
const cleanValue = rawValue.toLowerCase();
if (cleanValue === "ftp") {
return "ftp";
}
if (cleanValue === "ftps") {
return "ftps";
}
if (cleanValue === "ftps-legacy") {
return "ftps-legacy";
}
throw new Error(`${argumentName}: invalid parameter - you provided "${rawValue}". Try "ftp", "ftps", or "ftps-legacy" instead.`);
}
export function optionalLogLevel(argumentName: string, rawValue: string): "minimal" | "standard" | "verbose" | undefined {
if (rawValue.length === 0) {
return undefined;
}
const cleanValue = rawValue.toLowerCase();
if (cleanValue === "minimal") {
return "minimal";
}
if (cleanValue === "standard") {
return "standard";
}
if (cleanValue === "verbose") {
return "verbose";
}
throw new Error(`${argumentName}: invalid parameter - you provided "${rawValue}". Try "minimal", "standard", or "verbose" instead.`);
}
export function optionalSecurity(argumentName: string, rawValue: string): "loose" | "strict" | undefined {
if (rawValue.length === 0) {
return undefined;
}
const cleanValue = rawValue.toLowerCase();
if (cleanValue === "loose") {
return "loose";
}
if (cleanValue === "strict") {
return "strict";
}
throw new Error(`${argumentName}: invalid parameter - you provided "${rawValue}". Try "loose" or "strict" instead.`);
}
export function optionalInt(argumentName: string, rawValue: string): number | undefined {
if (rawValue.length === 0) {
return undefined;
}
const valueAsNumber = parseFloat(rawValue);
if (Number.isInteger(valueAsNumber)) {
return valueAsNumber;
}
throw new Error(`${argumentName}: invalid parameter - you provided "${rawValue}". Try a whole number (no decimals) instead like 1234`);
}
export function optionalStringArray(argumentName: string, rawValue: string[]): string[] | undefined {
if (rawValue.length === 0) {
return undefined;
}
if (typeof rawValue === "string") {
throw new Error(`${argumentName}: invalid parameter - you provided "${rawValue}". This option expects an list in the EXACT format described in the readme`);
}
return rawValue;
}

View File

@ -1,31 +0,0 @@
export interface IActionArguments {
ftp_server: string | undefined;
ftp_username: string | undefined;
ftp_password: string | undefined;
/** @default "." */
local_dir: string | undefined;
/** @default "" */
gitFtpArgs: string | undefined;
/** @default "" */
knownHosts: string | undefined;
}
/**
* @see https://github.com/git-ftp/git-ftp/blob/master/man/git-ftp.1.md#exit-codes
*/
export enum gitFTPExitCode {
Successful = 0,
UnknownError = 1,
WrongUsage = 2,
MissingArguments = 3,
ErrorWhileUploading = 4,
ErrorWhileDownloading = 5,
UnknownProtocol = 6,
RemoteLocked = 7,
NotAGitProject = 8,
PreFTPPushHookFailed = 9,
LocalFileOperationFailed = 10
}

View File

@ -1,63 +1,17 @@
{
"compilerOptions": {
/* Basic Options */
// "incremental": true, /* Enable incremental compilation */
"target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
// "allowJs": true, /* Allow javascript files to be compiled. */
// "checkJs": true, /* Report errors in .js files. */
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
// "declaration": true, /* Generates corresponding '.d.ts' file. */
// "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
// "sourceMap": true, /* Generates corresponding '.map' file. */
// "outFile": "./", /* Concatenate and emit output to single file. */
"outDir": "./lib", /* Redirect output structure to the directory. */
"rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
// "composite": true, /* Enable project compilation */
// "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */
// "removeComments": true, /* Do not emit comments to output. */
"noEmit": true, /* Do not emit outputs. */
// "importHelpers": true, /* Import emit helpers from 'tslib'. */
// "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
// "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
/* Strict Type-Checking Options */
"strict": true, /* Enable all strict type-checking options. */
"noImplicitAny": false, /* Raise error on expressions and declarations with an implied 'any' type. */
// "strictNullChecks": true, /* Enable strict null checks. */
// "strictFunctionTypes": true, /* Enable strict checking of function types. */
// "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
// "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
/* Additional Checks */
// "noUnusedLocals": true, /* Report errors on unused locals. */
// "noUnusedParameters": true, /* Report errors on unused parameters. */
// "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
/* Module Resolution Options */
// "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
// "baseUrl": "./", /* Base directory to resolve non-absolute module names. */
// "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
// "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
// "typeRoots": [], /* List of folders to include type definitions from. */
// "types": [], /* Type declaration files to be included in compilation. */
// "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
"esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
// "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
/* Source Map Options */
// "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
// "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
// "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
/* Experimental Options */
// "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
// "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
"moduleResolution": "Node",
"target": "ES2019", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
"outDir": "./dist", /* Redirect output structure to the directory. */
"rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
"strict": true, /* Enable all strict type-checking options. */
"noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
"esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
"noEmit": true
},
"exclude": ["node_modules", "**/*.test.ts"]
}
"exclude": [
"node_modules",
"**/.test.ts"
]
}

View File

@ -1,33 +0,0 @@
# Migrating from v2 to v3
`uses: actions/checkout@v2.1.0` must now have the option `fetch-depth: 2`
Without the `fetch-depth` option diffs cannot be calculated and all files will be uploaded.
### Breaking changes
All arguments have been renamed to lower `kebab-case`
| Old Value | New Value | Notes |
|------------------|-----------------|----------------------------|
| `env:` | `with:` | ⚠ Before declaring settings in v2 you set a line to `env:` In v3+ that line must now read `with:` ⚠ |
| `FTP_SERVER` | `ftp-server` | |
| `FTP_USERNAME` | `ftp-username` | |
| `FTP_PASSWORD` | `ftp-password` | |
| `LOCAL_DIR` | `local-dir` | |
| `ARGS` | `git-ftp-args` | |
| `METHOD` | | `METHOD` has been removed. Instead specify the method within `ftp-server` (ex: ftp://server.com, ftps://server.com, sftp://sever.com) |
| `PORT` | | `PORT` has been removed. Instead specify the port between the domain and destination within `ftp-server` (ex: ftp://server.com:PORT/destination/) |
| `REMOTE_DIR` | | `REMOTE_DIR` has been removed. Instead specify the destination path within `ftp-server` (ex: ftp://server.com/full/destination/path/) |
### ARGS changes
| Old ARG | New ARG | Notes |
|---------------------|-----------------|----------------------------------------|
| `--include` | | use `.git-ftp-ignore` instead |
| `--include-glob` | | use `.git-ftp-ignore` instead |
| `--exclude` | | use `.git-ftp-ignore` instead |
| `--exclude-glob` | | use `.git-ftp-ignore` instead |
| `--delete-excluded` | | |
| `--no-empty-dirs` | | |
| `--parallel` | | |
| `--L` | | |
| `--ignore-time` | | v3 only uploads differences by default |