Compare commits

...

166 Commits

Author SHA1 Message Date
bucky 1822004460 use the hostname of the artifacts repository
Gitea Bucky/url-shortener/pipeline/head There was a failure building this commit
2023-12-19 07:58:59 -08:00
bucky b9345f9cb5 removed extra line
Gitea Bucky/url-shortener/pipeline/head This commit looks good
2023-12-18 20:19:55 -08:00
bucky 166c68570d v1.0.1
Gitea Bucky/url-shortener/pipeline/head There was a failure building this commit
2023-12-18 20:16:52 -08:00
bucky 28fc8b3b86 updated Gemfile with falcon instead of puma
Gitea Bucky/url-shortener/pipeline/head There was a failure building this commit
2023-12-18 20:15:33 -08:00
bucky 2c7a18c374 create the directory before syncingit
Gitea Bucky/url-shortener/pipeline/head This commit looks good
2023-12-18 18:38:18 -08:00
bucky 0a3f6c5fab try with ssh-agent
Gitea Bucky/url-shortener/pipeline/head There was a failure building this commit
2023-12-18 18:11:28 -08:00
bucky ca29051dc2 try to rsync with the user/key pair
Gitea Bucky/url-shortener/pipeline/head There was a failure building this commit
2023-12-18 17:50:42 -08:00
bucky 0b51b52b84 echo the file to see what's in there/how to handle it
Gitea Bucky/url-shortener/pipeline/head This commit looks good
2023-12-18 17:45:55 -08:00
bucky 4659942800 use user/key pair
Gitea Bucky/url-shortener/pipeline/head This commit looks good
2023-12-18 17:33:09 -08:00
bucky 6d0f594bba set file in the stage it is used in
Gitea Bucky/url-shortener/pipeline/head There was a failure building this commit
2023-12-18 17:15:30 -08:00
bucky 4ca73cc3ca use artifacts key
Gitea Bucky/url-shortener/pipeline/head There was a failure building this commit
2023-12-18 16:59:52 -08:00
bucky 1f96facbf2 use the ZIP FILE variable not ZIP_FILE text
Gitea Bucky/url-shortener/pipeline/head There was a failure building this commit
2023-12-18 15:57:02 -08:00
bucky e362cef9ba added SHA256 and sync both the sig and the zip
Gitea Bucky/url-shortener/pipeline/head There was a failure building this commit
2023-12-18 15:51:41 -08:00
bucky 25d94bbfc2 attempt to use rsync to sync data to artifact repo jail
Gitea Bucky/url-shortener/pipeline/head There was a failure building this commit
2023-12-18 13:09:52 -08:00
bucky 40e3703650 get the actual version, not the line
Gitea Bucky/url-shortener/pipeline/head This commit looks good
2023-10-24 18:11:12 -07:00
bucky 21eeb9db72 use version instead of date
Gitea Bucky/url-shortener/pipeline/head There was a failure building this commit
2023-10-24 18:01:15 -07:00
bucky 2cbe5f85b0 moved bundle-audit inside test group, added version file 2023-10-24 17:53:56 -07:00
bucky b62d45d0d8 Merge pull request 'prod-artifact-when-good' (#34) from prod-artifact-when-good into master
Gitea Bucky/url-shortener/pipeline/head This commit looks good
Reviewed-on: #34
2023-10-23 15:54:27 -07:00
bucky 0dc792b0bf added try catch wrappers around other parts. if they fail, don't build
Gitea Bucky/url-shortener/pipeline/head This commit looks good
the deliverable
2023-10-23 15:48:42 -07:00
bucky 5f4209dbe8 testing skipping building the artifact at the end (and cleanup of it)
Gitea Bucky/url-shortener/pipeline/head This commit looks good
2023-10-23 15:10:16 -07:00
bucky fbba67a9bd install, not clean, since it changed the bundle location
Gitea Bucky/url-shortener/pipeline/head This commit looks good
2023-10-23 15:05:20 -07:00
bucky 5cd296cb70 when is outside the steps
Gitea Bucky/url-shortener/pipeline/head There was a failure building this commit
2023-10-23 15:03:45 -07:00
bucky 7c0f6eb603 limit building deployment artifact
Gitea Bucky/url-shortener/pipeline/head There was a failure building this commit
+ added buildArtifact variable and set it to true
+ in auditing stage, if there's an error, set buildArtifact to false
+ in build artifact stage, if buildArtifact is true, build  it
2023-10-23 14:58:02 -07:00
bucky de3dcc48ab removed the when, and removed unnecessary rm command
Gitea Bucky/url-shortener/pipeline/head There was a failure building this commit
2023-10-23 12:31:29 -07:00
bucky 958091e000 see if we can access the buildResult status to use it 2023-10-23 11:32:02 -07:00
bucky 35583e404e move the local path in the build prod artifact stage to make the tests
quicker
2023-10-23 07:43:30 -07:00
bucky 0e9342fab6 only build the production environment when the previous steps all executed successfully 2023-10-23 07:41:52 -07:00
bucky ca4182d798 Merge pull request 'added bundle config to only use prod gems and bundle clean to remove unnecessary gems from the current poject' (#33) from build-deployment-artifact into master
Reviewed-on: #33

closes bucky/url-shortener#32
2023-10-23 07:31:15 -07:00
bucky 7d04c46728 added bundle config to only use prod gems and bundle clean to remove unnecessary gems from the current poject 2023-10-23 07:18:31 -07:00
bucky 4490ed3e7c output something from the bundler audit to see in the reports 2023-10-22 16:22:18 -07:00
bucky 30c1192e27 Merge pull request 'audit' (#31) from audit into master
Reviewed-on: #31

closes bucky/url-shortener#30
2023-10-22 16:06:15 -07:00
bucky 6e30705810 rubocop autofixed quotes 2023-10-22 15:57:57 -07:00
bucky d7c9105995 added audit checks, this should help keep things secure 2023-10-22 15:51:16 -07:00
bucky a732eb2a61 added bundle-audit and ruby_audit gems 2023-10-22 15:48:40 -07:00
bucky c29d53a33b Merge pull request 'rubocop' (#29) from rubocop into master
Reviewed-on: #29

closes bucky/url-shortener#28
2023-10-22 15:11:23 -07:00
bucky 3fd8e8c630 wrap the string in single quotes 2023-10-22 15:00:59 -07:00
bucky 950c358ae5 another try 2023-10-22 14:55:06 -07:00
bucky f81199e31b maybe this will clean up a few things 2023-10-22 14:15:27 -07:00
bucky bf1fefd1bc still worknig on env file, and adding logic to not build if the tests fail 2023-10-22 14:05:51 -07:00
bucky c51a6782d9 another shot at cleaning up the .env.rb file 2023-10-22 13:50:58 -07:00
bucky 795447e029 attempting to clean up the .env.rb file 2023-10-22 13:43:12 -07:00
bucky 7caf25c4d0 don't kill it if linting breaks, mark it as unstable 2023-10-22 13:32:39 -07:00
bucky 3fa1de5e4e install bundled gems in /vendor, and use bundle exec to run them 2023-10-22 13:27:07 -07:00
bucky f86da2ed6f forgot to wrap the steps in a steps block 2023-10-22 13:19:30 -07:00
bucky 282a07c5fb added rubocop linting section with output for reports and clean up
rubocop config
2023-10-22 13:16:20 -07:00
bucky bf6ed14b5e custom parts for rubocop to run. don't worry about block length in many
parts. hide extension suggestions
2023-10-22 13:15:09 -07:00
bucky 7d35133e43 require capybara and rspec parts needed for tests to run instead of
including them. rubocop autofixed formatting
2023-10-22 13:14:23 -07:00
bucky c505012b00 rubocop added frozen string literal comment 2023-10-22 13:14:02 -07:00
bucky 4f54124519 rubocop autofixed formatting 2023-10-22 13:13:27 -07:00
bucky 18e8eac2ab rubocop autofixed formatting 2023-10-22 13:12:48 -07:00
bucky 5abf07d0c7 rubocop formatting fixes 2023-10-22 13:07:07 -07:00
bucky 48ffdf560b frozen string literal for rubocop 2023-10-22 13:06:12 -07:00
bucky e0392f2483 added rubocop 2023-10-22 13:05:43 -07:00
bucky 15a5017c86 set up to run with only the freebsd and ruby labeled agent(s) 2023-10-18 13:08:41 -07:00
bucky dd5caa4056 updated README, swapped Falcon for Puma for now, and ignored more files 2023-10-17 21:53:12 -07:00
bucky 360ddbe6d2 include the branch name in the zip, so it can be identified a little easier later 2023-10-17 21:45:14 -07:00
bucky b3b886f0b3 Merge pull request 'simplify-secret' (#27) from simplify-secret into master
Reviewed-on: #27
2023-10-17 21:43:19 -07:00
bucky 93aa007c14 removed secret.rb, it's no longer needed 2023-10-17 21:40:39 -07:00
bucky 4e32f4a60d use the escaped quotes for it to work correctly 2023-10-17 21:39:15 -07:00
bucky 2759880a53 remove env. 2023-10-17 21:37:45 -07:00
bucky 7bc1a852db swap quotes on the db name 2023-10-17 21:36:56 -07:00
bucky 00119f9723 use env.DB_NAME to access the environment variable 2023-10-17 21:32:30 -07:00
bucky ff2a0e867d swap the quotes because single quotes doesn't exec the ruby command 2023-10-17 21:30:53 -07:00
bucky 1fae85ff9d moved the init step into one shell command to load it all, and don't use
the secret.rb file
2023-10-17 21:26:23 -07:00
bucky 10fe82ab6a Merge pull request 'archive-deliverable' (#26) from archive-deliverable into master
Reviewed-on: #26
2023-10-17 18:12:37 -07:00
bucky 9812a92d59 remove ls 2023-10-17 18:09:17 -07:00
bucky e8b12c307a include ruby version 2023-10-17 18:06:36 -07:00
bucky ae00ac8672 forgot the .rb 2023-10-17 18:04:29 -07:00
bucky bf92201721 removed some unnecessary lines, and check what's in the current
directory
2023-10-17 18:02:40 -07:00
bucky 1f2e3d41dd syntax error extra - in there 2023-10-17 18:00:46 -07:00
bucky f31b6da49c include the .env file and remove the scret.rb file 2023-10-17 17:58:40 -07:00
bucky f32d153b69 simplified things? 2023-10-17 17:46:24 -07:00
bucky 15d9ade2cf remove EXPORT 2023-10-17 17:42:17 -07:00
bucky 4587c35806 just set it in the script 2023-10-17 17:40:23 -07:00
bucky 340614dadc echo outside catch error 2023-10-17 17:37:35 -07:00
bucky 8a0fef63b2 another try 2023-10-17 17:35:37 -07:00
bucky 8691d19e8d dump the zip file, let's see how it's working? 2023-10-17 17:32:50 -07:00
bucky 35d196bdc2 another shot accessing the new env var 2023-10-17 17:28:41 -07:00
bucky e2c3cb7035 access the ZIP_FILE variable properly? 2023-10-17 17:25:02 -07:00
bucky a69b3e4226 missed quote 2023-10-17 17:22:00 -07:00
bucky 36285b060b better try to set the environment 2023-10-17 17:19:31 -07:00
bucky a0a9e84b91 another try 2023-10-17 17:14:33 -07:00
bucky 01d9f9a21c another shot at setting the zip file name 2023-10-17 17:12:16 -07:00
bucky 621a777a46 update env vars
+ removed the app session secret. it's used where it is set
+ added zip file to make it easier to name the zip and reuse the name
2023-10-17 17:05:15 -07:00
bucky 6fbecd78a4 clean out unnecessary files a little easier 2023-10-17 10:39:17 -07:00
bucky 873b86a809 Merge pull request 'remove db files as well' (#25) from archive-deliverable into master
Reviewed-on: #25
2023-10-16 17:41:38 -07:00
bucky 47393a5ead remove db files as well 2023-10-16 17:30:11 -07:00
bucky 69c56ae31a Merge pull request 'archive-deliverable' (#24) from archive-deliverable into master
Reviewed-on: #24
2023-10-16 17:28:43 -07:00
bucky b2cdf60a32 Revert "simplify it a little"
This reverts commit 91f45965a0.
2023-10-16 17:23:50 -07:00
bucky 91f45965a0 simplify it a little 2023-10-16 17:18:06 -07:00
bucky 3097cb69aa clean the workspace when done 2023-10-16 17:04:23 -07:00
bucky eed17d61a3 use tmp as a staging place for building the tgz file 2023-10-16 16:35:56 -07:00
bucky 9e5a4069a4 wrapping all the commands in one script, hope it works? 2023-10-16 15:44:50 -07:00
bucky f8c20541d5 removed shopt, added that in jenkins user's .profile 2023-10-16 15:09:44 -07:00
bucky ee07312b86 another shot at getting local shell 2023-10-16 13:48:31 -07:00
bucky e4eabf8aa6 looking to see what shell is used 2023-10-16 12:06:11 -07:00
bucky 3ec0f0ff7b mkdir -p and wrapped the steps in a catch so the clean up happens 2023-10-16 12:01:10 -07:00
bucky 27b32fc8f4 another shot 2023-10-16 11:57:20 -07:00
bucky ceab408ec0 build deliverable, store it, and clean up afterwards 2023-10-16 10:54:52 -07:00
bucky b56b618a8c added stages to build a deliverable and then clean it up when done 2023-10-16 10:50:22 -07:00
bucky 5631ae386f include rackup 2023-10-13 21:28:47 -07:00
bucky c31c556df5 removed falcon and it's dependencies, because it wasn't working right.
use puma for now
2023-10-13 21:27:25 -07:00
bucky 5fae0c4fa9 Merge pull request 'rspec-coverage' (#22) from rspec-coverage into master
Reviewed-on: #22
2023-10-12 23:49:48 -07:00
bucky 144731062b added URL validation to webpage part 2023-10-12 23:42:52 -07:00
bucky 72f3e03edd added tests for invalid URL entries
+ URL that returns a 404
+ URL where the domain does not resolve with DNS
+ URL that is not properly formatted
2023-10-12 23:42:04 -07:00
bucky b08693e866 remove the puts, don't print out the test result 2023-10-12 23:41:38 -07:00
bucky ae2360a480 include the proper status code 2023-10-12 23:31:15 -07:00
bucky 213265a5d0 added test for submitting with the wrong content type header 2023-10-12 23:30:47 -07:00
bucky dfb6b23e70 run simplecov for rspec tests 2023-10-12 23:12:14 -07:00
bucky c81a7a6160 added rescue for urls that don't resolve 2023-10-12 19:03:03 -07:00
bucky bbb710a5e1 added test for bad TLD, better named 404 url test 2023-10-12 19:02:38 -07:00
bucky 7eaa8eacf8 added rescue for OpenURI HTTPErrors 2023-10-12 18:26:13 -07:00
bucky d78e361c29 added test for validating a url is accessible 2023-10-12 18:25:38 -07:00
bucky 1ae6c02472 rescue BadURIError for invalid URL format 2023-10-12 18:20:56 -07:00
bucky 11206854ad added test for an invalid url 2023-10-12 18:20:35 -07:00
bucky 33089e6fbd build HTML output with cucumber and rspec files in root dir 2023-10-12 16:25:22 -07:00
bucky 5cec47efcc Merge pull request 'create-json' (#21) from create-json into master
Reviewed-on: #21
2023-10-12 14:36:38 -07:00
bucky cabb4daded split up the nil? and empty? cases, because they are different
situations
2023-10-12 14:27:31 -07:00
bucky 1e61a76ded added 2 more tests for empty and missing url data posting to links 2023-10-12 14:27:02 -07:00
bucky ac3e9f14cd added links route for API interactions 2023-10-12 11:42:43 -07:00
bucky 5ee9351362 added db initialization to make sure the db exists and is up to date
before tests
2023-10-12 11:42:14 -07:00
bucky 2964e06639 added before and after actions
+ before initializes the db
+ after cleans the db
2023-10-12 11:40:15 -07:00
bucky d1a0fc0222 change request to use the /links path, to fit more into a RESTful API
format

+ also renamed the test to better describe the behavior
2023-10-12 11:32:00 -07:00
bucky 4a82174526 implemented API create endpoint
+ added plugins to read json and access the header to parse the request
  for an API request
+ fixed logic where url param is nil
+ refactored the new code to a variable to be reused easier
+ if CONTENT_TYPE header is application/json, reply with json
- there could be more refactoring (maybe separating it to a different
  endpoint) to handle other scenarios, we'll work on that later
2023-10-11 19:21:43 -07:00
bucky 3ae20255f6 DRY it out a little 2023-10-11 19:21:21 -07:00
bucky f69c53bf29 removed unnecessary variable 2023-10-11 19:20:07 -07:00
bucky 7d6c098047 added more to the spec test for creating a new link 2023-10-11 19:18:47 -07:00
bucky 3421e18f21 added more logic for running tests without killing the whole pipeline, and outputting rspec results 2023-10-11 12:05:33 -07:00
bucky 0dec27a01c added rspec step in tests stage, adjusted should clause 2023-10-11 11:04:08 -07:00
bucky c45cf6ab51 started building out rspec specs for API functionality 2023-10-11 11:01:46 -07:00
bucky e50667b392 split homepage out into homepage and submit feature sets 2023-10-10 17:29:23 -07:00
bucky d4db64f404 Merge pull request 'cucumber-jenkins' (#20) from cucumber-jenkins into master
Reviewed-on: #20
2023-10-10 17:22:55 -07:00
bucky 05858078d1 added unstable scenario 2023-10-10 17:20:25 -07:00
bucky f75f0378bf separate out success and failure tasks 2023-10-10 17:16:24 -07:00
bucky c3d2fb32e2 added icon for message 2023-10-10 17:11:05 -07:00
bucky 1fe30fc7e7 removed jenkins cucumber section, use the html formatter instead
also added more info to the success message
2023-10-10 17:05:33 -07:00
bucky 43cc151138 moved stuff around a little more 2023-10-10 14:50:01 -07:00
bucky 1fee4f276d maybe put both files in the same report 2023-10-10 14:47:09 -07:00
bucky 0b17f36fde added more test results, just exploring 2023-10-10 14:43:11 -07:00
bucky aca92fdae1 cleaned up message a bit for success 2023-10-10 14:32:54 -07:00
bucky c7bf62062a wrap it 2023-10-10 14:28:41 -07:00
bucky b853ca6fe4 trying to make the message cleaner, and print the env to take a look at other options 2023-10-10 14:25:59 -07:00
bucky d5919fc82a got it working with vars, now try the URLs 2023-10-10 14:23:44 -07:00
bucky e2395989f4 try normal quotes 2023-10-10 14:22:30 -07:00
bucky e93868a483 try DB_NAME since the others are failing 2023-10-10 14:19:59 -07:00
bucky 7f6fc24872 maybe this one will work 2023-10-10 14:17:48 -07:00
bucky 776ec0d30d trying different env vars 2023-10-10 14:10:50 -07:00
bucky 6861740d00 bots can't be easily used with incoming webhooks, but let's try some URLs 2023-10-10 14:05:18 -07:00
bucky 77e72d18e1 use the bot's endpoint 2023-10-10 13:50:48 -07:00
bucky 1792d94082 extra , syntax error in jenkins file 2023-10-10 13:30:40 -07:00
bucky 16d17bcadb added icon 2023-10-10 13:27:40 -07:00
bucky f5d1361d59 swapped text/message 2023-10-10 13:10:19 -07:00
bucky c4932dd6cc message to mattermost example 2023-10-10 13:02:31 -07:00
bucky 031a30ed5f send slack message to mattermost for cucumber results 2023-10-10 10:52:14 -07:00
bucky cc1fe1c3b7 Merge pull request 'cucumber-jenkins' (#19) from cucumber-jenkins into master
Reviewed-on: #19
2023-10-10 09:44:14 -07:00
bucky 72e1cee9d5 split features into 2 separate feature files 2023-10-09 20:19:34 -07:00
bucky a90ff753b1 use cucumber plugin 2023-10-09 18:52:48 -07:00
bucky b6010cd431 remove the config in there 2023-10-09 18:37:46 -07:00
bucky 33bfb23405 add a setting for it 2023-10-09 18:35:50 -07:00
bucky ad4f8492d4 add jenkins cucumber functionality 2023-10-09 18:30:50 -07:00
bucky e6cc0959a4 Merge pull request 'invalid-urls' (#18) from invalid-urls into master
Reviewed-on: #18
2023-10-07 21:13:53 -07:00
bucky 5bce31baf2 refactored missing link scenario to make more sense
+ 404 code, stay on the current page, and load the form
+ also simplified the logic for the create action if the link doesn't
  already exist
2023-10-07 21:11:12 -07:00
bucky c7fee27623 update for missing link scenario
+ if the link isn't found, don't redirect it, keep it on the same page
+ it should have a status code of 404
+ it should have the form fields as well

+ added page status check
2023-10-07 21:10:16 -07:00
bucky f8499a79c2 check if the link exists, redirects home if it doesn't 2023-10-07 13:38:10 -07:00
bucky b97ee3f3bb use the correct clause format since staying on site 2023-10-07 13:37:51 -07:00
bucky beb9b0c14a added new scenario 2023-10-07 13:27:00 -07:00
17 changed files with 504 additions and 99 deletions
+2
View File
@@ -3,3 +3,5 @@
*.db
.env.rb
coverage
vendor
.ruby-version
+6
View File
@@ -0,0 +1,6 @@
AllCops:
NewCops: enable
SuggestExtensions: false
Metrics/BlockLength:
AllowedMethods: ['describe', 'context', 'route', 'r.on', 'r.post']
+18 -12
View File
@@ -1,29 +1,35 @@
# frozen_string_literal: true
source "https://rubygems.org"
source 'https://rubygems.org'
gem "falcon", "~> 0.42.3"
gem 'rackup', '~> 2.1'
gem "roda", "~> 3.72"
gem 'falcon', '~> 0.42.3'
gem "sequel", "~> 5.72"
gem 'roda', '~> 3.72'
gem "tilt", "~> 2.2"
gem 'sequel', '~> 5.72'
gem "sqlite3", "~> 1.6"
gem 'tilt', '~> 2.2'
gem "erubi", "~> 1.12"
gem 'sqlite3', '~> 1.6'
gem 'erubi', '~> 1.12'
group :test do
gem 'cucumber', '~> 9.0'
gem "cucumber", "~> 9.0"
gem 'capybara', '~> 3.39'
gem "capybara", "~> 3.39"
gem 'rspec', '~> 3.12'
gem "rspec", "~> 3.12"
gem 'selenium-webdriver', '~> 4.13'
gem "selenium-webdriver", "~> 4.13"
gem 'simplecov'
gem "simplecov"
gem 'rubocop', require: false
gem 'ruby_audit', '~> 2.2'
gem 'bundle-audit', '~> 0.1.0'
end
+49 -8
View File
@@ -3,7 +3,8 @@ GEM
specs:
addressable (2.8.5)
public_suffix (>= 2.0.2, < 6.0)
async (2.6.4)
ast (2.4.2)
async (2.6.5)
console (~> 1.10)
fiber-annotation
io-event (~> 1.1)
@@ -11,23 +12,29 @@ GEM
async-container (0.16.12)
async
async-io
async-http (0.60.2)
async-http (0.61.0)
async (>= 1.25)
async-io (>= 1.28)
async-pool (>= 0.2)
protocol-http (~> 0.24.0)
protocol-http1 (~> 0.15.0)
protocol-http (~> 0.25.0)
protocol-http1 (~> 0.16.0)
protocol-http2 (~> 0.15.0)
traces (>= 0.10.0)
async-http-cache (0.4.3)
async-http (~> 0.56)
async-io (1.36.0)
async-io (1.37.0)
async
async-pool (0.4.0)
async (>= 1.25)
base64 (0.1.1)
bigdecimal (3.1.4)
build-environment (1.13.0)
builder (3.2.4)
bundle-audit (0.1.0)
bundler-audit
bundler-audit (0.9.1)
bundler (>= 1.2.0, < 3)
thor (~> 1.0)
capybara (3.39.2)
addressable
matrix
@@ -83,7 +90,9 @@ GEM
ffi (1.16.2)
fiber-annotation (0.2.0)
fiber-local (1.0.0)
io-event (1.3.2)
io-event (1.3.3)
json (2.6.3)
language_server-protocol (3.17.0.3)
localhost (1.1.10)
mapping (1.1.1)
matrix (0.4.2)
@@ -94,12 +103,16 @@ GEM
mini_portile2 (~> 2.8.2)
racc (~> 1.4)
openssl (3.2.0)
parallel (1.23.0)
parser (3.2.2.4)
ast (~> 2.4.1)
racc
process-metrics (0.2.1)
console (~> 1.8)
samovar (~> 2.1)
protocol-hpack (1.4.2)
protocol-http (0.24.7)
protocol-http1 (0.15.1)
protocol-http (0.25.0)
protocol-http1 (0.16.0)
protocol-http (~> 0.22)
protocol-http2 (0.15.1)
protocol-hpack (~> 1.4)
@@ -112,6 +125,10 @@ GEM
rack (3.0.8)
rack-test (2.1.0)
rack (>= 1.3)
rackup (2.1.0)
rack (>= 3)
webrick (~> 1.8)
rainbow (3.1.1)
regexp_parser (2.8.1)
rexml (3.2.6)
roda (3.72.0)
@@ -129,6 +146,23 @@ GEM
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.12.0)
rspec-support (3.12.1)
rubocop (1.57.1)
base64 (~> 0.1.1)
json (~> 2.3)
language_server-protocol (>= 3.17.0)
parallel (~> 1.10)
parser (>= 3.2.2.4)
rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 1.8, < 3.0)
rexml (>= 3.2.5, < 4.0)
rubocop-ast (>= 1.28.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)
ruby-progressbar (1.13.0)
ruby_audit (2.2.0)
bundler-audit (~> 0.9.0)
rubyzip (2.3.2)
samovar (2.2.0)
console (~> 1.0)
@@ -149,9 +183,12 @@ GEM
mini_portile2 (~> 2.8.0)
sys-uname (1.2.3)
ffi (~> 1.1)
thor (1.3.0)
tilt (2.3.0)
timers (4.3.5)
traces (0.11.1)
unicode-display_width (2.5.0)
webrick (1.8.1)
websocket (1.2.10)
xpath (3.2.0)
nokogiri (~> 1.8)
@@ -160,12 +197,16 @@ PLATFORMS
x86_64-freebsd-13
DEPENDENCIES
bundle-audit (~> 0.1.0)
capybara (~> 3.39)
cucumber (~> 9.0)
erubi (~> 1.12)
falcon (~> 0.42.3)
rackup (~> 2.1)
roda (~> 3.72)
rspec (~> 3.12)
rubocop
ruby_audit (~> 2.2)
selenium-webdriver (~> 4.13)
sequel (~> 5.72)
simplecov
Vendored
+138 -14
View File
@@ -1,20 +1,21 @@
def buildArtifact = true
pipeline {
agent any
agent { label 'ruby && freebsd' }
environment {
APP_SESSION_SECRET = ''
DB_NAME = 'url_shortener.db'
}
stages {
stage('Init') {
steps {
sh 'rbenv local 3.2.2'
script {
env.APP_SESSION_SECRET = sh(script: 'ruby secret.rb', returnStdout: true)
}
sh 'echo "ENV[\\\"APP_SESSION_SECRET\\\"] ||= $(ruby secret.rb)" > .env.rb'
sh 'echo "ENV[\\\"DB_NAME\\\"] ||= \\\"${DB_NAME}\\\"" >> .env.rb'
sh 'cat .env.rb'
sh ''' #!/usr/local/bin/bash
rbenv local 3.2.2
echo "# frozen_string_literal: true\n" > .env.rb
echo "ENV['APP_SESSION_SECRET'] ||= '$(ruby -rsecurerandom -e 'puts SecureRandom.base64(64)')'" >> .env.rb
echo "ENV['DB_NAME'] ||= '${DB_NAME}'" >> .env.rb
cat .env.rb
'''
}
}
stage('Build dependencies') {
@@ -23,23 +24,146 @@ pipeline {
sh 'sequel -m db/migrations sqlite://db/${DB_NAME}'
}
}
stage('Audit Dependencies') {
steps {
catchError(buildResult: 'FAILURE', stageResult: 'FAILURE') {
script {
try {
sh 'bundle exec ruby-audit check'
sh 'bundle exec bundle-audit check >> audit.html'
} catch (e) {
script {
buildArtifact = false
}
}
}
}
}
}
stage('Code Linting') {
steps {
catchError(buildResult: 'UNSTABLE', stageResult: 'FAILURE') {
script {
try {
sh 'bundle exec rubocop --format html --out rubocop.html'
} catch (e) {
script {
buildArtifact = false
}
}
}
}
}
}
stage('Run tests') {
steps {
sh 'cucumber'
catchError(buildResult: 'UNSTABLE', stageResult: 'FAILURE') {
script {
try {
sh 'bundle exec cucumber features --format html --out cucumber.html'
} catch (e) {
script {
buildArtifact = false
}
}
}
}
catchError(buildResult: 'UNSTABLE', stageResult: 'FAILURE') {
script {
try {
sh 'bundle exec rspec spec --format html --out spec.html'
} catch (e) {
script {
buildArtifact = false
}
}
}
}
}
}
stage('Report results') {
steps {
archive(includes: 'pkg/*.gem')
publishHTML (target: [
allowMissing: false,
alwaysLinkToLastBuild: false,
keepAll: true,
reportDir: 'coverage',
reportFiles: 'index.html',
reportDir: '.',
reportFiles: 'rubocop.html, audit.html, cucumber.html, spec.html, coverage/index.html',
reportName: 'Test Results',
reportTitles: 'Test Coverage'])
reportTitles: 'Rubocop Results, Bundler Audit Results, Cucumber Results, RSpec Results, Test Coverage'])
}
}
stage('Build production deliverable') {
when {
expression {
buildArtifact
}
}
steps {
catchError(buildResult: 'FAILURE', stageResult: 'FAILURE') {
sh ''' #!/usr/local/bin/bash
ZIP_FILE="url-shortener_${BRANCH_NAME}_$(cat VERSION | cut -d"'" -f2).tgz"
CUR_DIR=$(pwd)
bundle config set --local without 'test'
bundle config set --local path "vendor"
bundle install
mkdir -p /tmp/url-shortener
cp -R * /tmp/url-shortener
cp .env.rb /tmp/url-shortener/
cp .ruby-version /tmp/url-shortener/
cd /tmp/url-shortener
rm -rf features spec coverage db/*.db .git* Jenkinsfile *.html .rubocop.yml
cd /tmp
tar -czvf $ZIP_FILE url-shortener/
mv /tmp/$ZIP_FILE $CUR_DIR/
'''
}
archiveArtifacts artifacts: '*.tgz'
}
}
stage('Generate SHA256 Hash and Upload to Artifact Repository') {
environment {
ARTIFACTS_KEY = credentials('artifactor-key')
}
steps {
sshagent(['artifactor-key']) {
sh ''' #!/usr/local/bin/bash
UUID=$(uuidgen -r)
VERSION=$(cat VERSION | cut -d"'" -f2)
BRANCH=${BRANCH_NAME}
ZIP_FILE="url-shortener_${BRANCH_NAME}_$(cat VERSION | cut -d"'" -f2).tgz"
sha256 $ZIP_FILE >> SHA256.sig
ssh artifactor@artifacts mkdir -p projects/url-shortener/$BRANCH/$VERSION/$UUID
rsync SHA256.sig artifactor@artifacts:projects/url-shortener/$BRANCH/$VERSION/$UUID/
rsync $ZIP_FILE artifactor@artifacts:projects/url-shortener/$BRANCH/$VERSION/$UUID/
'''
}
}
}
stage('Clean up deliverable') {
when {
expression {
buildArtifact
}
}
steps {
sh 'rm -rf /tmp/url-shortener'
sh 'rm SHA256.sig'
}
}
}
post {
success {
mattermostSend channel: 'git-messages', color: 'good', message: "[${JOB_NAME}](${JOB_URL}) [#${BUILD_NUMBER}](${BUILD_URL}) ([Gitea](${GIT_URL}))", text: 'Build Finished Successfully'
}
unstable {
mattermostSend channel: 'git-messages', color: 'warning', message: "[${JOB_NAME}](${JOB_URL}) [#${BUILD_NUMBER}](${BUILD_URL}) ([Gitea](${GIT_URL}))", text: "Build Unstable"
}
failure {
mattermostSend channel: 'git-messages', color: 'danger', message: "[${JOB_NAME}](${JOB_URL}) [#${BUILD_NUMBER}](${BUILD_URL}) ([Gitea](${GIT_URL}))", text: "Build Failed"
}
always {
cleanWs deleteDirs: true, patterns: [[pattern: '*', type: 'INCLUDE']]
}
}
}
+12 -8
View File
@@ -1,11 +1,11 @@
# simple url shortener
this project is a simple solution to build out a URL shortener using
Roda, Falcon, Sequel, and SQLite
Roda, Puma, Sequel, and SQLite on a FreeBSD Jail
the point of this project is to quickly build something and work on continuous deployment while making small refinements to the functional pieces.
the outside pieces of software that this project relies on are sqlite3 and pkgconf.
the outside pieces of software that this project relies on are rbenv, ruby-build, sqlite3, and pkgconf.
@@ -14,9 +14,9 @@ first you have to install the dependencies:
`bundle install`
if you want the development group included run this first:
if you want to skip the test dependencies:
`bundle config set --local with 'development'`
`bundle config set --local without 'test'`
then create a .env.rb file in the root directory that contains the following ENV attributes:
@@ -24,15 +24,19 @@ then create a .env.rb file in the root directory that contains the following ENV
```
ENV["APP_SESSION_SECRET"] = {output of a random 64 byte secret}
ENV["DB_NAME"] = {db file name}
ENV["DB_NAME"] = {DB_NAME}
```
after the dependencies are installed, you have to create the db
after the dependencies are installed, you have to create the db and schema
`sequel -m db/migrations sqlite://db/{DB_NAME}`
to start the application with Falcon:
to start the application with Puma:
`rackup -o {ip address} -p {port} -s falcon`
`rackup -o {ip address} -p {port}`
to run it as a daemon:
`rackup -o {ip address} -p {port} -D`
+1
View File
@@ -0,0 +1 @@
VERSION = '1.0.1'
+79 -14
View File
@@ -1,41 +1,106 @@
# frozen_string_literal: true
require 'roda'
require 'securerandom'
require 'json'
require 'sequel'
require 'open-uri'
# URL Shortener App class
class App < Roda
plugin :sessions, secret: ENV.delete('APP_SESSION_SECRET')
plugin :render, escape: true
plugin :flash
plugin :json_parser
plugin :request_headers
DB = Sequel.sqlite("db/#{ENV['DB_NAME']}")
DB = Sequel.sqlite("db/#{ENV.fetch('DB_NAME', nil)}")
links = DB[:links]
route do |r|
r.root do
@message = flash['message'] || "Enter a URL"
@message = flash['message'] || 'Enter a URL'
view :home
end
r.get String do | url_code |
link = links.filter(:code => url_code).first[:url]
r.redirect link
r.get String do |url_code|
link = links.filter(code: url_code)
r.redirect link.first[:url] unless link.first.nil?
@message = "Link #{url_code} doesn't exist"
response.status = 404
view :home
end
r.post "create" do
r.post 'create' do
url = r.params['url']
if url.empty?
flash['message'] = "Please enter a valid URL";
if url.nil? || url.empty?
flash['message'] = 'Please enter a valid URL'
r.redirect '/'
end
if nil == links.filter(:url => url).first
code = SecureRandom.urlsafe_base64 4
links.insert(url: url, code: code)
@message = "Link created"
begin
OpenURI.open_uri(url)
rescue URI::BadURIError
flash['message'] = 'Invalid URL'
r.redirect '/'
rescue OpenURI::HTTPError
flash['message'] = 'URL not found'
r.redirect '/'
rescue SocketError
flash['message'] = 'URL does not resolve'
r.redirect '/'
end
@message ||= "Link exists"
@new_link = 'http://' + request.env['HTTP_HOST'] + '/' + links.filter(:url => url).first[:code]
if links.filter(url:).first.nil?
code = SecureRandom.urlsafe_base64 4
links.insert(url:, code:)
@message = 'Link created'
end
code = links.filter(url:).first[:code]
@message ||= 'Link exists'
@new_link = "http://#{request.env['HTTP_HOST']}/#{code}"
view :create
end
r.on 'links' do
r.post do
if r.headers['CONTENT_TYPE'] != 'application/json'
response.status = 400
return { message: 'not a valid json request' }.to_json
end
url = r.params['url']
if url.nil?
response.status = 400
return { message: 'missing url parameter' }.to_json
end
if url.empty?
response.status = 400
return { message: 'invalid url parameter' }.to_json
end
begin
OpenURI.open_uri(url)
rescue URI::BadURIError
response.status = 400
return { message: 'invalid url parameter' }.to_json
rescue OpenURI::HTTPError
response.status = 400
return { message: 'url not found' }.to_json
rescue SocketError
response.status = 400
return { message: 'url does not resolve' }.to_json
end
if links.filter(url:).first.nil?
code = SecureRandom.urlsafe_base64 4
links.insert(url:, code:)
end
code = links.filter(url:).first[:code]
@new_link = "http://#{request.env['HTTP_HOST']}/#{code}"
return { url:, code:, link: @new_link }.to_json
end
end
end
end
+2
View File
@@ -1,3 +1,5 @@
# frozen_string_literal: true
require './.env'
require './app'
+2
View File
@@ -1,3 +1,5 @@
# frozen_string_literal: true
Sequel.migration do
change do
create_table :links do
-29
View File
@@ -10,32 +10,3 @@ Feature: Homepage
And I should see the message "Enter a URL"
And I should see a form field "url"
And I should see a "Submit" button
Scenario: Submitting the form without entering a URL
Given I visit the "/" page
When I click the "Submit" button
Then I should be on "/" page
And I should see the message "Please enter a valid URL"
@db-test
Scenario: Submitting the form with a correct URL
Given I visit the "/" page
When I type "http://google.com" in the "url" field
And I click the "Submit" button
Then I should be on "/create" page
And I should see the message "Link created"
@db-test
Scenario: Submitting the form with an existing URL
Given I visit the "/" page
And A link already exists with the url "http://google.com"
When I type "http://google.com" in the "url" field
And I click the "Submit" button
Then I should be on "/create" page
And I should see the message "Link exists"
@db-test
Scenario: Accessing the URL based on the shortcode
Given A link already exists with the url "https://google.com" and code "aaaaaa"
When I visit the "/aaaaaa" location
Then I should be redirected to "https://google.com"
+11 -4
View File
@@ -1,6 +1,8 @@
# frozen_string_literal: true
# BEFORE
Before('@db-test') do
@links = Sequel.sqlite("db/#{ENV['DB_NAME']}")[:links]
@links = Sequel.sqlite("db/#{ENV.fetch('DB_NAME', nil)}")[:links]
end
# GIVEN
@@ -10,17 +12,17 @@ Given('I visit the {string} page') do |string|
end
Given('A link already exists with the url {string}') do |string|
@links.insert(url: string, code: "aaaaaa")
@links.insert(url: string, code: 'aaaaaa')
end
Given('A link already exists with the url {string} and code {string}') do |url, code|
@links.insert(url: url, code: code)
@links.insert(url:, code:)
end
# WHEN
When('I click the {string} button') do |string|
click_button {string}
click_button { string }
end
When('I type {string} in the {string} field') do |text, field|
@@ -58,6 +60,11 @@ Then('I should be redirected to {string}') do |string|
location = actual.index(string)
location.should equal(0)
end
Then('The status code should be {int}') do |code|
page.status_code.should eq(code)
end
# AFTER
After('@db-test') do
+52
View File
@@ -0,0 +1,52 @@
# features/submit.feature
Feature: Submit
Submitting URL's on the homepage
Scenario: Submitting the form without entering a URL
Given I visit the "/" page
When I click the "Submit" button
Then I should be on "/" page
And I should see the message "Please enter a valid URL"
@db-test
Scenario: Submitting the form with a correct URL
Given I visit the "/" page
When I type "http://google.com" in the "url" field
And I click the "Submit" button
Then I should be on "/create" page
And I should see the message "Link created"
@db-test
Scenario: Submitting the form with an existing URL
Given I visit the "/" page
And A link already exists with the url "http://google.com"
When I type "http://google.com" in the "url" field
And I click the "Submit" button
Then I should be on "/create" page
And I should see the message "Link exists"
@db-test
Scenario: Submitting the form with a URL that is 404
Given I visit the "/" page
When I type "http://google.com/example" in the "url" field
And I click the "Submit" button
Then I should be on "/" page
And I should see the message "URL not found"
@db-test
Scenario: Submitting the form with a URL that does not resolve
Given I visit the "/" page
When I type "http://bad.tld" in the "url" field
And I click the "Submit" button
Then I should be on "/" page
And I should see the message "URL does not resolve"
@db-test
Scenario: Submitting the form with an invalid URL
Given I visit the "/" page
When I type "not-an-url" in the "url" field
And I click the "Submit" button
Then I should be on "/" page
And I should see the message "Invalid URL"
+9 -7
View File
@@ -1,25 +1,27 @@
# frozen_string_literal: true
require 'simplecov'
SimpleCov.start
require_relative '../../.env'
ENV["DB_NAME"] = "test_#{ENV["DB_NAME"]}"
ENV['DB_NAME'] = "test_#{ENV.fetch('DB_NAME', nil)}"
require_relative '../../app'
require 'rubygems'
require 'roda'
require 'sequel'
require 'capybara'
require 'capybara/dsl'
require 'capybara/cucumber'
require 'rspec'
###
require 'rspec/expectations'
require 'rspec/matchers'
# DB initialization
Sequel.extension :migration
Sequel.sqlite("db/#{ENV['DB_NAME']}") do |db|
Sequel::Migrator.apply(db, "db/migrations")
Sequel.sqlite("db/#{ENV.fetch('DB_NAME', nil)}") do |db|
Sequel::Migrator.apply(db, 'db/migrations')
end
# attach app to Capybara
Capybara.app = App
include Capybara::DSL
include RSpec::Expectations
include RSpec::Matchers
+19
View File
@@ -0,0 +1,19 @@
# features/visit.feature
Feature: Visit
Accessing a URL from it's link code
@db-test
Scenario: Accessing the URL based on the shortcode
Given A link already exists with the url "https://google.com" and code "aaaaaa"
When I visit the "/aaaaaa" location
Then I should be redirected to "https://google.com"
Scenario: Accessing a nonexistent URL code
Given I visit the "/aaaaaa" location
Then I should be on "/aaaaaa" page
And The status code should be 404
And I should see the message "Link aaaaaa doesn't exist"
And I should see a form field "url"
And I should see a "Submit" button
-2
View File
@@ -1,2 +0,0 @@
require 'securerandom'
puts SecureRandom.base64(64).inspect()
+103
View File
@@ -0,0 +1,103 @@
# frozen_string_literal: true
require 'simplecov'
SimpleCov.start
require_relative '../.env'
ENV['DB_NAME'] = "test_#{ENV.fetch('DB_NAME', nil)}"
require_relative '../app'
require 'rubygems'
require 'roda'
require 'sequel'
require 'rspec'
require 'rack/test'
# DB initialization
Sequel.extension :migration
Sequel.sqlite("db/#{ENV.fetch('DB_NAME', nil)}") do |db|
Sequel::Migrator.apply(db, 'db/migrations')
end
def app
App
end
describe 'Submit API request to create new link' do
include Rack::Test::Methods
before :each do
@links = Sequel.sqlite("db/#{ENV.fetch('DB_NAME', nil)}")[:links]
end
after :each do
@links.delete
end
it 'should return link data in json format when a valid url is submitted' do
data = {
url: 'http://google.com'
}
post('/links', data.to_json, 'CONTENT_TYPE' => 'application/json')
expect(last_response).to be_ok
response_json = JSON.parse(last_response.body)
expect(response_json['url']).to eq(data[:url])
expect(response_json['code']).not_to eq(nil)
expect(response_json['link']).to include(response_json['code'])
end
it "should return with a 400 status and 'invalid url parameter' message when an empty url is submitted" do
data = {
url: ''
}
post('/links', data.to_json, 'CONTENT_TYPE' => 'application/json')
expect(last_response.status).to eq(400)
response_json = JSON.parse(last_response.body)
expect(response_json['message']).to eq('invalid url parameter')
end
it "should return with a 400 status and 'missing url parameter' message when an empty url is submitted" do
data = {}
post('/links', data.to_json, 'CONTENT_TYPE' => 'application/json')
expect(last_response.status).to eq(400)
response_json = JSON.parse(last_response.body)
expect(response_json['message']).to eq('missing url parameter')
end
it "should return with a 400 status and 'invalid url parameter' message when an invalid url is submitted" do
data = {
url: 'not-an-url'
}
post('/links', data.to_json, 'CONTENT_TYPE' => 'application/json')
expect(last_response.status).to eq(400)
response_json = JSON.parse(last_response.body)
expect(response_json['message']).to eq('invalid url parameter')
end
it "should return with a 400 status and 'url not found' message when a 404 url is submitted" do
data = {
url: 'http://google.com/example'
}
post('/links', data.to_json, 'CONTENT_TYPE' => 'application/json')
expect(last_response.status).to eq(400)
response_json = JSON.parse(last_response.body)
expect(response_json['message']).to eq('url not found')
end
it "should return with a 400 status and 'url not found' message when a URL with no DNS is submitted" do
data = {
url: 'http://bad.tld'
}
post('/links', data.to_json, 'CONTENT_TYPE' => 'application/json')
expect(last_response.status).to eq(400)
response_json = JSON.parse(last_response.body)
expect(response_json['message']).to eq('url does not resolve')
end
it "should return with a 400 status and 'not a valid json request'
message when a request is made with the wrong content type header" do
data = {
url: 'http://google.com'
}
post('/links', data.to_json)
expect(last_response.status).to eq(400)
response_json = JSON.parse(last_response.body)
expect(response_json['message']).to eq('not a valid json request')
end
end