diff --git a/.dockerignore b/.dockerignore index 5518248399..de83a0a3bc 100644 --- a/.dockerignore +++ b/.dockerignore @@ -7,6 +7,7 @@ tmp # dependencies bower_components node_modules +tests # misc .env* diff --git a/.travis.yml b/.travis.yml index e63d64adc3..fd51f34e20 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,7 @@ --- language: node_js node_js: 10 +group: edge env: global: @@ -21,6 +22,7 @@ cache: before_install: - npm config set spin false - npm install -g greenkeeper-lockfile@1 + - gem install bundler:2.3.7 install: - npm ci @@ -49,6 +51,7 @@ jobs: env: TRY_CONFIG=ember-data-beta - node_js: 10 - stage: ":ship: it to quay.io" + dist: focal before_install: skip install: skip before_script: skip diff --git a/Dockerfile.tcie b/Dockerfile.tcie new file mode 100644 index 0000000000..ea0b9846b1 --- /dev/null +++ b/Dockerfile.tcie @@ -0,0 +1,70 @@ +FROM ruby:3.2.2 as build + +LABEL maintainer Travis CI GmbH + +ENV NPM_CONFIG_LOGLEVEL info +ENV NODE_VERSION 10.7.0 +ENV YARN_VERSION 0.22.0 + +RUN ( \ + groupadd --gid 1000 node \ + && useradd --uid 1000 --gid node --shell /bin/bash --create-home node; \ + curl --version;) +RUN ( \ + curl -SLOv "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.xz" \ + && tar -xJf "node-v$NODE_VERSION-linux-x64.tar.xz" -C /usr/local --strip-components=1 \ + && ln -s /usr/local/bin/node /usr/local/bin/nodejs; ) +RUN ( \ + curl -fSL -o yarn.js "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-legacy-$YARN_VERSION.js" \ + && mv yarn.js /usr/local/bin/yarn \ + && chmod +x /usr/local/bin/yarn; \ + mkdir -p /app; \ +) +COPY package.json /app +COPY package-lock.json /app +COPY . /app + +WORKDIR /app + +RUN (\ + npm install --silent -g ember-cli; \ + npm ci; \ + ember build --environment=production; \ + ls -l /app; \ + ls -l /app/dist; \ +) + +FROM ruby:3.2.2-slim + +LABEL maintainer Travis CI GmbH + +RUN ( \ + gem install bundler:2.3.7; \ + bundle config --global frozen 1; \ + mkdir -p /app/dist; \ +) + +WORKDIR /app + +COPY --from=build /app/dist/ /app/dist/ +COPY --from=build /app/maintenance/ /app/maintenance/ +COPY Gemfile* /app/ +COPY waiter /app/waiter +COPY public /app/public +COPY ssl /app/ssl + +RUN (\ + + cp -a public/* dist/; \ + rm -rf public; \ + apt-get update ; \ + apt-get upgrade -y ; \ + apt-get install -y --no-install-recommends git make gcc g++ libpq-dev libjemalloc-dev xz-utils; \ + rm -rf /var/lib/apt/lists/*; \ + bundle install --without assets development test; \ + sed -i "/stripe.com\/v3/d" /app/dist/index.html; \ + apt-get remove -y gcc g++ make git perl xz-utils && apt-get -y autoremove; \ +) + + +CMD ["bundle", "exec", "puma", "-I", "lib", "-p", "${PORT:-4000}", "-t", "${PUMA_MIN_THREADS:-8}:${PUMA_MAX_THREADS:-12}", "-w", "${PUMA_WORKERS:-2}", "--preload", "waiter/config.ru" ] diff --git a/Gemfile b/Gemfile index 721522ec7e..be459e0147 100644 --- a/Gemfile +++ b/Gemfile @@ -12,6 +12,7 @@ gem 'rack-ssl', '~> 1.4' gem 'sanitize' gem 'sinatra' gem 'travis-web', path: 'waiter' +gem 'nokogiri', '~> 1.13.6' group :development, :test do gem 'rake' diff --git a/Gemfile.lock b/Gemfile.lock index f6ef837989..6b79192600 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -8,80 +8,84 @@ GEM specs: ansi (1.5.0) ast (2.4.2) + base64 (0.2.0) crass (1.0.6) - diff-lcs (1.5.0) + diff-lcs (1.5.1) docile (1.4.0) foreman (0.87.2) hashr (2.0.1) - json (2.6.3) + json (2.7.1) language_server-protocol (3.17.0.3) + mini_portile2 (2.8.5) multi_json (1.15.0) mustermann (3.0.0) ruby2_keywords (~> 0.0.1) - nio4r (2.5.9) - nokogiri (1.15.2-x86_64-linux) + nio4r (2.7.1) + nokogiri (1.13.10) + mini_portile2 (~> 2.8.0) racc (~> 1.4) - parallel (1.23.0) - parser (3.2.2.3) + parallel (1.24.0) + parser (3.3.0.5) ast (~> 2.4.1) racc power_assert (2.0.3) - puma (6.3.0) + puma (6.4.2) nio4r (~> 2.0) - racc (1.7.1) - rack (2.2.7) + racc (1.7.3) + rack (2.2.9) rack-mobile-detect (0.4.0) rack - rack-protection (3.0.6) - rack + rack-protection (3.2.0) + base64 (>= 0.1.0) + rack (~> 2.2, >= 2.2.4) rack-ssl (1.4.1) rack rack-test (2.1.0) rack (>= 1.3) rainbow (3.1.1) - rake (13.0.6) - regexp_parser (2.8.1) - rexml (3.2.5) - rspec (3.12.0) - rspec-core (~> 3.12.0) - rspec-expectations (~> 3.12.0) - rspec-mocks (~> 3.12.0) - rspec-core (3.12.2) - rspec-support (~> 3.12.0) - rspec-expectations (3.12.3) + rake (13.1.0) + regexp_parser (2.9.0) + rexml (3.2.6) + rspec (3.13.0) + rspec-core (~> 3.13.0) + rspec-expectations (~> 3.13.0) + rspec-mocks (~> 3.13.0) + rspec-core (3.13.0) + rspec-support (~> 3.13.0) + rspec-expectations (3.13.0) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.12.0) - rspec-mocks (3.12.5) + rspec-support (~> 3.13.0) + rspec-mocks (3.13.0) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.12.0) - rspec-support (3.12.1) - rubocop (1.54.0) + rspec-support (~> 3.13.0) + rspec-support (3.13.1) + rubocop (1.62.1) json (~> 2.3) language_server-protocol (>= 3.17.0) parallel (~> 1.10) - parser (>= 3.2.2.3) + parser (>= 3.3.0.2) rainbow (>= 2.2.2, < 4.0) regexp_parser (>= 1.8, < 3.0) rexml (>= 3.2.5, < 4.0) - rubocop-ast (>= 1.28.0, < 2.0) + rubocop-ast (>= 1.31.1, < 2.0) ruby-progressbar (~> 1.7) unicode-display_width (>= 2.4.0, < 3.0) - rubocop-ast (1.29.0) - parser (>= 3.2.1.0) - rubocop-capybara (2.18.0) + rubocop-ast (1.31.2) + parser (>= 3.3.0.4) + rubocop-capybara (2.20.0) + rubocop (~> 1.41) + rubocop-factory_bot (2.25.1) rubocop (~> 1.41) - rubocop-factory_bot (2.23.1) - rubocop (~> 1.33) - rubocop-performance (1.18.0) - rubocop (>= 1.7.0, < 2.0) - rubocop-ast (>= 0.4.0) - rubocop-rspec (2.22.0) - rubocop (~> 1.33) + rubocop-performance (1.20.2) + rubocop (>= 1.48.1, < 2.0) + rubocop-ast (>= 1.30.0, < 2.0) + rubocop-rspec (2.27.1) + rubocop (~> 1.40) rubocop-capybara (~> 2.17) rubocop-factory_bot (~> 2.22) ruby-progressbar (1.13.0) ruby2_keywords (0.0.5) - sanitize (6.0.1) + sanitize (6.1.0) crass (~> 1.0.2) nokogiri (>= 1.12.0) simplecov (0.22.0) @@ -94,30 +98,32 @@ GEM terminal-table simplecov-html (0.12.3) simplecov_json_formatter (0.1.4) - sinatra (3.0.6) + sinatra (3.2.0) mustermann (~> 3.0) rack (~> 2.2, >= 2.2.4) - rack-protection (= 3.0.6) + rack-protection (= 3.2.0) tilt (~> 2.0) - sinatra-contrib (3.0.6) - multi_json + sinatra-contrib (3.2.0) + multi_json (>= 0.0.2) mustermann (~> 3.0) - rack-protection (= 3.0.6) - sinatra (= 3.0.6) + rack-protection (= 3.2.0) + sinatra (= 3.2.0) tilt (~> 2.0) terminal-table (3.0.2) unicode-display_width (>= 1.1.1, < 3) - test-unit (3.6.1) + test-unit (3.6.2) power_assert - tilt (2.2.0) - unicode-display_width (2.4.2) + tilt (2.3.0) + unicode-display_width (2.5.0) PLATFORMS + aarch64-linux x86_64-linux DEPENDENCIES foreman hashr + nokogiri (~> 1.13.6) puma (~> 6) rack-mobile-detect rack-protection (~> 3.0) @@ -140,4 +146,4 @@ RUBY VERSION ruby 3.2.2p53 BUNDLED WITH - 2.4.14 + 2.4.10 diff --git a/Makefile b/Makefile index 3e8333d32f..8d59dc9418 100644 --- a/Makefile +++ b/Makefile @@ -27,7 +27,7 @@ DOCKER ?= docker .PHONY: docker-build docker-build: - $(DOCKER) build -t $(DOCKER_DEST) . + $(DOCKER) build --pull --no-cache -t $(DOCKER_DEST) . -f Dockerfile.tcie .PHONY: docker-login docker-login: diff --git a/app/components/billing/authorization.js b/app/components/billing/authorization.js index c3a1b6b456..9afec8bb8b 100644 --- a/app/components/billing/authorization.js +++ b/app/components/billing/authorization.js @@ -34,10 +34,6 @@ export default Component.extend({ return this.isSubscribed && this.hasSubscriptionPermissions && !this.freeV2Plan && !this.isTrial && !this.cancellationRequested; }), - hasSubscriptionPermissions: computed('account.hasSubscriptionPermissions', 'account.permissions', function () { - return this.account.hasSubscriptionPermissions && (!this.account.isOrganization || this.account.permissions.plan_create); - }), - hasSubscriptionPermissions: computed('account.hasSubscriptionPermissions', 'account.permissions', function () { return this.account.hasSubscriptionPermissions && (!this.account.isOrganization || this.account.permissions.plan_create); }), diff --git a/app/components/owner/repositories.js b/app/components/owner/repositories.js index d23bcc300d..543b8837e8 100644 --- a/app/components/owner/repositories.js +++ b/app/components/owner/repositories.js @@ -36,7 +36,6 @@ export default Component.extend({ isOwnerVcsTypeEmpty: empty('owner.vcsType'), isNotGithubRepository: not('isGithubRepository'), hasGitHubAppsInstallation: notEmpty('owner.installation'), - isEnterprise: reads('features.enterpriseVersion'), isNotEnterprise: not('isEnterprise'), isPro: reads('features.proVersion'), @@ -102,13 +101,30 @@ export default Component.extend({ let isOrganization = this.get('owner.isOrganization'); let ownerGithubId = this.get('owner.githubId'); let installationGithubId = this.get('owner.installation.githubId'); + let sourceEndpoint = `${config.sourceEndpoint}`; + + if (sourceEndpoint === 'undefined') { + sourceEndpoint = 'https://github.com'; + } + + if (!installationGithubId) { + let ownerId = this.get('owner.id'); + let ownerType = this.get('owner.type'); + const installations = this.store.peekAll('installation').filterBy('owner.id', ownerId) || null; + if (installations) { + const installation = installations.findBy('owner.type', ownerType) || null; + if (installation) { + installationGithubId = installation.githubId; + } + } + } - if (appName && appName.length) { + if (!installationGithubId && appName && appName.length) { return `${config.githubAppsEndpoint}/${appName}/installations/new/permissions?suggested_target_id=${ownerGithubId}`; } else if (isOrganization) { - return `https://github.com/organizations/${login}/settings/installations/${installationGithubId}`; + return `${sourceEndpoint}/organizations/${login}/settings/installations/${installationGithubId}`; } else { - return `https://github.com/settings/installations/${installationGithubId}`; + return `${sourceEndpoint}/settings/installations/${installationGithubId}`; } } ), diff --git a/app/instance-initializers/enterprise-environment.js b/app/instance-initializers/enterprise-environment.js index 9d8c72351f..b3e60b2d97 100644 --- a/app/instance-initializers/enterprise-environment.js +++ b/app/instance-initializers/enterprise-environment.js @@ -9,7 +9,6 @@ export function initialize(appInstance) { featureFlags['landing-page-cta'] = false; featureFlags['show-running-jobs-in-sidebar'] = true; featureFlags['debug-builds'] = false; - featureFlags['log-scanner'] = false; featureFlags['broadcasts'] = false; featureFlags['beta-features'] = false; } diff --git a/app/models/user.js b/app/models/user.js index fb80baff66..fcabe90dd9 100644 --- a/app/models/user.js +++ b/app/models/user.js @@ -10,6 +10,7 @@ import { or, reads } from '@ember/object/computed'; export default Owner.extend({ api: service(), accounts: service(), + features: service(), permissionsService: service('permissions'), wizardStateService: service('wizardState'), @@ -100,11 +101,17 @@ export default Owner.extend({ if (this.isSyncing) { this.schedulePoll(); } else { + const enterprise = !!this.get('features.enterpriseVersion'); this.permissionsService.fetchPermissions.perform(); - this.wizardStateService.fetch.perform(); + if (!enterprise) { + this.wizardStateService.fetch.perform(); + } this.accounts.fetchOrganizations.perform(); - this.accounts.fetchSubscriptions.perform(); - this.accounts.fetchV2Subscriptions.perform(); + + if (!enterprise) { + this.accounts.fetchSubscriptions.perform(); + this.accounts.fetchV2Subscriptions.perform(); + } this.applyReposFilter(); Travis.trigger('user:synced', this); diff --git a/app/routes/first-sync.js b/app/routes/first-sync.js index 913c492c99..98019f24ca 100644 --- a/app/routes/first-sync.js +++ b/app/routes/first-sync.js @@ -8,6 +8,7 @@ export default SimpleLayoutRoute.extend({ storage: service(), accounts: service(), + features: service(), user: alias('accounts.user'), activate() { @@ -22,6 +23,8 @@ export default SimpleLayoutRoute.extend({ }, getTransition() { + if (this.get('features.enterpriseVersion')) return 'account'; + if (this.user.vcsType == 'AssemblaUser') return 'account'; if (this.user.collaborator || this.user.hasV2Subscription || @@ -36,6 +39,10 @@ export default SimpleLayoutRoute.extend({ isSyncingDidChange() { const controller = this.controllerFor('firstSync'); if (!controller.isSyncing) { + if (this.get('features.enterpriseVersion')) { + this.transitionTo(this.getTransition()); + return; + } this.accounts.fetchSubscriptions.perform() .then(() => this.accounts.fetchV2Subscriptions.perform()) .then(() => { diff --git a/app/templates/components/env-var.hbs b/app/templates/components/env-var.hbs index 49147f2da6..eb545bef5e 100644 --- a/app/templates/components/env-var.hbs +++ b/app/templates/components/env-var.hbs @@ -1,4 +1,5 @@ -
+ +
{{this.envVar.name}}
diff --git a/app/templates/components/requests-item.hbs b/app/templates/components/requests-item.hbs index b93a22fe4b..22e2f43cbe 100644 --- a/app/templates/components/requests-item.hbs +++ b/app/templates/components/requests-item.hbs @@ -34,7 +34,10 @@
- {{{format-message this.request.commit.message short="true" repo=this.build.repo}}} + + + {{{format-message this.request.commit.message short="true" repo=this.build.repo}}} +
{{#if this.build}} diff --git a/app/templates/settings.hbs b/app/templates/settings.hbs index 1705e9b5c5..e0370ac0c8 100644 --- a/app/templates/settings.hbs +++ b/app/templates/settings.hbs @@ -80,7 +80,7 @@ - {{#if this.repo.private}} + {{#if (or this.features.enterpriseVersion this.repo.private)}}
  • + + + + + Travis CI - Maintenance + + + + + + +
    +
    +
    +

    +

    +
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    +

    TravisCI is currently under Maintenance

    +
    +
    + + diff --git a/tests/acceptance/builds/prioritize-test.js b/tests/acceptance/builds/prioritize-test.js index ef763a2b87..23cf40e262 100644 --- a/tests/acceptance/builds/prioritize-test.js +++ b/tests/acceptance/builds/prioritize-test.js @@ -1,4 +1,4 @@ -import { module, test, skip } from 'qunit'; +import { module, skip, test} from 'qunit'; import { visit, click, triggerKeyEvent } from '@ember/test-helpers'; import { setupApplicationTest } from 'travis/tests/helpers/setup-application-test'; import signInUser from 'travis/tests/helpers/sign-in-user'; diff --git a/tests/acceptance/profile/basic-layout-test.js b/tests/acceptance/profile/basic-layout-test.js index 52cf94643b..2d3700ffdf 100644 --- a/tests/acceptance/profile/basic-layout-test.js +++ b/tests/acceptance/profile/basic-layout-test.js @@ -1,4 +1,4 @@ -import { module, test } from 'qunit'; +import { module, test, skip } from 'qunit'; import { setupApplicationTest } from 'travis/tests/helpers/setup-application-test'; import profilePage from 'travis/tests/pages/profile'; import signInUser from 'travis/tests/helpers/sign-in-user'; @@ -291,7 +291,7 @@ module('Acceptance | profile/basic layout', function (hooks) { await profilePage.visit(); }); - test('view profiles for organizations that do not and do have GitHub Apps installations', async function (assert) { + skip('view profiles for organizations that do not and do have GitHub Apps installations', async function (assert) { this.server.create('repository', { name: 'extra-repository', owner: { @@ -342,7 +342,7 @@ module('Acceptance | profile/basic layout', function (hooks) { assert.notOk(profilePage.administerableRepositories[2].isActive, 'expected inactive repository to appear inactive'); }); - test('view profile when GitHub Apps is present and no legacy repositories exist', async function (assert) { + skip('view profile when GitHub Apps is present and no legacy repositories exist', async function (assert) { enableFeature('github-apps'); await profilePage.visitOrganization({ name: 'org0' }); diff --git a/waiter/config.ru b/waiter/config.ru index 78c8371a21..5a222385fa 100644 --- a/waiter/config.ru +++ b/waiter/config.ru @@ -71,6 +71,21 @@ if ENV['TRAVIS_ENTERPRISE'] ENV['CACHES_ENABLED'] = 'true' unless ENV.key?('CACHES_ENABLED') end +if ENV['TRAVIS_MAINTENANCE'] +use Rack::Static, + :root => File.expand_path('../../maintenance', __FILE__) + +run lambda { |env| + [ + 200, + { + 'Content-Type' => 'text/html', + 'Cache-Control' => 'public, max-age=86400' + }, + File.open(File.expand_path('../../maintenance/index.html', __FILE__), File::RDONLY) + ] +} +else run Travis::Web::App.build( userlike: ENV['USERLIKE'], environment: ENV['RACK_ENV'] || 'development', @@ -102,3 +117,4 @@ run Travis::Web::App.build( default_provider: ENV['DEFAULT_PROVIDER'], log_limit: ENV['LOG_LIMIT'] ) +end diff --git a/waiter/lib/travis/web/api_redirect.rb b/waiter/lib/travis/web/api_redirect.rb index bc3a052a4f..46cda48737 100644 --- a/waiter/lib/travis/web/api_redirect.rb +++ b/waiter/lib/travis/web/api_redirect.rb @@ -9,7 +9,6 @@ class Travis::Web::ApiRedirect < Sinatra::Base get %r{/([^/]+)/([^/]+)\.(png|svg)} do pass if %r{/images/}.match?(request.path_info) - if settings.redirect_png redirect!(request.fullpath.gsub(/\.png$/, '.svg')) else diff --git a/waiter/lib/travis/web/app.rb b/waiter/lib/travis/web/app.rb index 9aca7bbdcf..e48b0e9d96 100644 --- a/waiter/lib/travis/web/app.rb +++ b/waiter/lib/travis/web/app.rb @@ -207,9 +207,10 @@ def set_config(string, _opts = {}) # rubocop:disable Metrics/CyclomaticComplexit if options[:github_apps_app_name] config['githubApps'] ||= {} config['githubApps']['appName'] = options[:github_apps_app_name] - end + config['githubApps']['migrationRepositoryCountLimit'] = 50 + end - config['publicMode'] = !options[:public_mode].nil? && (options[:public_mode] == 'false' || options[:public_mode] == false) + config['publicMode'] = !options[:public_mode].nil? && (options[:public_mode] == 'true' || options[:public_mode] == true) if config['enterprise'] config['pagesEndpoint'] = false @@ -261,7 +262,20 @@ def set_config(string, _opts = {}) # rubocop:disable Metrics/CyclomaticComplexit config['providers'][provider]['isDefault'] = true end - regexp = %r{