Updating distribution
This commit is contained in:
@@ -0,0 +1,27 @@
|
|||||||
|
---
|
||||||
|
name: Azure DevOps
|
||||||
|
about: Migrate Azure DevOps pipelines to GitHub Actions with Valet
|
||||||
|
title: "[Azure DevOps]:"
|
||||||
|
labels: azure-devops
|
||||||
|
assignees: ""
|
||||||
|
---
|
||||||
|
|
||||||
|
## Inputs
|
||||||
|
|
||||||
|
Provide the following required inputs:
|
||||||
|
|
||||||
|
Organization:
|
||||||
|
_The Azure DevOps organization to migrate pipelines from._
|
||||||
|
|
||||||
|
Project:
|
||||||
|
_The Azure DevOps project to migrate pipelines from._
|
||||||
|
|
||||||
|
## Available commands
|
||||||
|
|
||||||
|
The following commands can be executed by adding a comment to this issue:
|
||||||
|
|
||||||
|
- `/audit`
|
||||||
|
- `/dry-run --pipeline-type pipeline|release --pipeline-id :pipeline-id`
|
||||||
|
- `/migrate --pipeline-type pipeline|release --pipeline-id :pipeline-id --target-url :github-repository-url`
|
||||||
|
|
||||||
|
**Note:** The `pipeline-type` option will default to `pipeline` if omitted. If any remaining options are missing, the command will not be successful.
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
---
|
||||||
|
name: Circle CI
|
||||||
|
about: Migrate Circle CI pipelines to GitHub Actions with Valet
|
||||||
|
title: "[Circle CI]:"
|
||||||
|
labels: circle-ci
|
||||||
|
assignees: ""
|
||||||
|
---
|
||||||
|
|
||||||
|
## Inputs
|
||||||
|
|
||||||
|
Provide the following required inputs:
|
||||||
|
|
||||||
|
Organization:
|
||||||
|
_The Circle CI organization to migrate pipelines from._
|
||||||
|
|
||||||
|
## Available commands
|
||||||
|
|
||||||
|
The following commands can be executed by adding a comment to this issue:
|
||||||
|
|
||||||
|
- `/audit`
|
||||||
|
- `/dry-run --repository :repository-name`
|
||||||
|
- `/migrate --repository :repository-name --target-url :github-repository-url`
|
||||||
|
|
||||||
|
**Note**: If any options are missing, the command will not be successful.
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
---
|
||||||
|
name: GitLab CI
|
||||||
|
about: Migrate GitLab CI pipelines to GitHub Actions with Valet
|
||||||
|
title: "[GitLab CI]:"
|
||||||
|
labels: gitlab
|
||||||
|
assignees: ""
|
||||||
|
---
|
||||||
|
|
||||||
|
## Inputs
|
||||||
|
|
||||||
|
Provide the following required inputs:
|
||||||
|
|
||||||
|
Namespace:
|
||||||
|
_The GitLab CI namespace (or group) to migrate pipelines from._
|
||||||
|
|
||||||
|
## Available commands
|
||||||
|
|
||||||
|
The following commands can be executed by adding a comment to this issue:
|
||||||
|
|
||||||
|
- `/audit`
|
||||||
|
- `/dry-run --project :project-name`
|
||||||
|
- `/migrate --project :project-name --target-url :github-repository-url`
|
||||||
|
|
||||||
|
**Note**: If any options are missing, the command will not be successful.
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
---
|
||||||
|
name: Jenkins
|
||||||
|
about: Migrate Jenkins jobs to GitHub Actions with Valet
|
||||||
|
title: "[Jenkins]:"
|
||||||
|
labels: jenkins
|
||||||
|
assignees: ""
|
||||||
|
---
|
||||||
|
|
||||||
|
## Inputs
|
||||||
|
|
||||||
|
Provide the following optional inputs:
|
||||||
|
|
||||||
|
Folders:
|
||||||
|
_Include specific folders in an audit_
|
||||||
|
|
||||||
|
## Available commands
|
||||||
|
|
||||||
|
The following commands can be executed by adding a comment to this issue:
|
||||||
|
|
||||||
|
- `/audit`
|
||||||
|
- `/dry-run --source-url :jenkins-job-url`
|
||||||
|
- `/migrate --source-url :jenkins-job-url --target-url :github-repository-url`
|
||||||
|
|
||||||
|
**Note**: If any options are missing, the command will not be successful.
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
---
|
||||||
|
name: Travis CI
|
||||||
|
about: Migrate Travis CI pipelines to GitHub Actions with Valet
|
||||||
|
title: "[Travis CI]:"
|
||||||
|
labels: travis-ci
|
||||||
|
assignees: ""
|
||||||
|
---
|
||||||
|
|
||||||
|
## Inputs
|
||||||
|
|
||||||
|
Provide the following required inputs:
|
||||||
|
|
||||||
|
Organization:
|
||||||
|
_The Travis CI organization to migrate pipelines from._
|
||||||
|
|
||||||
|
## Available commands
|
||||||
|
|
||||||
|
The following commands can be executed by adding a comment to this issue:
|
||||||
|
|
||||||
|
- `/audit`
|
||||||
|
- `/dry-run --repository :repository-name`
|
||||||
|
- `/migrate --repository :repository-name --target-url :github-repository-url`
|
||||||
|
|
||||||
|
**Note**: If any options are missing, the command will not be successful.
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
name: ci
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [main]
|
||||||
|
pull_request:
|
||||||
|
|
||||||
|
env:
|
||||||
|
ruby_version: 2.7.1
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
unit-test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- uses: ruby/setup-ruby@v1
|
||||||
|
with:
|
||||||
|
ruby-version: ${{ env.ruby_version }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: bundle install
|
||||||
|
- name: Run specs
|
||||||
|
run: bin/rspec
|
||||||
|
lint:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- uses: ruby/setup-ruby@v1.47.0
|
||||||
|
with:
|
||||||
|
ruby-version: ${{ env.ruby_version }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: bundle install
|
||||||
|
- name: Lint
|
||||||
|
run: bin/rubocop
|
||||||
@@ -0,0 +1,227 @@
|
|||||||
|
name: valet-issue-ops
|
||||||
|
|
||||||
|
on:
|
||||||
|
issue_comment:
|
||||||
|
types: [created]
|
||||||
|
|
||||||
|
env:
|
||||||
|
GITHUB_INSTANCE_URL: https://github.com
|
||||||
|
GITHUB_ACCESS_TOKEN: ${{ secrets.GH_ACCESS_TOKEN }}
|
||||||
|
JENKINS_INSTANCE_URL: https://jenkout.westus2.cloudapp.azure.com
|
||||||
|
JENKINS_USERNAME: ${{ secrets.jenkins_username }}
|
||||||
|
JENKINS_ACCESS_TOKEN: ${{ secrets.jenkins_access_token }}
|
||||||
|
JENKINSFILE_ACCESS_TOKEN: ${{ secrets.jenkinsfile_access_token }}
|
||||||
|
AZURE_DEVOPS_ACCESS_TOKEN: ${{ secrets.azure_devops_access_token }}
|
||||||
|
TRAVIS_CI_ACCESS_TOKEN: ${{ secrets.travis_ci_access_token }}
|
||||||
|
TRAVIS_CI_SOURCE_GITHUB_ACCESS_TOKEN: ${{ secrets.travis_ci_source_github_access_token }}
|
||||||
|
GITLAB_ACCESS_TOKEN: ${{ secrets.gitlab_access_token }}
|
||||||
|
CIRCLE_CI_ACCESS_TOKEN: ${{ secrets.circle_ci_access_token }}
|
||||||
|
CIRCLE_CI_SOURCE_GITHUB_ACCESS_TOKEN: ${{ secrets.circle_ci_source_github_access_token }}
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
execute-valet:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
outputs:
|
||||||
|
command: ${{ steps.prepare.outputs.command }}
|
||||||
|
log-filename: ${{ steps.logs.outputs.filename }}
|
||||||
|
container:
|
||||||
|
image: ghcr.io/valet-customers/valet-cli:latest
|
||||||
|
credentials:
|
||||||
|
username: ${{ secrets.valet_ghcr_username }}
|
||||||
|
password: ${{ secrets.valet_ghcr_password }}
|
||||||
|
steps:
|
||||||
|
- uses: actions-ecosystem/action-add-labels@v1
|
||||||
|
if: always()
|
||||||
|
with:
|
||||||
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
labels: valet-running
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Install dependencies
|
||||||
|
run: bundle install --without development
|
||||||
|
- name: Prepare arguments
|
||||||
|
id: prepare
|
||||||
|
run: |
|
||||||
|
echo "${{ toJSON(github.event.issue.labels.*.name) }}"
|
||||||
|
./bin/parse_issue "${{ github.event.issue.body }}" "${{ github.event.comment.body }}" "${{ toJSON(github.event.issue.labels.*.name) }}"
|
||||||
|
- name: Validate arguments
|
||||||
|
run: |
|
||||||
|
if [ -z "${{ steps.prepare.outputs.provider }}" ]; then
|
||||||
|
echo "Unable to determine provider"
|
||||||
|
exit 1
|
||||||
|
elif [ -z "${{ steps.prepare.outputs.command }}" ]; then
|
||||||
|
echo "Unable to determine command"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
- name: execute valet
|
||||||
|
run: |
|
||||||
|
valet ${{ steps.prepare.outputs.command }} ${{ steps.prepare.outputs.provider }} \
|
||||||
|
${{ steps.prepare.outputs.args }} \
|
||||||
|
--output-dir /data/output \
|
||||||
|
--no-telemetry
|
||||||
|
- uses: actions/upload-artifact@v2
|
||||||
|
if: always()
|
||||||
|
with:
|
||||||
|
path: /data/output/
|
||||||
|
name: output
|
||||||
|
- if: always()
|
||||||
|
id: logs
|
||||||
|
run: |
|
||||||
|
path=$(ls /data/output/log/*.log | head -1)
|
||||||
|
filename=$(basename "$path")
|
||||||
|
echo "LOG_FILE_PATH=$path" >> $GITHUB_ENV
|
||||||
|
echo "::set-output name=filename::$filename"
|
||||||
|
- uses: actions/upload-artifact@v2
|
||||||
|
if: always()
|
||||||
|
with:
|
||||||
|
path: ${{ env.LOG_FILE_PATH }}
|
||||||
|
name: logs
|
||||||
|
|
||||||
|
audit:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: needs.execute-valet.outputs.command == 'audit'
|
||||||
|
needs: execute-valet
|
||||||
|
steps:
|
||||||
|
- uses: actions/download-artifact@v2
|
||||||
|
if: always()
|
||||||
|
with:
|
||||||
|
name: output
|
||||||
|
- uses: actions/github-script@v5
|
||||||
|
with:
|
||||||
|
script: |
|
||||||
|
const fs = require('fs')
|
||||||
|
const summaryText = fs.readFileSync("./audit_summary.md", "utf8")
|
||||||
|
const artifactUrl = `https://github.com/${context.repo.owner}/${context.repo.repo}/actions/runs/${process.env.GITHUB_RUN_ID}`
|
||||||
|
const body = `Audit successfully completed :rocket:
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Audit summary :point_down:</summary>
|
||||||
|
|
||||||
|
\`\`\`
|
||||||
|
${summaryText}
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
Download full results [here](${artifactUrl})
|
||||||
|
`
|
||||||
|
await github.rest.issues.createComment({
|
||||||
|
issue_number: context.issue.number,
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
body
|
||||||
|
})
|
||||||
|
dry-run:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: needs.execute-valet.outputs.command == 'dry-run'
|
||||||
|
needs: execute-valet
|
||||||
|
steps:
|
||||||
|
- uses: actions/download-artifact@v2
|
||||||
|
if: always()
|
||||||
|
with:
|
||||||
|
name: output
|
||||||
|
- uses: actions/github-script@v5
|
||||||
|
with:
|
||||||
|
script: |
|
||||||
|
const fs = require('fs')
|
||||||
|
const directory = "${{ github.workspace }}/"
|
||||||
|
const globber = await glob.create(`${directory}**/*.yml`)
|
||||||
|
|
||||||
|
const workflows = []
|
||||||
|
for await (const file of globber.globGenerator()) {
|
||||||
|
const content = fs.readFileSync(file, 'utf8')
|
||||||
|
workflows.push(
|
||||||
|
"<details>",
|
||||||
|
` <summary>${file.substring(directory.length)}</summary>`,
|
||||||
|
"",
|
||||||
|
"```yaml",
|
||||||
|
content,
|
||||||
|
"```",
|
||||||
|
"</details>",
|
||||||
|
""
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const body = `Dry run was successful :boom:
|
||||||
|
|
||||||
|
Transformed workflows:
|
||||||
|
|
||||||
|
${workflows.join("\n")}
|
||||||
|
`
|
||||||
|
await github.rest.issues.createComment({
|
||||||
|
issue_number: context.issue.number,
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
body
|
||||||
|
})
|
||||||
|
|
||||||
|
migrate:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: needs.execute-valet.outputs.command == 'migrate'
|
||||||
|
needs: execute-valet
|
||||||
|
steps:
|
||||||
|
- uses: actions/download-artifact@v2
|
||||||
|
if: always()
|
||||||
|
with:
|
||||||
|
name: logs
|
||||||
|
- id: pull-request-url
|
||||||
|
run: |
|
||||||
|
pullRequest=$(grep "${{ env.pullRequestPattern }}" ${{ needs.execute-valet.outputs.log-filename }} | sed -rn "s/^.*${{ env.pullRequestPattern }}'(.+)'.*$/\1/p")
|
||||||
|
echo $pullRequest
|
||||||
|
echo ::set-output name=output::$pullRequest
|
||||||
|
env:
|
||||||
|
pullRequestPattern: "Pull request: "
|
||||||
|
- uses: actions/github-script@v5
|
||||||
|
env:
|
||||||
|
PULL_REQUEST_URL: "${{ steps.pull-request-url.outputs.output }}"
|
||||||
|
with:
|
||||||
|
script: |
|
||||||
|
const body = `Migration was successful :sparkles:
|
||||||
|
|
||||||
|
Continue to the [pull request](${process.env.PULL_REQUEST_URL}) to complete the migration.
|
||||||
|
`
|
||||||
|
try {
|
||||||
|
await github.rest.issues.createComment({
|
||||||
|
issue_number: context.issue.number,
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
body
|
||||||
|
})
|
||||||
|
} catch(e) {
|
||||||
|
console.log(e)
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: [execute-valet, audit, migrate, dry-run]
|
||||||
|
if: always()
|
||||||
|
steps:
|
||||||
|
- uses: actions/download-artifact@v2
|
||||||
|
if: always() && needs.execute-valet.result == 'failure'
|
||||||
|
with:
|
||||||
|
name: logs
|
||||||
|
- uses: actions/github-script@v5
|
||||||
|
if: always() && needs.execute-valet.result == 'failure'
|
||||||
|
with:
|
||||||
|
script: |
|
||||||
|
const fs = require('fs')
|
||||||
|
const body = `Something went wrong. Please check the logs for more information.
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Logs :point_down:</summary>
|
||||||
|
|
||||||
|
\`\`\`
|
||||||
|
${fs.readFileSync("${{ needs.execute-valet.outputs.log-filename }}", "utf8")}
|
||||||
|
\`\`\`
|
||||||
|
</details>
|
||||||
|
`
|
||||||
|
await github.rest.issues.createComment({
|
||||||
|
issue_number: context.issue.number,
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
body
|
||||||
|
})
|
||||||
|
- uses: actions-ecosystem/action-remove-labels@v1
|
||||||
|
if: always()
|
||||||
|
with:
|
||||||
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
labels: valet-running
|
||||||
+20
@@ -0,0 +1,20 @@
|
|||||||
|
/.bundle/
|
||||||
|
/.yardoc
|
||||||
|
/_yardoc/
|
||||||
|
/coverage/
|
||||||
|
/doc/
|
||||||
|
/pkg/
|
||||||
|
/spec/reports/
|
||||||
|
/tmp/
|
||||||
|
/log/
|
||||||
|
/vendor/
|
||||||
|
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
|
# rspec failure tracking
|
||||||
|
.rspec_status
|
||||||
|
|
||||||
|
.env*local
|
||||||
|
|
||||||
|
*.gem
|
||||||
|
.vscode/settings.json
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
--format progress
|
||||||
|
--color
|
||||||
|
--require spec_helper
|
||||||
|
--format RSpec::Github::Formatter
|
||||||
|
--pattern "**/*_spec.rb"
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
inherit_gem:
|
||||||
|
rubocop-github:
|
||||||
|
- config/default_edge.yml
|
||||||
|
|
||||||
|
Lint/AmbiguousBlockAssociation:
|
||||||
|
Exclude:
|
||||||
|
- "spec/**/*"
|
||||||
|
Style/HashEachMethods:
|
||||||
|
Enabled: true
|
||||||
|
Style/HashTransformKeys:
|
||||||
|
Enabled: true
|
||||||
|
Style/HashTransformValues:
|
||||||
|
Enabled: true
|
||||||
|
Style/Documentation:
|
||||||
|
Enabled: false
|
||||||
|
Naming/MethodParameterName:
|
||||||
|
Enabled: false
|
||||||
|
Style/MultilineIfModifier:
|
||||||
|
Enabled: false
|
||||||
|
Performance/Detect:
|
||||||
|
Enabled: false
|
||||||
|
Layout/FirstArrayElementLineBreak:
|
||||||
|
Enabled: true
|
||||||
|
Layout/FirstHashElementIndentation:
|
||||||
|
EnforcedStyle: consistent
|
||||||
|
Layout/FirstHashElementLineBreak:
|
||||||
|
Enabled: true
|
||||||
|
Layout/FirstMethodArgumentLineBreak:
|
||||||
|
Enabled: true
|
||||||
|
Layout/HashAlignment:
|
||||||
|
EnforcedHashRocketStyle: table
|
||||||
|
EnforcedColonStyle: table
|
||||||
|
EnforcedLastArgumentHashStyle: always_inspect
|
||||||
|
Layout/MultilineHashKeyLineBreaks:
|
||||||
|
Enabled: true
|
||||||
|
Layout/MultilineMethodArgumentLineBreaks:
|
||||||
|
Enabled: true
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
2.7.1
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
source "https://rubygems.org"
|
||||||
|
|
||||||
|
git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
|
||||||
|
|
||||||
|
gem "require_all", "~> 3.0.0"
|
||||||
|
|
||||||
|
group :development do
|
||||||
|
gem "dotenv", "~> 2.7.6"
|
||||||
|
gem "factory_bot", "~> 6.1"
|
||||||
|
gem "faker", "~> 2.17"
|
||||||
|
gem "pry-byebug", "~> 3.9"
|
||||||
|
gem "rspec", "~> 3.10"
|
||||||
|
gem "rspec-github", "~> 2.3", ">= 2.3.1"
|
||||||
|
gem "rubocop", "~> 0.80", "< 0.81"
|
||||||
|
gem "rubocop-github", "~> 0.14.0"
|
||||||
|
gem "rubocop-performance", "~> 1.6.1"
|
||||||
|
gem "ruby-debug-ide", "~> 0.7.2"
|
||||||
|
gem "shoulda-matchers", "~> 4.5.1"
|
||||||
|
end
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
GEM
|
||||||
|
remote: https://rubygems.org/
|
||||||
|
specs:
|
||||||
|
activesupport (6.1.4.1)
|
||||||
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
||||||
|
i18n (>= 1.6, < 2)
|
||||||
|
minitest (>= 5.1)
|
||||||
|
tzinfo (~> 2.0)
|
||||||
|
zeitwerk (~> 2.3)
|
||||||
|
ast (2.4.2)
|
||||||
|
byebug (11.1.3)
|
||||||
|
coderay (1.1.3)
|
||||||
|
concurrent-ruby (1.1.9)
|
||||||
|
diff-lcs (1.4.4)
|
||||||
|
dotenv (2.7.6)
|
||||||
|
factory_bot (6.2.0)
|
||||||
|
activesupport (>= 5.0.0)
|
||||||
|
faker (2.19.0)
|
||||||
|
i18n (>= 1.6, < 2)
|
||||||
|
i18n (1.8.11)
|
||||||
|
concurrent-ruby (~> 1.0)
|
||||||
|
jaro_winkler (1.5.4)
|
||||||
|
method_source (1.0.0)
|
||||||
|
minitest (5.14.4)
|
||||||
|
parallel (1.21.0)
|
||||||
|
parser (3.0.3.1)
|
||||||
|
ast (~> 2.4.1)
|
||||||
|
pry (0.13.1)
|
||||||
|
coderay (~> 1.1)
|
||||||
|
method_source (~> 1.0)
|
||||||
|
pry-byebug (3.9.0)
|
||||||
|
byebug (~> 11.0)
|
||||||
|
pry (~> 0.13.0)
|
||||||
|
rainbow (3.0.0)
|
||||||
|
rake (13.0.6)
|
||||||
|
require_all (3.0.0)
|
||||||
|
rexml (3.2.5)
|
||||||
|
rspec (3.10.0)
|
||||||
|
rspec-core (~> 3.10.0)
|
||||||
|
rspec-expectations (~> 3.10.0)
|
||||||
|
rspec-mocks (~> 3.10.0)
|
||||||
|
rspec-core (3.10.1)
|
||||||
|
rspec-support (~> 3.10.0)
|
||||||
|
rspec-expectations (3.10.1)
|
||||||
|
diff-lcs (>= 1.2.0, < 2.0)
|
||||||
|
rspec-support (~> 3.10.0)
|
||||||
|
rspec-github (2.3.1)
|
||||||
|
rspec-core (~> 3.0)
|
||||||
|
rspec-mocks (3.10.2)
|
||||||
|
diff-lcs (>= 1.2.0, < 2.0)
|
||||||
|
rspec-support (~> 3.10.0)
|
||||||
|
rspec-support (3.10.3)
|
||||||
|
rubocop (0.80.1)
|
||||||
|
jaro_winkler (~> 1.5.1)
|
||||||
|
parallel (~> 1.10)
|
||||||
|
parser (>= 2.7.0.1)
|
||||||
|
rainbow (>= 2.2.2, < 4.0)
|
||||||
|
rexml
|
||||||
|
ruby-progressbar (~> 1.7)
|
||||||
|
unicode-display_width (>= 1.4.0, < 1.7)
|
||||||
|
rubocop-github (0.14.0)
|
||||||
|
rubocop (~> 0.59)
|
||||||
|
rubocop-performance (1.6.1)
|
||||||
|
rubocop (>= 0.71.0)
|
||||||
|
ruby-debug-ide (0.7.3)
|
||||||
|
rake (>= 0.8.1)
|
||||||
|
ruby-progressbar (1.11.0)
|
||||||
|
shoulda-matchers (4.5.1)
|
||||||
|
activesupport (>= 4.2.0)
|
||||||
|
tzinfo (2.0.4)
|
||||||
|
concurrent-ruby (~> 1.0)
|
||||||
|
unicode-display_width (1.6.1)
|
||||||
|
zeitwerk (2.5.1)
|
||||||
|
|
||||||
|
PLATFORMS
|
||||||
|
ruby
|
||||||
|
x86_64-darwin-19
|
||||||
|
|
||||||
|
DEPENDENCIES
|
||||||
|
dotenv (~> 2.7.6)
|
||||||
|
factory_bot (~> 6.1)
|
||||||
|
faker (~> 2.17)
|
||||||
|
pry-byebug (~> 3.9)
|
||||||
|
require_all (~> 3.0.0)
|
||||||
|
rspec (~> 3.10)
|
||||||
|
rspec-github (~> 2.3, >= 2.3.1)
|
||||||
|
rubocop (~> 0.80, < 0.81)
|
||||||
|
rubocop-github (~> 0.14.0)
|
||||||
|
rubocop-performance (~> 1.6.1)
|
||||||
|
ruby-debug-ide (~> 0.7.2)
|
||||||
|
shoulda-matchers (~> 4.5.1)
|
||||||
|
|
||||||
|
BUNDLED WITH
|
||||||
|
2.2.33
|
||||||
@@ -1 +1,82 @@
|
|||||||
# issue-ops
|
# Valet Issue Ops
|
||||||
|
|
||||||
|
Valet can be orchestrated using GitHub Actions and Issues. This template repository can be used to enable this workflow to migrate pipelines from an existing CI/CD instance to GitHub Actions.
|
||||||
|
|
||||||
|
## Getting started
|
||||||
|
|
||||||
|
To get started create a new repository using this repository as the template by clicking [here](https://github.com/github/valet-issue-ops/generate). Next, add the repository secrets relevant to the CI/CD providers being migrated:
|
||||||
|
|
||||||
|
### All CI/CD providers
|
||||||
|
|
||||||
|
The following secrets are required:
|
||||||
|
|
||||||
|
- `VALET_GHCR_USERNAME`: The username to access the `valet` container.
|
||||||
|
- `VALET_GHCR_PASSWORD`: The password to access the `valet` container (requires `read:packages` scope).
|
||||||
|
- `GH_ACCESS_TOKEN`: GitHub personal access token to create pull requests (requires `repo` and `workflow` scopes).
|
||||||
|
|
||||||
|
Optionally, the following environment variables can be set:
|
||||||
|
|
||||||
|
- `GITHUB_INSTANCE_URL`: The base URL of your GitHub instance (only required if it is **not** <https://github.com>).
|
||||||
|
|
||||||
|
### Azure DevOps
|
||||||
|
|
||||||
|
The following secrets are required:
|
||||||
|
|
||||||
|
- `AZURE_DEVOPS_ACCESS_TOKEN`: The personal access token to access the Azure DevOps instance. This token requires the following scopes:
|
||||||
|
- Build (Read & Execute)
|
||||||
|
- Code (Read)
|
||||||
|
- Release (Read)
|
||||||
|
- Service Connections (Read)
|
||||||
|
- Variable Groups (Read)
|
||||||
|
|
||||||
|
Optionally, the following environment variables can be set:
|
||||||
|
|
||||||
|
- `AZURE_DEVOPS_INSTANCE_URL`: The base URL of your Azure DevOps instance (only required if it is **not** <https://dev.azure.com>).
|
||||||
|
|
||||||
|
### Circle CI
|
||||||
|
|
||||||
|
The following secrets are required:
|
||||||
|
|
||||||
|
- `CIRCLE_CI_ACCESS_TOKEN`: The personal access token to access the Circle CI instance.
|
||||||
|
- `CIRCLE_CI_SOURCE_GITHUB_ACCESS_TOKEN`: The personal access token to access pipeline files stored in GitHub.
|
||||||
|
|
||||||
|
Optionally, the following environment variables can be set:
|
||||||
|
|
||||||
|
- `CIRCLE_CI_INSTANCE_URL`: The base URL of your Circle CI instance (only required if it is **not** <https://circleci.com>).
|
||||||
|
|
||||||
|
### GitLab CI
|
||||||
|
|
||||||
|
The following secrets are required:
|
||||||
|
|
||||||
|
- `GITLAB_ACCESS_TOKEN`: The personal access token to access the GitLab CI instance (requires `read_api` scope).
|
||||||
|
|
||||||
|
Optionally, the following environment variables can be set:
|
||||||
|
|
||||||
|
- `GITLAB_INSTANCE_URL`: The base URL of your GitLab CI instance (only required if it is **not** <https://gitlab.com>).
|
||||||
|
|
||||||
|
### Jenkins
|
||||||
|
|
||||||
|
The following secrets are required:
|
||||||
|
|
||||||
|
- `JENKINSFILE_ACCESS_TOKEN`: The personal access token used to retrieve the contents of a `Jenkinsfile` stored in the build repository (requires `repo` scope).
|
||||||
|
- `JENKINS_ACCESS_TOKEN`: The access token used to view Jenkins resources.
|
||||||
|
- `JENKINS_USERNAME`: The username of the user's access token.
|
||||||
|
|
||||||
|
The following environment variables are required:
|
||||||
|
|
||||||
|
- `JENKINS_INSTANCE_URL`: The base URL of your Jenkins instance.
|
||||||
|
|
||||||
|
### Travis CI
|
||||||
|
|
||||||
|
The following secrets are required:
|
||||||
|
|
||||||
|
- `TRAVIS_CI_ACCESS_TOKEN`: The personal access token to access the Travis CI instance.
|
||||||
|
- `TRAVIS_CI_SOURCE_GITHUB_ACCESS_TOKEN`: The personal access token to access pipeline files stored in GitHub.
|
||||||
|
|
||||||
|
Optionally, the following environment variables can be set:
|
||||||
|
|
||||||
|
- `TRAVIS_CI_INSTANCE_URL`: The base URL of your Travis CI instance (only required if it is **not** <https://travis-ci.com>).
|
||||||
|
|
||||||
|
## Pipeline migration
|
||||||
|
|
||||||
|
Once configured, pipelines can be migrated to GitHub Actions by opening an issue with the relevant issue template and following the instructions.
|
||||||
|
|||||||
Executable
+7
@@ -0,0 +1,7 @@
|
|||||||
|
#!/usr/bin/env ruby
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require "bundler/setup"
|
||||||
|
require "./cli"
|
||||||
|
|
||||||
|
Pry.start
|
||||||
Executable
+26
@@ -0,0 +1,26 @@
|
|||||||
|
#!/usr/bin/env ruby
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require "yaml"
|
||||||
|
require "open3"
|
||||||
|
|
||||||
|
require_relative "./../cli"
|
||||||
|
|
||||||
|
issue_content, comment_body, labels = ARGV
|
||||||
|
|
||||||
|
puts labels
|
||||||
|
|
||||||
|
raise "No issue content provided" if issue_content.nil?
|
||||||
|
raise "No comment provided" if comment_body.nil?
|
||||||
|
raise "No labels provided" if labels.nil?
|
||||||
|
|
||||||
|
provider = Provider.new(labels)
|
||||||
|
command = Command.new(comment_body)
|
||||||
|
|
||||||
|
arguments = Arguments.new(provider, command, issue_content)
|
||||||
|
|
||||||
|
return unless command.valid?
|
||||||
|
|
||||||
|
provider.to_output
|
||||||
|
command.to_output
|
||||||
|
arguments.to_output
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
#!/usr/bin/env ruby
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
#
|
||||||
|
# This file was generated by Bundler.
|
||||||
|
#
|
||||||
|
# The application 'rspec' is installed as part of a gem, and
|
||||||
|
# this file is here to facilitate running it.
|
||||||
|
#
|
||||||
|
|
||||||
|
require "pathname"
|
||||||
|
ENV["BUNDLE_GEMFILE"] ||= File.expand_path(
|
||||||
|
"../../Gemfile",
|
||||||
|
Pathname.new(__FILE__).realpath
|
||||||
|
)
|
||||||
|
|
||||||
|
bundle_binstub = File.expand_path("bundle", __dir__)
|
||||||
|
|
||||||
|
if File.file?(bundle_binstub)
|
||||||
|
if /This file was generated by Bundler/.match?(File.read(bundle_binstub, 300))
|
||||||
|
load(bundle_binstub)
|
||||||
|
else
|
||||||
|
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
||||||
|
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
require "rubygems"
|
||||||
|
require "bundler/setup"
|
||||||
|
|
||||||
|
load Gem.bin_path("rspec-core", "rspec")
|
||||||
Executable
+31
@@ -0,0 +1,31 @@
|
|||||||
|
#!/usr/bin/env ruby
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
#
|
||||||
|
# This file was generated by Bundler.
|
||||||
|
#
|
||||||
|
# The application 'rubocop' is installed as part of a gem, and
|
||||||
|
# this file is here to facilitate running it.
|
||||||
|
#
|
||||||
|
|
||||||
|
require "pathname"
|
||||||
|
ENV["BUNDLE_GEMFILE"] ||= File.expand_path(
|
||||||
|
"../../Gemfile",
|
||||||
|
Pathname.new(__FILE__).realpath
|
||||||
|
)
|
||||||
|
|
||||||
|
bundle_binstub = File.expand_path("bundle", __dir__)
|
||||||
|
|
||||||
|
if File.file?(bundle_binstub)
|
||||||
|
if /This file was generated by Bundler/.match?(File.read(bundle_binstub, 300))
|
||||||
|
load(bundle_binstub)
|
||||||
|
else
|
||||||
|
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
||||||
|
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
require "rubygems"
|
||||||
|
require "bundler/setup"
|
||||||
|
|
||||||
|
load Gem.bin_path("rubocop", "rubocop")
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require "require_all"
|
||||||
|
require "pry" if ENV["VALET_CONTAINER"].nil?
|
||||||
|
require "json"
|
||||||
|
|
||||||
|
require_all "lib"
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module IssueParser
|
||||||
|
def parameter_from_issue(name, text)
|
||||||
|
match = text.match(/#{name}: ([^\n]+)/)
|
||||||
|
return if match.nil?
|
||||||
|
|
||||||
|
match[1].strip
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module OutputWriter
|
||||||
|
def set_output(name, value)
|
||||||
|
return if value.nil?
|
||||||
|
|
||||||
|
puts "::set-output name=#{name}::#{value}"
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require_relative "../concerns/output_writer"
|
||||||
|
|
||||||
|
class Arguments
|
||||||
|
include OutputWriter
|
||||||
|
|
||||||
|
def initialize(provider, command, issue_content)
|
||||||
|
@args = argument_class(provider, command, issue_content)
|
||||||
|
end
|
||||||
|
|
||||||
|
def argument_class(provider, command, issue_content)
|
||||||
|
provider.module.const_get(command.classify).new(issue_content, command)
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_output
|
||||||
|
arguments = @args.to_a
|
||||||
|
return if arguments.blank?
|
||||||
|
|
||||||
|
set_output(
|
||||||
|
"args",
|
||||||
|
arguments.map do |a|
|
||||||
|
next a unless a.include?(" ")
|
||||||
|
|
||||||
|
a.inspect
|
||||||
|
end.join(" ")
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module AzureDevops
|
||||||
|
class Audit
|
||||||
|
include IssueParser
|
||||||
|
|
||||||
|
def initialize(issue_content, _)
|
||||||
|
@organization = parameter_from_issue("Organization", issue_content)
|
||||||
|
@project = parameter_from_issue("Project", issue_content)
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_a
|
||||||
|
args = []
|
||||||
|
args.concat(["--azure-devops-organization", @organization]) unless @organization.nil?
|
||||||
|
args.concat(["--azure-devops-project", @project]) unless @project.nil?
|
||||||
|
|
||||||
|
return args unless args.empty?
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module AzureDevops
|
||||||
|
class DryRun
|
||||||
|
include IssueParser
|
||||||
|
|
||||||
|
def initialize(issue_content, command)
|
||||||
|
@organization = parameter_from_issue("Organization", issue_content)
|
||||||
|
@project = parameter_from_issue("Project", issue_content)
|
||||||
|
|
||||||
|
@pipeline_type = command.options.fetch("pipeline-type", "pipeline")
|
||||||
|
@pipeline_id = command.options["pipeline-id"]
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_a
|
||||||
|
args = [@pipeline_type]
|
||||||
|
args.concat(["--azure-devops-organization", @organization]) unless @organization.nil?
|
||||||
|
args.concat(["--azure-devops-project", @project]) unless @project.nil?
|
||||||
|
args.concat(["--pipeline-id", @pipeline_id]) unless @pipeline_id.nil?
|
||||||
|
|
||||||
|
return args unless args.empty?
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module AzureDevops
|
||||||
|
class Migrate
|
||||||
|
include IssueParser
|
||||||
|
|
||||||
|
def initialize(issue_content, command)
|
||||||
|
@organization = parameter_from_issue("Organization", issue_content)
|
||||||
|
@project = parameter_from_issue("Project", issue_content)
|
||||||
|
|
||||||
|
@pipeline_type = command.options.fetch("pipeline-type", "pipeline")
|
||||||
|
@pipeline_id = command.options["pipeline-id"]
|
||||||
|
@target_url = command.options["target-url"]
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_a
|
||||||
|
args = [@pipeline_type]
|
||||||
|
args.concat(["--azure-devops-organization", @organization]) unless @organization.nil?
|
||||||
|
args.concat(["--azure-devops-project", @project]) unless @project.nil?
|
||||||
|
args.concat(["--pipeline-id", @pipeline_id]) unless @pipeline_id.nil?
|
||||||
|
args.concat(["--target-url", @target_url]) unless @target_url.nil?
|
||||||
|
|
||||||
|
return args unless args.empty?
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module CircleCI
|
||||||
|
class Audit
|
||||||
|
include IssueParser
|
||||||
|
|
||||||
|
def initialize(issue_content, _)
|
||||||
|
@organization = parameter_from_issue("Organization", issue_content)
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_a
|
||||||
|
return if @organization.nil?
|
||||||
|
|
||||||
|
["--circle-ci-organization", @organization]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module CircleCI
|
||||||
|
class DryRun
|
||||||
|
include IssueParser
|
||||||
|
|
||||||
|
def initialize(issue_content, command)
|
||||||
|
# TODO: manually test this
|
||||||
|
@organization = parameter_from_issue("Organization", issue_content)
|
||||||
|
@project = command.options["project"]
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_a
|
||||||
|
args = []
|
||||||
|
args.concat(["--circle-ci-organization", @organization]) unless @organization.nil?
|
||||||
|
args.concat(["--circle-ci-project", @project]) unless @project.nil?
|
||||||
|
|
||||||
|
return args unless args.empty?
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module CircleCI
|
||||||
|
class Migrate
|
||||||
|
include IssueParser
|
||||||
|
|
||||||
|
def initialize(issue_content, command)
|
||||||
|
@organization = parameter_from_issue("Organization", issue_content)
|
||||||
|
@project = command.options["project"]
|
||||||
|
@target_url = command.options["target-url"]
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_a
|
||||||
|
args = []
|
||||||
|
args.concat(["--circle-ci-organization", @organization]) unless @organization.nil?
|
||||||
|
args.concat(["--circle-ci-project", @project]) unless @project.nil?
|
||||||
|
args.concat(["--target-url", @target_url]) unless @target_url.nil?
|
||||||
|
|
||||||
|
return args unless args.empty?
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require "active_support/core_ext/string"
|
||||||
|
require_relative "../concerns/output_writer"
|
||||||
|
|
||||||
|
class Command
|
||||||
|
include OutputWriter
|
||||||
|
|
||||||
|
VALID_COMMANDS = %w[audit migrate dry-run].freeze
|
||||||
|
|
||||||
|
def initialize(comment_body)
|
||||||
|
@comment_body = comment_body
|
||||||
|
end
|
||||||
|
|
||||||
|
def command
|
||||||
|
@command ||= begin
|
||||||
|
command = @comment_body&.match(%r{/([^\s\\]+)})
|
||||||
|
command[1] unless command.nil? || !VALID_COMMANDS.include?(command[1])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def valid?
|
||||||
|
!command.nil?
|
||||||
|
end
|
||||||
|
|
||||||
|
def classify
|
||||||
|
return unless valid?
|
||||||
|
|
||||||
|
command.tr("-", "_").classify
|
||||||
|
end
|
||||||
|
|
||||||
|
def options
|
||||||
|
return unless valid?
|
||||||
|
|
||||||
|
@options ||= begin
|
||||||
|
command_text = "/#{command}"
|
||||||
|
command_index = @comment_body.index(command_text)
|
||||||
|
|
||||||
|
options_text = @comment_body[command_index + command_text.length..-1]
|
||||||
|
options_text.split(" ")
|
||||||
|
.each_slice(2)
|
||||||
|
.to_h
|
||||||
|
.transform_keys { |key| key.delete_prefix("--") }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_output
|
||||||
|
set_output("command", command)
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module GitlabCI
|
||||||
|
class Audit
|
||||||
|
include IssueParser
|
||||||
|
|
||||||
|
def initialize(issue_content, _)
|
||||||
|
@namespace = parameter_from_issue("Namespace", issue_content)
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_a
|
||||||
|
return if @namespace.nil?
|
||||||
|
|
||||||
|
["--namespace", @namespace]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module GitlabCI
|
||||||
|
class DryRun
|
||||||
|
include IssueParser
|
||||||
|
|
||||||
|
def initialize(issue_content, command)
|
||||||
|
@namespace = parameter_from_issue("Namespace", issue_content)
|
||||||
|
@project = command.options["project"]
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_a
|
||||||
|
args = []
|
||||||
|
args.concat(["--namespace", @namespace]) unless @namespace.nil?
|
||||||
|
args.concat(["--project", @project]) unless @project.nil?
|
||||||
|
|
||||||
|
return args unless args.empty?
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module GitlabCI
|
||||||
|
class Migrate
|
||||||
|
include IssueParser
|
||||||
|
|
||||||
|
def initialize(issue_content, command)
|
||||||
|
@namespace = parameter_from_issue("Namespace", issue_content)
|
||||||
|
@project = command.options["project"]
|
||||||
|
@target_url = command.options["target-url"]
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_a
|
||||||
|
args = []
|
||||||
|
args.concat(["--namespace", @namespace]) unless @namespace.nil?
|
||||||
|
args.concat(["--project", @project]) unless @project.nil?
|
||||||
|
args.concat(["--target-url", @target_url]) unless @target_url.nil?
|
||||||
|
|
||||||
|
return args unless args.empty?
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Jenkins
|
||||||
|
class Audit
|
||||||
|
include IssueParser
|
||||||
|
|
||||||
|
def initialize(issue_content, _)
|
||||||
|
@folders = parameter_from_issue("Folders", issue_content)
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_a
|
||||||
|
return if @folders.nil?
|
||||||
|
|
||||||
|
["--folders", @folders]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Jenkins
|
||||||
|
class DryRun
|
||||||
|
include IssueParser
|
||||||
|
|
||||||
|
def initialize(_, command)
|
||||||
|
@source_url = command.options["source-url"]
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_a
|
||||||
|
return if @source_url.nil?
|
||||||
|
|
||||||
|
["--source-url", @source_url]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Jenkins
|
||||||
|
class Migrate
|
||||||
|
include IssueParser
|
||||||
|
|
||||||
|
def initialize(_, command)
|
||||||
|
@source_url = command.options["source-url"]
|
||||||
|
@target_url = command.options["target-url"]
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_a
|
||||||
|
args = []
|
||||||
|
args.concat(["--source-url", @source_url]) unless @source_url.nil?
|
||||||
|
args.concat(["--target-url", @target_url]) unless @target_url.nil?
|
||||||
|
|
||||||
|
return args unless args.empty?
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require_rel "./azure_devops/**/*.rb"
|
||||||
|
require_rel "./circle_ci/**/*.rb"
|
||||||
|
require_rel "./gitlab_ci/**/*.rb"
|
||||||
|
require_rel "./jenkins/**/*.rb"
|
||||||
|
require_rel "./travis_ci/**/*.rb"
|
||||||
|
|
||||||
|
class Provider
|
||||||
|
include OutputWriter
|
||||||
|
|
||||||
|
PROVIDER_MAP = {
|
||||||
|
"azure-devops" => ::AzureDevops,
|
||||||
|
"circle-ci" => ::CircleCI,
|
||||||
|
"gitlab" => ::GitlabCI,
|
||||||
|
"jenkins" => ::Jenkins,
|
||||||
|
"travis-ci" => ::TravisCI
|
||||||
|
}.freeze
|
||||||
|
|
||||||
|
def initialize(labels)
|
||||||
|
labels = labels.tr("\n", "").delete_prefix("[").delete_suffix("]").split(",").map(&:strip)
|
||||||
|
providers = labels.select { |label| PROVIDER_MAP.key?(label) }
|
||||||
|
|
||||||
|
raise "One provider must be selected" if providers.empty?
|
||||||
|
raise "Only one provider can be selected" unless providers.one?
|
||||||
|
|
||||||
|
@provider = providers.first
|
||||||
|
end
|
||||||
|
|
||||||
|
def cli_command
|
||||||
|
@provider
|
||||||
|
end
|
||||||
|
|
||||||
|
def module
|
||||||
|
PROVIDER_MAP[@provider]
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_output
|
||||||
|
set_output("provider", cli_command)
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module TravisCI
|
||||||
|
class Audit
|
||||||
|
include IssueParser
|
||||||
|
|
||||||
|
def initialize(issue_content, _)
|
||||||
|
@organization = parameter_from_issue("Organization", issue_content)
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_a
|
||||||
|
return if @organization.nil?
|
||||||
|
|
||||||
|
["--travis-ci-organization", @organization]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module TravisCI
|
||||||
|
class DryRun
|
||||||
|
include IssueParser
|
||||||
|
|
||||||
|
def initialize(issue_content, command)
|
||||||
|
@organization = parameter_from_issue("Organization", issue_content)
|
||||||
|
@repository = command.options["repository"]
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_a
|
||||||
|
args = []
|
||||||
|
args.concat(["--travis-ci-organization", @organization]) unless @organization.nil?
|
||||||
|
args.concat(["--travis-ci-repository", @repository]) unless @repository.nil?
|
||||||
|
|
||||||
|
return args unless args.empty?
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module TravisCI
|
||||||
|
class Migrate
|
||||||
|
include IssueParser
|
||||||
|
|
||||||
|
def initialize(issue_content, command)
|
||||||
|
@organization = parameter_from_issue("Organization", issue_content)
|
||||||
|
@repository = command.options["repository"]
|
||||||
|
@target_url = command.options["target-url"]
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_a
|
||||||
|
args = []
|
||||||
|
args.concat(["--travis-ci-organization", @organization]) unless @organization.nil?
|
||||||
|
args.concat(["--travis-ci-repository", @repository]) unless @repository.nil?
|
||||||
|
args.concat(["--target-url", @target_url]) unless @target_url.nil?
|
||||||
|
|
||||||
|
return args unless args.empty?
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
RSpec.describe OutputWriter do
|
||||||
|
let(:test_class) do
|
||||||
|
class TestClass
|
||||||
|
include OutputWriter
|
||||||
|
end
|
||||||
|
|
||||||
|
TestClass.new
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#set_output" do
|
||||||
|
let(:name) { "var_name" }
|
||||||
|
let(:value) { "var_value" }
|
||||||
|
|
||||||
|
subject { test_class.set_output(name, value) }
|
||||||
|
|
||||||
|
it { expect { subject }.to output(/::set-output name=#{name}::#{value}/).to_stdout }
|
||||||
|
|
||||||
|
context "when value is nil" do
|
||||||
|
let(:value) { nil }
|
||||||
|
|
||||||
|
it { expect { subject }.not_to output(/::set-output name=#{name}::#{value}/).to_stdout }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
RSpec.describe Arguments do
|
||||||
|
let(:arguments) { Arguments.new(provider, command, issue_content) }
|
||||||
|
let(:provider) { instance_double(Provider) }
|
||||||
|
let(:command) { instance_double(Command) }
|
||||||
|
let(:issue_content) { "some issue content" }
|
||||||
|
|
||||||
|
describe "#argument_class" do
|
||||||
|
subject { arguments.argument_class(provider, command, issue_content) }
|
||||||
|
|
||||||
|
context "when the command is found" do
|
||||||
|
before do
|
||||||
|
expect(provider).to receive(:module).and_return(::Jenkins).at_least(:once)
|
||||||
|
expect(command).to receive(:classify).and_return("Audit").at_least(:once)
|
||||||
|
end
|
||||||
|
|
||||||
|
it { is_expected.to be_a(::Jenkins::Audit) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when the command is not found" do
|
||||||
|
before do
|
||||||
|
expect(provider).to receive(:module).and_return(::Jenkins).at_least(:once)
|
||||||
|
expect(command).to receive(:classify).and_return("Whoopsie").at_least(:once)
|
||||||
|
end
|
||||||
|
|
||||||
|
it { expect { subject }.to raise_error(NameError) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#to_output" do
|
||||||
|
subject { arguments.to_output }
|
||||||
|
|
||||||
|
before do
|
||||||
|
expect(provider).to receive(:module).and_return(::AzureDevops).at_least(:once)
|
||||||
|
expect(command).to receive(:classify).and_return("Audit").at_least(:once)
|
||||||
|
expect_any_instance_of(::AzureDevops::Audit).to receive(:to_a).and_return(output)
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when the output is nil" do
|
||||||
|
let(:output) { nil }
|
||||||
|
|
||||||
|
it "does not write any output variable" do
|
||||||
|
expect(arguments).not_to receive(:set_output)
|
||||||
|
subject
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when the output is not nil" do
|
||||||
|
let(:output) { ["--option", "value"] }
|
||||||
|
|
||||||
|
it "writes an output variable" do
|
||||||
|
expect(arguments).to receive(:set_output).with("args", "--option value")
|
||||||
|
subject
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when the output contains a space" do
|
||||||
|
let(:output) { ["--option", "some value"] }
|
||||||
|
|
||||||
|
it "writes an output variable" do
|
||||||
|
expect(arguments).to receive(:set_output).with("args", "--option \"some value\"")
|
||||||
|
subject
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
RSpec.describe AzureDevops::Audit do
|
||||||
|
let(:audit) { described_class.new(issue_content, nil) }
|
||||||
|
|
||||||
|
describe "#to_a" do
|
||||||
|
subject { audit.to_a }
|
||||||
|
|
||||||
|
context "when issue_content contains no args" do
|
||||||
|
let(:issue_content) do
|
||||||
|
<<~ISSUE
|
||||||
|
Organization:
|
||||||
|
Project:
|
||||||
|
ISSUE
|
||||||
|
end
|
||||||
|
|
||||||
|
it { is_expected.to be_nil }
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when issue_content contains an organization" do
|
||||||
|
let(:issue_content) do
|
||||||
|
<<~ISSUE
|
||||||
|
Organization: my-organization
|
||||||
|
Project:
|
||||||
|
ISSUE
|
||||||
|
end
|
||||||
|
|
||||||
|
it { is_expected.to eq(["--azure-devops-organization", "my-organization"]) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when issue_content contains a project" do
|
||||||
|
let(:issue_content) do
|
||||||
|
<<~ISSUE
|
||||||
|
Organization: my-organization
|
||||||
|
Project: my-project
|
||||||
|
ISSUE
|
||||||
|
end
|
||||||
|
|
||||||
|
it { is_expected.to eq(["--azure-devops-organization", "my-organization", "--azure-devops-project", "my-project"]) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
RSpec.describe AzureDevops::DryRun do
|
||||||
|
let(:dry_run) { described_class.new(issue_content, command) }
|
||||||
|
let(:command) { Command.new(comment_body) }
|
||||||
|
|
||||||
|
describe "#to_a" do
|
||||||
|
subject { dry_run.to_a }
|
||||||
|
let(:issue_content) do
|
||||||
|
<<~ISSUE
|
||||||
|
Organization: my-organization
|
||||||
|
Project: my-project
|
||||||
|
ISSUE
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when the comment body does not contain a pipeline type" do
|
||||||
|
let(:comment_body) { "/dry-run" }
|
||||||
|
|
||||||
|
it { is_expected.to eq(["pipeline", "--azure-devops-organization", "my-organization", "--azure-devops-project", "my-project"]) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when the comment body contains a pipeline id" do
|
||||||
|
let(:comment_body) { "/dry-run --pipeline-id 42" }
|
||||||
|
|
||||||
|
it { is_expected.to eq(["pipeline", "--azure-devops-organization", "my-organization", "--azure-devops-project", "my-project", "--pipeline-id", "42"]) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
RSpec.describe AzureDevops::Migrate do
|
||||||
|
let(:dry_run) { described_class.new(issue_content, command) }
|
||||||
|
let(:command) { Command.new(comment_body) }
|
||||||
|
|
||||||
|
describe "#to_a" do
|
||||||
|
subject { dry_run.to_a }
|
||||||
|
let(:issue_content) do
|
||||||
|
<<~ISSUE
|
||||||
|
Organization: my-organization
|
||||||
|
Project: my-project
|
||||||
|
ISSUE
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when the comment body does not contain a pipeline type" do
|
||||||
|
let(:comment_body) { "/migrate" }
|
||||||
|
|
||||||
|
it { is_expected.to eq(["pipeline", "--azure-devops-organization", "my-organization", "--azure-devops-project", "my-project"]) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when the comment body contains a pipeline id" do
|
||||||
|
let(:comment_body) { "/migrate --pipeline-id 42 --target-url https://github.com/org/repo" }
|
||||||
|
|
||||||
|
it { is_expected.to eq(["pipeline", "--azure-devops-organization", "my-organization", "--azure-devops-project", "my-project", "--pipeline-id", "42", "--target-url", "https://github.com/org/repo"]) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
RSpec.describe CircleCI::Audit do
|
||||||
|
let(:audit) { described_class.new(issue_content, nil) }
|
||||||
|
|
||||||
|
describe "#to_a" do
|
||||||
|
subject { audit.to_a }
|
||||||
|
|
||||||
|
context "when issue_content contains no args" do
|
||||||
|
let(:issue_content) do
|
||||||
|
<<~ISSUE
|
||||||
|
Organization:
|
||||||
|
ISSUE
|
||||||
|
end
|
||||||
|
|
||||||
|
it { is_expected.to be_nil }
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when issue_content contains a organization" do
|
||||||
|
let(:issue_content) do
|
||||||
|
<<~ISSUE
|
||||||
|
Organization: testing
|
||||||
|
ISSUE
|
||||||
|
end
|
||||||
|
|
||||||
|
it { is_expected.to eq(["--circle-ci-organization", "testing"]) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
RSpec.describe CircleCI::DryRun do
|
||||||
|
let(:dry_run) { described_class.new(issue_content, command) }
|
||||||
|
let(:command) { Command.new(comment_body) }
|
||||||
|
|
||||||
|
describe "#to_a" do
|
||||||
|
subject { dry_run.to_a }
|
||||||
|
let(:issue_content) do
|
||||||
|
<<~ISSUE
|
||||||
|
Organization: testing
|
||||||
|
ISSUE
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when the comment body contains a project" do
|
||||||
|
let(:comment_body) { "/dry-run --project repo" }
|
||||||
|
|
||||||
|
it { is_expected.to eq(["--circle-ci-organization", "testing", "--circle-ci-project", "repo"]) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
RSpec.describe CircleCI::Migrate do
|
||||||
|
let(:dry_run) { described_class.new(issue_content, command) }
|
||||||
|
let(:command) { Command.new(comment_body) }
|
||||||
|
|
||||||
|
describe "#to_a" do
|
||||||
|
subject { dry_run.to_a }
|
||||||
|
let(:issue_content) do
|
||||||
|
<<~ISSUE
|
||||||
|
Organization: testing
|
||||||
|
ISSUE
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when the comment body contains a project" do
|
||||||
|
let(:comment_body) { "/migrate --project repo --target-url https://github.com/org/repo" }
|
||||||
|
|
||||||
|
it { is_expected.to eq(["--circle-ci-organization", "testing", "--circle-ci-project", "repo", "--target-url", "https://github.com/org/repo"]) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,109 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
RSpec.describe Command do
|
||||||
|
let(:command) { described_class.new(comment_body) }
|
||||||
|
|
||||||
|
describe "#command" do
|
||||||
|
subject { command.command }
|
||||||
|
|
||||||
|
context "when no command is present" do
|
||||||
|
let(:comment_body) do
|
||||||
|
<<~COMMENT
|
||||||
|
This is just a comment.
|
||||||
|
COMMENT
|
||||||
|
end
|
||||||
|
|
||||||
|
it { is_expected.to be_nil }
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when an unsupported comment is present" do
|
||||||
|
let(:comment_body) do
|
||||||
|
<<~COMMENT
|
||||||
|
/do-something-unsupported
|
||||||
|
COMMENT
|
||||||
|
end
|
||||||
|
|
||||||
|
it { is_expected.to be_nil }
|
||||||
|
end
|
||||||
|
|
||||||
|
described_class::VALID_COMMANDS.each do |c|
|
||||||
|
context "when a supported command is present" do
|
||||||
|
let(:comment_body) do
|
||||||
|
<<~COMMENT
|
||||||
|
/#{c}
|
||||||
|
COMMENT
|
||||||
|
end
|
||||||
|
|
||||||
|
it { is_expected.to eq(c) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#options" do
|
||||||
|
subject { command.options }
|
||||||
|
|
||||||
|
context "when the command is not valid" do
|
||||||
|
let(:comment_body) { "/do-something-unsupported --option-one value" }
|
||||||
|
|
||||||
|
it { is_expected.to be_nil }
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when no options are present" do
|
||||||
|
let(:comment_body) { "/dry-run" }
|
||||||
|
|
||||||
|
it { is_expected.to be_blank }
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when options are present" do
|
||||||
|
let(:comment_body) { "/dry-run --option-one value-one --option-two value-two" }
|
||||||
|
|
||||||
|
it { is_expected.to eq({ "option-one" => "value-one", "option-two" => "value-two" }) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#valid?" do
|
||||||
|
subject { command.valid? }
|
||||||
|
|
||||||
|
context "when the command is supported" do
|
||||||
|
let(:comment_body) { "/dry-run" }
|
||||||
|
|
||||||
|
it { is_expected.to be_truthy }
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when the command is not supported" do
|
||||||
|
let(:comment_body) { "/run-something-else" }
|
||||||
|
|
||||||
|
it { is_expected.to be_falsey }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#classify" do
|
||||||
|
subject { command.classify }
|
||||||
|
|
||||||
|
[%w[audit Audit], %w[dry-run DryRun], %w[migrate Migrate]].each do |command, klass|
|
||||||
|
context "when the command is #{command}" do
|
||||||
|
let(:comment_body) { "/#{command}" }
|
||||||
|
|
||||||
|
it { is_expected.to eq(klass) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when the command is invalid" do
|
||||||
|
let(:comment_body) { "/do-something-unsupported" }
|
||||||
|
|
||||||
|
it { is_expected.to be_nil }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "to_output" do
|
||||||
|
subject { command.to_output }
|
||||||
|
|
||||||
|
let(:comment_body) do
|
||||||
|
<<~COMMENT
|
||||||
|
/audit
|
||||||
|
COMMENT
|
||||||
|
end
|
||||||
|
|
||||||
|
it { expect { subject }.to output(/::set-output name=command::audit/).to_stdout }
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
RSpec.describe GitlabCI::Audit do
|
||||||
|
let(:audit) { described_class.new(issue_content, nil) }
|
||||||
|
|
||||||
|
describe "#to_a" do
|
||||||
|
subject { audit.to_a }
|
||||||
|
|
||||||
|
context "when issue_content contains no args" do
|
||||||
|
let(:issue_content) do
|
||||||
|
<<~ISSUE
|
||||||
|
Namespace:
|
||||||
|
ISSUE
|
||||||
|
end
|
||||||
|
|
||||||
|
it { is_expected.to be_nil }
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when issue_content contains a namespace" do
|
||||||
|
let(:issue_content) do
|
||||||
|
<<~ISSUE
|
||||||
|
Namespace: testing
|
||||||
|
ISSUE
|
||||||
|
end
|
||||||
|
|
||||||
|
it { is_expected.to eq(["--namespace", "testing"]) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
RSpec.describe GitlabCI::DryRun do
|
||||||
|
let(:dry_run) { described_class.new(issue_content, command) }
|
||||||
|
let(:command) { Command.new(comment_body) }
|
||||||
|
|
||||||
|
describe "#to_a" do
|
||||||
|
subject { dry_run.to_a }
|
||||||
|
let(:issue_content) do
|
||||||
|
<<~ISSUE
|
||||||
|
Namespace: testing
|
||||||
|
ISSUE
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when the comment body contains a pipeline id" do
|
||||||
|
let(:comment_body) { "/dry-run --project project" }
|
||||||
|
|
||||||
|
it { is_expected.to eq(["--namespace", "testing", "--project", "project"]) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
RSpec.describe GitlabCI::Migrate do
|
||||||
|
let(:dry_run) { described_class.new(issue_content, command) }
|
||||||
|
let(:command) { Command.new(comment_body) }
|
||||||
|
|
||||||
|
describe "#to_a" do
|
||||||
|
subject { dry_run.to_a }
|
||||||
|
let(:issue_content) do
|
||||||
|
<<~ISSUE
|
||||||
|
Namespace: testing
|
||||||
|
ISSUE
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when the comment body contains a pipeline id" do
|
||||||
|
let(:comment_body) { "/migrate --project project --target-url https://github.com/org/repo" }
|
||||||
|
|
||||||
|
it { is_expected.to eq(["--namespace", "testing", "--project", "project", "--target-url", "https://github.com/org/repo"]) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
RSpec.describe Jenkins::Audit do
|
||||||
|
let(:audit) { described_class.new(issue_content, nil) }
|
||||||
|
|
||||||
|
describe "#to_a" do
|
||||||
|
subject { audit.to_a }
|
||||||
|
|
||||||
|
context "when issue_content contains no args" do
|
||||||
|
let(:issue_content) do
|
||||||
|
<<~ISSUE
|
||||||
|
Folders:
|
||||||
|
ISSUE
|
||||||
|
end
|
||||||
|
|
||||||
|
it { is_expected.to be_nil }
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when issue_content contains a folder" do
|
||||||
|
let(:issue_content) do
|
||||||
|
<<~ISSUE
|
||||||
|
Folders: test, prod
|
||||||
|
ISSUE
|
||||||
|
end
|
||||||
|
|
||||||
|
it { is_expected.to eq(["--folders", "test, prod"]) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
RSpec.describe Jenkins::DryRun do
|
||||||
|
let(:dry_run) { described_class.new(nil, command) }
|
||||||
|
let(:command) { Command.new(comment_body) }
|
||||||
|
|
||||||
|
describe "#to_a" do
|
||||||
|
subject { dry_run.to_a }
|
||||||
|
|
||||||
|
context "when the comment body contains a pipeline id" do
|
||||||
|
let(:comment_body) { "/dry-run --source-url https://jenkins.company.com/job/pipeline" }
|
||||||
|
|
||||||
|
it { is_expected.to eq(["--source-url", "https://jenkins.company.com/job/pipeline"]) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
RSpec.describe Jenkins::Migrate do
|
||||||
|
let(:dry_run) { described_class.new(nil, command) }
|
||||||
|
let(:command) { Command.new(comment_body) }
|
||||||
|
|
||||||
|
describe "#to_a" do
|
||||||
|
subject { dry_run.to_a }
|
||||||
|
|
||||||
|
context "when the comment body contains a pipeline id" do
|
||||||
|
let(:comment_body) { "/migrate --source-url https://jenkins.company.com/job/pipeline --target-url https://github.com/org/repo" }
|
||||||
|
|
||||||
|
it { is_expected.to eq(["--source-url", "https://jenkins.company.com/job/pipeline", "--target-url", "https://github.com/org/repo"]) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,97 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
RSpec.describe Provider do
|
||||||
|
let(:provider) { described_class.new(labels) }
|
||||||
|
|
||||||
|
describe "#initialize" do
|
||||||
|
subject { provider }
|
||||||
|
|
||||||
|
context "when no providers are selected" do
|
||||||
|
let(:labels) do
|
||||||
|
<<~LABELS
|
||||||
|
[]
|
||||||
|
LABELS
|
||||||
|
end
|
||||||
|
|
||||||
|
it { expect { subject }.to raise_error("One provider must be selected") }
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when multiple providers are selected" do
|
||||||
|
let(:labels) do
|
||||||
|
<<~LABELS
|
||||||
|
[
|
||||||
|
jenkins,
|
||||||
|
azure-devops
|
||||||
|
]
|
||||||
|
LABELS
|
||||||
|
end
|
||||||
|
|
||||||
|
it { expect { subject }.to raise_error("Only one provider can be selected") }
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when an unsupported provider is selected" do
|
||||||
|
let(:labels) do
|
||||||
|
<<~LABELS
|
||||||
|
[
|
||||||
|
something-unsupported
|
||||||
|
]
|
||||||
|
LABELS
|
||||||
|
end
|
||||||
|
|
||||||
|
it { expect { subject }.to raise_error("One provider must be selected") }
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when a single provider is selected" do
|
||||||
|
let(:labels) do
|
||||||
|
<<~LABELS
|
||||||
|
[
|
||||||
|
jenkins
|
||||||
|
]
|
||||||
|
LABELS
|
||||||
|
end
|
||||||
|
|
||||||
|
it { expect { subject }.not_to raise_error }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#cli_command" do
|
||||||
|
subject { provider.cli_command }
|
||||||
|
let(:labels) do
|
||||||
|
<<~LABELS
|
||||||
|
[
|
||||||
|
gitlab
|
||||||
|
]
|
||||||
|
LABELS
|
||||||
|
end
|
||||||
|
|
||||||
|
it { is_expected.to eq("gitlab") }
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#module" do
|
||||||
|
subject { provider.module }
|
||||||
|
|
||||||
|
let(:labels) do
|
||||||
|
<<~LABELS
|
||||||
|
[
|
||||||
|
travis-ci
|
||||||
|
]
|
||||||
|
LABELS
|
||||||
|
end
|
||||||
|
|
||||||
|
it { is_expected.to eq(::TravisCI) }
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "to_output" do
|
||||||
|
subject { provider.to_output }
|
||||||
|
|
||||||
|
let(:labels) do
|
||||||
|
<<~LABELS
|
||||||
|
[
|
||||||
|
azure-devops
|
||||||
|
]
|
||||||
|
LABELS
|
||||||
|
end
|
||||||
|
|
||||||
|
it { expect { subject }.to output(/::set-output name=provider::azure-devops/).to_stdout }
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
RSpec.describe TravisCI::Audit do
|
||||||
|
let(:audit) { described_class.new(issue_content, nil) }
|
||||||
|
|
||||||
|
describe "#to_a" do
|
||||||
|
subject { audit.to_a }
|
||||||
|
|
||||||
|
context "when issue_content contains no args" do
|
||||||
|
let(:issue_content) do
|
||||||
|
<<~ISSUE
|
||||||
|
Organization:
|
||||||
|
ISSUE
|
||||||
|
end
|
||||||
|
|
||||||
|
it { is_expected.to be_nil }
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when issue_content contains an organization" do
|
||||||
|
let(:issue_content) do
|
||||||
|
<<~ISSUE
|
||||||
|
Organization: testing
|
||||||
|
ISSUE
|
||||||
|
end
|
||||||
|
|
||||||
|
it { is_expected.to eq(["--travis-ci-organization", "testing"]) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
RSpec.describe TravisCI::DryRun do
|
||||||
|
let(:dry_run) { described_class.new(issue_content, command) }
|
||||||
|
let(:command) { Command.new(comment_body) }
|
||||||
|
|
||||||
|
describe "#to_a" do
|
||||||
|
subject { dry_run.to_a }
|
||||||
|
let(:issue_content) do
|
||||||
|
<<~ISSUE
|
||||||
|
Organization: testing
|
||||||
|
ISSUE
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when the comment body contains a pipeline id" do
|
||||||
|
let(:comment_body) { "/dry-run --repository repo" }
|
||||||
|
|
||||||
|
it { is_expected.to eq(["--travis-ci-organization", "testing", "--travis-ci-repository", "repo"]) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
RSpec.describe TravisCI::Migrate do
|
||||||
|
let(:dry_run) { described_class.new(issue_content, command) }
|
||||||
|
let(:command) { Command.new(comment_body) }
|
||||||
|
|
||||||
|
describe "#to_a" do
|
||||||
|
subject { dry_run.to_a }
|
||||||
|
let(:issue_content) do
|
||||||
|
<<~ISSUE
|
||||||
|
Organization: testing
|
||||||
|
ISSUE
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when the comment body contains a pipeline id" do
|
||||||
|
let(:comment_body) { "/migrate --repository repo --target-url https://github.com/org/repo" }
|
||||||
|
|
||||||
|
it { is_expected.to eq(["--travis-ci-organization", "testing", "--travis-ci-repository", "repo", "--target-url", "https://github.com/org/repo"]) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require "bundler/setup"
|
||||||
|
require "factory_bot"
|
||||||
|
require "faker"
|
||||||
|
|
||||||
|
require_relative "./../cli"
|
||||||
|
|
||||||
|
Dir[File.join(__dir__, "support/**/*.rb")].sort.each { |f| require f }
|
||||||
|
|
||||||
|
RSpec.configure do |config|
|
||||||
|
# Enable flags like --only-failures and --next-failure
|
||||||
|
config.example_status_persistence_file_path = ".rspec_status"
|
||||||
|
|
||||||
|
# Disable RSpec exposing methods globally on `Module` and `main`
|
||||||
|
config.disable_monkey_patching!
|
||||||
|
|
||||||
|
config.expect_with :rspec do |c|
|
||||||
|
# Override truncation of expected/got output
|
||||||
|
c.max_formatted_output_length = 1000
|
||||||
|
c.syntax = :expect
|
||||||
|
end
|
||||||
|
|
||||||
|
config.include FactoryBot::Syntax::Methods
|
||||||
|
|
||||||
|
config.before(:suite) do
|
||||||
|
FactoryBot.find_definitions
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require "shoulda-matchers"
|
||||||
|
|
||||||
|
Shoulda::Matchers.configure do |config|
|
||||||
|
config.integrate do |with|
|
||||||
|
with.test_framework :rspec
|
||||||
|
end
|
||||||
|
end
|
||||||
Reference in New Issue
Block a user