Skip to content
This repository has been archived by the owner on Jul 1, 2021. It is now read-only.

Help me with beforeDeploy #33

Closed
LexRiver opened this issue Feb 3, 2017 · 16 comments
Closed

Help me with beforeDeploy #33

LexRiver opened this issue Feb 3, 2017 · 16 comments

Comments

@LexRiver
Copy link

LexRiver commented Feb 3, 2017

I'm trying to compile *.pug templates to *.html before deploy.
I have a script which I run like node build.js and it works good. But when I'm trying to use it in section beforeDeploy nothing happens.

here is my working script:

            var fs = require('fs');
            var pug = require('pug');
            var glob = require('glob');
            var path = require('path');

            console.log('building *.pug');
            
            glob('*.pug', {}, function(error, files){
                files.forEach(function(file, index){
                    var htmlFilename = path.basename(file, '.pug')+'.html';
                    console.log(file+' => '+htmlFilename);
                    fs.writeFile(htmlFilename, pug.renderFile(file, {pretty: true}));
                });
            });

and here is my beforeDeploy part:

                "beforeDeploy": [
                    {
                        "type": "script",
                        "script": "./build.js"
                    }
                ]

and here is my build.js script for vs-deploy:

console.log('test');

function execute(args) {
    console.log('execute starts');
    return new Promise(function(resolve, reject) {
        try {
            // do the MAGIC here

            // from the configuration example
            // above 'args.options' would contain
            // 5979 as value

            var fs = require('fs');
            var pug = require('pug');
            var glob = require('glob');
            var path = require('path');

            console.log('building *.pug');
            
            glob('*.pug', {}, function(error, files){
                files.forEach(function(file, index){
                    var htmlFilename = path.basename(file, '.pug')+'.html';
                    console.log(file+' => '+htmlFilename);
                    fs.writeFile(htmlFilename, pug.renderFile(file, {pretty: true}));
                });
                resolve();  // tell that anything went fine
            });


            
        }
        catch (e) {
            reject(e); // Oops, an error!
        }
    });
}
exports.execute = execute;

So I have no console outputs, no compilation of my *.pug and no errors:

[BEFORE DEPLOY #1] 
Deploying file ..... [OK]
Finished

So what I'm doing wrong?

@mkloubert
Copy link
Owner

mkloubert commented Feb 3, 2017

@LexRiver

Try to wrap the code with try-catch-blocks and see if an error messages is shown as popup:

var vscode = require('vscode');

try {
    var fs = require('fs');
    var pug = require('pug');
    var glob = require('glob');
    var path = require('path');

    // console.log('building *.pug');
    vscode.window.showInformationMessage('build.js: building *.pug');

    glob('*.pug', {}, function(error, files){
        try {
            files.forEach(function(file, index) {
                var htmlFilename = path.basename(file, '.pug')+'.html';
                console.log(file+' => '+htmlFilename);
                fs.writeFile(htmlFilename, pug.renderFile(file, {pretty: true}));
            });

            resolve();  // tell that anything went fine
        }
        catch (e) {
            vscode.window.showErrorMessage('build.js.forEach(): ' + e);
            
            reject(e);
        }
    });
}
catch (e) {
    vscode.window.showErrorMessage('build.js: ' + e);
    
    reject(e);
}

I think the problem is that you have to link the pug module inside your project folder. It is not part of the extension.

For console.log you have to look at the debug console (CTRL + SHIFT + Y).

@mkloubert
Copy link
Owner

mkloubert commented Feb 3, 2017

@LexRiver

I had the problem, after I removed the pug part, the script told me that glob could not be loaded.

The problem is that this is no NodeJS API / VSCode module.

After I replaced

var glob = require('glob');

with

var glob = args.require('glob');

it works.

The require method of args loads modules from the script / extension context, what means that you are also able to load modules that are part of the extension (and not only the VSCode / NodeJS ones).

These are the modules, the extension currently uses (s. package.json)

{
  "dependencies": {
    "aws-sdk": "^2.7.19",
    "azure-storage": "^1.4.0",
    "fs-extra": "^1.0.0",
    "ftp": "^0.3.10",
    "glob": "^7.1.1",
    "html-entities": "^1.2.0",
    "i18next": "^4.1.4",
    "isbinaryfile": "^3.0.2",
    "less": "^2.7.2",
    "mime": "^1.3.4",
    "moment": "^2.17.1",
    "mssql": "^3.3.0",
    "mysql": "^2.12.0",
    "node-uuid": "^1.4.7",
    "node-zip": "^1.1.1",
    "nodemailer": "^2.7.0",
    "ssh2-sftp-client": "^1.0.5",
    "typescript": "^2.1.5"
  }
}

BTW: If you want to include own modules, you have to the NodeJS way:

// relative to the 'build.js' path
var myModule = require('./my-module.js');

@mkloubert
Copy link
Owner

mkloubert commented Feb 3, 2017

@LexRiver

Now it seems to work.

Open your terminal / command line, go to the folder where your build.js is stored and execute

npm link pug

It will create a node_modules subfolder with the module there and you can use it by

var pug = require('pug');

@LexRiver
Copy link
Author

LexRiver commented Feb 3, 2017

@mkloubert
Thank you, compilation of *.pug files works now, but what are the correct settings to deploy these files to server?

Seems like they are deploying only on Ctrl+Alt+W, but not on Ctr+Alt+F

@LexRiver
Copy link
Author

LexRiver commented Feb 3, 2017

@mkloubert
If you could add some option like

  • track any file change (or file size change / or newly created files) in directory and deploy these files

that will be really great.

@mkloubert
Copy link
Owner

mkloubert commented Feb 3, 2017

@LexRiver

There is still a deploy on change feature :-)

