HEX
Server: Apache/2.4.65 (Ubuntu)
System: Linux ielts-store-v2 6.8.0-1036-gcp #38~22.04.1-Ubuntu SMP Thu Aug 14 01:19:18 UTC 2025 x86_64
User: root (0)
PHP: 7.2.34-54+ubuntu20.04.1+deb.sury.org+1
Disabled: pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,
Upload Files
File: //snap/google-cloud-cli/394/platform/ext-runtime/nodejs/bin/detect
#!/usr/bin/python
# Copyright 2015 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# Language detection script.

import json
import os
import re
import sys
import subprocess

DEV_NULL = open(os.devnull, 'w')

# Augment the path with our library directory.
ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(sys.argv[0])))
sys.path.append(os.path.join(ROOT_DIR, 'lib'))

import comm

def asList(val):
    """Returns the value if it is a list else returns a list with the value.
    """
    return val if isinstance(val, list) else [val]

def main(args):

    if len(args) != 2:
        # If we're being called incorrectly, this probably isn't happening from a
        # framework.
        sys.stderr.write('Invalid Usage: %s <source-root-directory>' %
                         sys.argv[0])
        return 1

    # Get the first argument, should be the source root directory.
    path = args[1]

    # Show failures in debug or error depending on whether nodejs has been
    # explicitly specified.
    config = comm.get_config()
    if ((config.params.appinfo and config.params.appinfo.runtime) or
        config.params.runtime):
        log_detect_error = comm.error
    else:
        log_detect_error = comm.debug

    comm.info('Checking for Node.js.')
    package_json = os.path.join(path, 'package.json')
    yarn_lock_name = 'yarn.lock'
    yarn_lock = os.path.join(path, yarn_lock_name)
    got_shrinkwrap = False

    if not os.path.isfile(package_json):
        comm.debug('node.js checker: No package.json file.')
        got_package_json = False
        got_scripts_start = False
        node_version = None
        use_yarn = False
    else:
        got_package_json = True
        # If there's a package.json file, that's unusual enough that any
        # errors should be surfaced to the user.
        log_detect_error = comm.error

        # Consider the yarn.lock file as present if and only if the yarn.lock
        # file exists and is not specified as being skipped in app.yaml.
        try:
            raw_skip_files = config.params.appinfo.skip_files
            skip_files = [] if raw_skip_files is None else asList(raw_skip_files)
        except AttributeError:
            # If the skip_file attribute or any other parent attribute
            # does not exist, treat the skip_files as not user specified.
            skip_files = []

        yarn_lock_exists = os.path.isfile(yarn_lock)
        yarn_lock_skipped = False
        for pattern in skip_files:
            if re.match(pattern, yarn_lock_name) is not None:
                yarn_lock_skipped = True
                break;

        use_yarn = yarn_lock_exists and not yarn_lock_skipped

        # Try to read the package.json file.
        try:
            with open(package_json) as f:
                contents = json.load(f)
        except (IOError, ValueError) as ex:
            # If we have an invalid or unreadable package.json file, there's
            # something funny going on here so fail recognition.
            # A package.json that exists is unusual enough that we want to warn
            # regardless of whether the nodejs runtime was specified.
            log_detect_error('node.js checker: error accessing package.json: '
                             '%r' % ex)
            return 1

        # See if we've got a scripts.start field.
        got_scripts_start = bool(contents.get('scripts', {}).get('start'))

        # See if a version of node is specified.
        try:
            node_version = contents.get('engines', {}).get('node', None)
            comm.info('node version is %s', node_version)
        except AttributeError:
            # Most likely "engines" wasn't a dictionary.
            comm.warn('node.js checker: ignoring invalid "engines" field in '
                      'package.json')
            node_version = None

        if node_version is None:
            comm.warn('No node version specified.  Please add your node '
                      'version, see '
                      'https://docs.npmjs.com/files/package.json#engines')

    if got_scripts_start or os.path.exists(os.path.join(path, 'server.js')):
      runtime = 'custom' if config.params.custom else 'nodejs'
      appinfo = {'runtime': runtime,
                 'env': 'flex'}
      comm.send_runtime_params({'got_package_json': got_package_json,
                                'got_scripts_start': got_scripts_start,
                                'node_version': node_version,
                                'use_yarn': use_yarn},
                                appinfo=appinfo)

    else:
        log_detect_error('node.js checker: Neither "start" in the "scripts" '
                         'section of "package.json" nor the "server.js" file '
                         'were found.')
        return 1

    return 0

if __name__ == '__main__':
    sys.exit(main(sys.argv))