Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

The deployment environment 'Staging' in your bitbucket-pipelines.yml file occurs multiple times in the pipeline

I'm trying to get Bitbucket Pipelines to work with multiple steps that define the deployment area. When I do, I get the error

Configuration error The deployment environment 'Staging' in your bitbucket-pipelines.yml file occurs multiple times in the pipeline. Please refer to our documentation for valid environments and their ordering.

From what I read, the deployment variable has to happen on a step by step basis.

How would I set up this example pipelines file to not hit that error?

image: ubuntu:18.04

definitions:
    steps:
        - step: &build
            name: npm-build
            condition:
                changesets:
                    includePaths:
                        # Only run npm if anything in the build directory was touched
                        - "build/**"
            image: node:14.17.5
            script:
              - echo 'build initiated'
              - cd build
              - npm install
              - npm run dev
              - echo 'build complete'
            artifacts:
              - themes/factor/css/**
              - themes/factor/js/**
        - step: &deploychanges
            name: Deploy_Changes
            deployment: Staging
            script:
              - echo 'Installing server dependencies'
              - apt-get update -q
              - apt-get install -qy software-properties-common
              - add-apt-repository -y ppa:git-ftp/ppa
              - apt-get update -q
              - apt-get install -qy git-ftp
              - echo 'All dependencies installed'
              - echo 'Transferring changes'
              - git ftp init --user $FTP_USER --passwd $FTP_PASSWORD $FTP_ADDRESS push --force --changed-only -vv
              - echo 'File transfer complete'
        
        - step: &deploycompiled
            name: Deploy_Compiled
            deployment: Staging
            condition:
                changesets:
                    includePaths:
                        # Only run npm if anything in the build directory was touched
                        - "build/**"
            script:
              - echo 'Installing server dependencies'
              - apt-get update -q
              - apt-get install -qy software-properties-common
              - add-apt-repository -y ppa:git-ftp/ppa
              - apt-get update -q
              - apt-get install -qy git-ftp
              - echo 'All dependencies installed'
              - echo 'Transferring compiled assets'
              - git ftp init --user $FTP_USER --passwd $FTP_PASSWORD $FTP_ADDRESS push --all --syncroot themes/factor/css/ -vv
              - git ftp init --user $FTP_USER --passwd $FTP_PASSWORD $FTP_ADDRESS push --all --syncroot themes/factor/js/ -vv
              - echo 'File transfer complete'

pipelines:
    branches:
        master:
            - step: *build
                <<: *deploychanges
                deployment: Production
            - step:            
                <<: *deploycompiled
                deployment: Production

        dev:
            - step: *build
            - step: *deploychanges
            - step: *deploycompiled
like image 280
hdwebpros Avatar asked Dec 08 '25 06:12

hdwebpros


2 Answers

Using Stage feature

Bitbucket release a beta feature called 'stage' that support the use of one deployment environment for several steps.

Stages allow you to group pipeline steps logically with shared properties, such as grouping steps for the same deployment environment, locking a deployment environment for multiple steps (preventing other Pipeline runs from interacting with it), and sharing deployment variables across multiple sets of sequential steps.

So your pipeline will be:

pipelines:
  branches:
    master:
      - stage:
          name: 'Build and Deploy to prod'
          deployment: "Production" # <- put here your deployment name
          steps: # next steps will use the same deployment variables
            - step: *build
            - step: *deploychanges
            - step: *deploycompiled
    dev:
      - stage:
          name: 'Build and Deploy to dev'
          steps:
            - step: *build
            - step: *deploychanges
            - step: *deploycompiled

ref: https://support.atlassian.com/bitbucket-cloud/docs/stage-options/

like image 53
Doremi Avatar answered Dec 10 '25 14:12

Doremi


The workaround for the issue with reusing Environment Variables without using the deployment clause for more than one steps in a pipeline I have found is to dump ENV VARS to a file and save it as an artifact that will be sourced in the following steps.

The code snippet for it would look like:

  steps:

    - step: &set-environment-variables
        name: 'Set environment variables'
        script:
          - printenv | xargs echo export > .envs
        artifacts:
          - .envs


    - step: &next-step
        name: "Next step in the pipeline"
        script:
          - source .envs
          - next_actions


pipelines:

  pull-requests:
    '**':
      - step:
          <<: *set-environment-variables
          deployment: my-deployment
      - step:
          <<: *next-step
          name: "Name of the next step being executed"

  branches:
    staging:
      - step:
          <<: *set-environment-variables
          deployment: my-deployment
      - step:
          <<: *next-step
          name: "Name of the next step being executed"

So far this solution works for me.

Update: after having an issue of "%s" appearing in the .envs file, which caused the later source .envs statement to fail, here is a slightly different approach to the initial step. It gets around that particular issue, but also only exports those variables you know you need in your pipeline - noting that there are a lot of bitbucket environment variables available to the first script step which will be available naturally to later scripts anyway, and it makes more sense (to me anyway) that you don't just dump out all environment variables to the .env artifact, but do it in a much more controlled manner.

   - step: &set-environment-variables
        name: 'Set environment variables'
        script:
          - echo "export SSH_USER=$SSH_USER" > .envs
          - echo "export SERVER_IP=$SERVER_IP" >> .envs
          - echo "export ANOTHER_ENV_VAR=$ANOTHER_ENV_VAR" >> .envs
        artifacts:
          - .envs

In this example, .envs will now contain only those 3 environment variables, and not a whole heap of system + bitbucket variables (and of course, no pesky %s characters either!)

like image 44
tymik Avatar answered Dec 10 '25 15:12

tymik