But before we start: Upgrade at least to version 5.19.1

1. We have to compile the PUG files to HTML

Create a package that tracks the .pug files:

{
    "deploy": {
        // ...
    
        "packages": [
            // ...
        
            {
                "name": "PUG to HTML",
                "description": "The files that should be compiled to HTML files.",
                
                "files": [
                    "/**/*.pug"
                ],

                "deployOnSave": [ "PUG Compiler" ]
            }
            
            // ...
        ]
        
        // ...
    }
}

This will send all .pug files to the following target, called PUG Compiler, automatically if you save one (or more):

{
    "deploy": {
        // ...
    
        "targets": [
            // ...
        
            {
                "name": "PUG Compiler",
                "description": "Compiles an HTML file to PUG",

                "type": "script",

                "script": "./build.js"
            }
            
            // ...
        ]
        
        // ...
    }
}

This script target will use your ./build.js as target, but first you have to modify it, because it has another structure:

function deployFile(args) {
    return new Promise(function(resolve, reject) {
        var onCompleted = function(err) {
            if (err) {
                reject(err);
            }
            else {
                resolve(args);  // send input arguments
                                // back to the extension
            }
        };

        if (args.context.isCancelling()) {
            // cancellation request
            args.canceled = true;    // tell the extension
                                     // that we have cancelled

            onCompleted();
            return;
        }

        try {
            var fs = require('fs');
            var path = require('path');
            var pug = require('pug');

            var file = args.file;

            var htmlFilename = path.basename(file, '.pug') + '.html';
            var htmlFile = path.join(path.dirname(file),
                                     htmlFilename);  // I hope that HTML files
                                                     // should be created in
                                                     // same directory as PUGs

            if (args.deployOptions.onBeforeDeploy) {
                // use this to tell the extension that
                // we begin to deploy the file
                
                args.deployOptions.onBeforeDeploy(args.sender, {
                    destination: htmlFilename,  // this is only a string
                                                // to display in the output window
                    file: file,
                    target: args.target
                });
            }

            // render from PUG to HTML
            var pugData = pug.renderFile(file, {
                pretty: true
            });
            
            // write to HTML file async
            fs.writeFile(htmlFile, pugData, (err) => {
                onCompleted(err);  // tell extenstion that we have finished
            });
        }
        catch (e) {
            onCompleted(e);
        }
    });
}

exports.deployFile = deployFile;

Now, when you save PUG files, it automatically compiles then to HTML.

2. Automatically deploy HTML after compilation

When a HTML file has been generated / changed, you can use the deploy on change feature:

Add a second package that tracks changed HTML files:

{
    "deploy": {
        // ...
    
        "packages": [
            // ...
        
            {
                "name": "HTML from PUG",
                "description": "The files that should be deployed after compilation.",
                
                "files": [
                    "/**/*.html"
                ],

                "deployOnChange": true,

                "deployOnSave": [ "HTML target" ]
            }
            
            // ...
        ]
        
        // ...
    }
}

This will send all modifed / created HTML to the second target, called HTML target, automatically:

{
    "deploy": {
        // ...
    
        "targets": [
            // ...
        
            {
                "name": "HTML target",
                "description": "Deploys HTML files",

                "type": "test"
            }
            
            // ...
        ]
        
        // ...
    }
}

In my example I only used a mock target. Have a look at the wiki where all target types are listed.

@LexRiver
Copy link
Author

LexRiver commented Feb 4, 2017

@mkloubert
Thank you very much, Marcel.
That's works for me.

But small mistake in your code

           // render from PUG to HTML
            var pugData = pug.renderFile(htmlFilename, {
                pretty: true
            });

htmlFilename should be file

and that's is not obvious that it's possible to use targets in deployOnSave, I think you should mention this in wiki.

"deployOnSave": [ "HTML target" ]

and another proposal is to make this combination of two targets to work a little faster.
When I save a *.pug file it compiles it to *.html and then waits for 1 or 2 seconds and only then deploying it.
So maybe this delay could be reduced.

@mkloubert
Copy link
Owner

mkloubert commented Feb 4, 2017

@LexRiver

Thats right, it needs a better documentation.

I described it here, but the better way is to write it down to a separate wiki article, were you find examples for such scenarios. I will do this the next days.

With the speed problem, you seem to have the same problem as @rshakespear

I realeased version 5.20.0 that should reduce the delay, as you can read here.

@LexRiver
Copy link
Author

LexRiver commented Feb 4, 2017

@mkloubert
Another strange thing I've noticed.
If I compile pug templates outside of vscode when this deployment is on I'm getting strange warning messages:
Could not deploy '/file.html' to $'sftp' on save: Error: read ECONNRESET
or
Could not deploy '/file.html' to $'sftp' on save: Error: Timed out while waiting for handshake

@sag3ll0
Copy link
Contributor

sag3ll0 commented Feb 28, 2017

Hi, before deploy a want call "gulp build" command for workspace, how i must write it in section "beforeDeploy": []

@mkloubert
Copy link
Owner

@sag3ll0

You can use the open operation type:

{
    "deploy": {
        // ...

        "targets": [
            {
                "name": "My target",
                "type": "test",

                "beforeDeploy": [
                    {
                        "type": "open",
                        "target": "gulp", "arguments": [ "build" ]
                    }
                ]
            }
        ]
    }
}

If the extension cannot execute your gulp, try to set the full path or create a npm link inside your workspace:

npm link gulp

@sag3ll0
Copy link
Contributor

sag3ll0 commented Mar 1, 2017

it working, but it call new cmd window, that after operation not close. Can we use vs code terminal?

@lvbeck
Copy link

lvbeck commented Mar 3, 2017

@LexRiver I had same Error: Timed out while waiting for handshake
I found a solution by adding a config variable "readyTimeout" in connect() function of ssh2-sftp-client

in out\src\plugins\sftp.js, line 179, add readyTimeout: 99999

                    conn.connect({
                        host: host,
                        port: port,
                        username: user,
                        password: pwd,
                        privateKey: privateKey,
                        passphrase: target.privateKeyPassphrase,
                        hostHash: hashAlgo,
                        hostVerifier: (hashedKey, cb) => {
                            hashedKey = toHashSafe(hashedKey);
                            if (hashes.length < 1) {
                                return true;
                            }
                            return hashes.indexOf(hashedKey) > -1;
                        },
                        agent: agent,
                        agentForward: agentForward,
                        tryKeyboard: tryKeyboard,
			readyTimeout: 99999 // to fix handshake timeout issue
                    })

@mkloubert
Copy link
Owner

@lvbeck

Great! I will add and release a new version that can define that value in about 2 or 3 hours.

@mkloubert
Copy link
Owner

@lvbeck @LexRiver

Since version 5.32.0 there is now a readTimeout property:

{
    "deploy": {
        // ...

        "targets": [
            {
                "name": "My target",
                "type": "sftp",

                "readyTimeout": 99999
            }
        ]
    }
}

@mkloubert
Copy link
Owner

@sag3ll0

Sorry, when I answer so late ... since version 7.0.0 I have implemented the feature of running apps and "bash" scripts inside the integrated terminal (by setting runInTerminal property to (true) in the operation):

{
    "deploy": {
        // ...

        "targets": [
            {
                "name": "My target",
                "type": "test",

                "beforeDeploy": [
                    {
                        "type": "open",
                        "target": "gulp", "arguments": [ "build" ],

                        "runInTerminal": true
                    }
                ]
            }
        ]
    }
}

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants