<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Yooniverse</title>
    <description>Write an awesome description for your new site here. You can edit this line in _config.yml. It will appear in your document head meta (for Google search results) and in your feed.xml site description.
</description>
    <link>https://oblsoun.github.io/</link>
    <atom:link href="https://oblsoun.github.io/feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Wed, 24 Apr 2024 00:35:06 +0900</pubDate>
    <lastBuildDate>Wed, 24 Apr 2024 00:35:06 +0900</lastBuildDate>
    <generator>Jekyll v3.9.5</generator>
    
      <item>
        <title>Jenkins - REST API를 이용한 Job 복사</title>
        <description>&lt;h4 id=&quot;개요&quot;&gt;개요&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;#사용-방법&quot;&gt;사용 방법&lt;/a&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#원본-Job-설정-파일-가져오기&quot;&gt;원본 Job 설정 파일 가져오기&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#Job-생성&quot;&gt;Job 생성&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h4 id=&quot;사용-방법&quot;&gt;사용 방법&lt;/h4&gt;

&lt;h5 id=&quot;원본-job-설정-파일-가져오기&quot;&gt;원본 Job 설정 파일 가져오기&lt;/h5&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;curl -X GET http://[JENKINS_URL]/job/[JOB_NAME]/config.xml -u [USER_NAME]:[API_TOKEN] &amp;gt; config.xml
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;[JENKINS_URL] Jenkins URL&lt;/li&gt;
  &lt;li&gt;[JOB_NAME] 복사할 Job Name&lt;/li&gt;
  &lt;li&gt;[USERNAME] 로그인 시 사용할 계정(admin)&lt;/li&gt;
  &lt;li&gt;[API_TOKEN] API token&lt;/li&gt;
&lt;/ul&gt;

&lt;h5 id=&quot;job-생성&quot;&gt;Job 생성&lt;/h5&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;curl -X POST -H &quot;Content-Type: application/xml&quot; -d @config.xml &quot;http://[JENKINS_URL]/createItem?name=[NEW_JOB_NAME]&quot; -u [USER_NAME]:[API_TOKEN]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;[JENKINS_URL] Jenkins URL&lt;/li&gt;
  &lt;li&gt;[NEW_JOB_NAME] 생성할 Job Name&lt;/li&gt;
  &lt;li&gt;[USER_NAME] 로그인 시 사용할 계정(admin)&lt;/li&gt;
  &lt;li&gt;[API_TOKEN] API token&lt;/li&gt;
&lt;/ul&gt;

</description>
        <pubDate>Tue, 23 Apr 2024 00:00:00 +0900</pubDate>
        <link>https://oblsoun.github.io/2024-04/study-jenkinsRESTAPIcopyjob</link>
        <guid isPermaLink="true">https://oblsoun.github.io/2024-04/study-jenkinsRESTAPIcopyjob</guid>
        
        
        <category>Study</category>
        
      </item>
    
      <item>
        <title>Jenkins - Matrix Authorization Strategy Plugin</title>
        <description>&lt;h4 id=&quot;개요&quot;&gt;개요&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;#Use-Case&quot;&gt;Use Case&lt;/a&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#사용자별-Use-Case&quot;&gt;사용자별 Use Case&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#프로젝트별-Use-Case&quot;&gt;프로젝트별 Use Case&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#사용-목적&quot;&gt;사용 목적&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h4 id=&quot;use-case&quot;&gt;Use Case&lt;/h4&gt;

&lt;p&gt;사용자별/프로젝트별 권한을 설정하여 관리한다.&lt;/p&gt;

&lt;h5 id=&quot;사용자별-use-case&quot;&gt;사용자별 Use Case&lt;/h5&gt;

&lt;ul&gt;
  &lt;li&gt;Matrix Authorization Strategy 플러그인 설치&lt;/li&gt;
  &lt;li&gt;Jenkins 관리 &amp;gt; Configure Global Security &amp;gt; Authorization &amp;gt; Matrix-based security 선택&lt;/li&gt;
  &lt;li&gt;Add user &amp;gt; 권한 설정&lt;/li&gt;
&lt;/ul&gt;

&lt;h5 id=&quot;프로젝트별-use-case&quot;&gt;프로젝트별 Use Case&lt;/h5&gt;

&lt;ul&gt;
  &lt;li&gt;Matrix Authorization Strategy 플러그인 설치&lt;/li&gt;
  &lt;li&gt;Jenkins 관리 &amp;gt; Configure Global Security &amp;gt; Authorization &amp;gt; Matrix-based security 선택&lt;/li&gt;
  &lt;li&gt;Item 구성 &amp;gt; General &amp;gt; Enable project-based security 체크박스 선택&lt;/li&gt;
  &lt;li&gt;Add user &amp;gt; 권한 설정&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h4 id=&quot;사용-목적&quot;&gt;사용 목적&lt;/h4&gt;

&lt;p&gt;권한은 기본적으로 전역으로 구성되어 있거나 모든 상위 목록에서 상속된다. 하지만 Matrix Authorization Plugin을 사용하게 되면 각 항목 또는 사용자들에 대한 권한을 독립적으로 구성이 가능하다.&lt;/p&gt;
</description>
        <pubDate>Tue, 23 Apr 2024 00:00:00 +0900</pubDate>
        <link>https://oblsoun.github.io/2024-04/study-jenkinsMASplugin</link>
        <guid isPermaLink="true">https://oblsoun.github.io/2024-04/study-jenkinsMASplugin</guid>
        
        
        <category>Study</category>
        
      </item>
    
      <item>
        <title>Jenkins - 설치 방법</title>
        <description>&lt;h4 id=&quot;개요&quot;&gt;개요&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;#환경&quot;&gt;환경&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#저장소-키-가져오기&quot;&gt;저장소 키 가져오기&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#Jenkins의-패키지-저장소-항목-추가&quot;&gt;Jenkins의 패키지 저장소 항목 추가&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#Java-패키지-버전-설치&quot;&gt;Java 패키지 버전 설치&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#Jenkins-설치&quot;&gt;Jenkins 설치&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#Jenkins-자동-실행-설정&quot;&gt;Jenkins 자동 실행 설정&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#Jenkins-서비스-시작&quot;&gt;Jenkins 서비스 시작&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#포트-번호-허용&quot;&gt;포트 번호 허용&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#Jenkins-접속&quot;&gt;Jenkins 접속&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h4 id=&quot;환경&quot;&gt;환경&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;OS: Window&lt;/li&gt;
  &lt;li&gt;VM: Virtual Box&lt;/li&gt;
  &lt;li&gt;VM 내 OS: Linux(Ubuntu)&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h4 id=&quot;저장소-키-가져오기&quot;&gt;저장소 키 가져오기&lt;/h4&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo wget -O /usr/share/keyrings/jenkins-keyring.asc https://pkg.jenkins.io/debian-stable/jenkins.io-2023.key
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;jenkins의-패키지-저장소-항목-추가&quot;&gt;Jenkins의 패키지 저장소 항목 추가&lt;/h4&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;echo deb [signed-by=/usr/share/keyrings/jenkins-keyring.asc] \
    https://pkg.jenkins.io/debian-stable binary/ | sudo tee \
    /etc/apt/sources.list.d/jenkins.list &amp;gt; /dev/null
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo apt update
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;java-패키지-버전-설치&quot;&gt;Java 패키지 버전 설치&lt;/h4&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo apt install fontconfig openjdk-11-jre
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo apt update
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;jenkins-설치&quot;&gt;Jenkins 설치&lt;/h4&gt;

&lt;p&gt;특정 버전 설치 시 [VERSION] 내에 원하는 버전 입력&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo apt install jenkins=[VERSION]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo apt update
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;jenkins-자동-실행-설정&quot;&gt;Jenkins 자동 실행 설정&lt;/h4&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo systemctl enable --now jenkins
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;jenkins-서비스-시작&quot;&gt;Jenkins 서비스 시작&lt;/h4&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo systemctl start jenkins
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;포트-번호-허용&quot;&gt;포트 번호 허용&lt;/h4&gt;

&lt;p&gt;기본 포트 번호: 8080&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo ufw allow 8080
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;jenkins-접속&quot;&gt;Jenkins 접속&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;localhost:8080&lt;/li&gt;
  &lt;li&gt;initialAdminPassword 위치 확인 후 복사 및 붙여넣기&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h4 id=&quot;참고-링크&quot;&gt;참고 링크&lt;/h4&gt;

&lt;p&gt;&lt;a href=&quot;https://pkg.origin.jenkins.io/debian-stable/&quot;&gt;클릭 시 이동&lt;/a&gt;&lt;/p&gt;
</description>
        <pubDate>Tue, 23 Apr 2024 00:00:00 +0900</pubDate>
        <link>https://oblsoun.github.io/2024-04/study-installJenkins</link>
        <guid isPermaLink="true">https://oblsoun.github.io/2024-04/study-installJenkins</guid>
        
        
        <category>Study</category>
        
      </item>
    
      <item>
        <title>Groovy Script 예시</title>
        <description>&lt;h4 id=&quot;개요&quot;&gt;개요&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;#개요&quot;&gt;개요&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#오래된-스크립트&quot;&gt;오래된 스크립트&lt;/a&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#jenkins의-로컬-복사본-시작&quot;&gt;Jenkins의 로컬 복사본 시작&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#scriptler-플러그인-groovy-script&quot;&gt;Scriptler 플러그인 Groovy Script&lt;/a&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#--jenkins-서버의-모든-작업에-대해-chuck-norris-플러그인-활성화&quot;&gt;Jenkins 서버의 모든 작업에 대해 Chuck Norris 플러그인 활성화&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#모든-작업에-알림-플러그인-추가&quot;&gt;모든 작업에 알림 플러그인 추가&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#서버의-모든-작업에서-옵션-활성화&quot;&gt;서버의 모든 작업에서 옵션 활성화&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#hg에서-체크아웃된-branch-일괄-업데이트&quot;&gt;Hg에서 체크아웃된 branch 일괄 업데이트&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#프로젝트-대량-이름-바꾸기&quot;&gt;프로젝트 대량 이름 바꾸기&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#freestyle-작업에-등록된-모든-maven-작업을-찾아-jvm-옵션을-새-값으로-변경&quot;&gt;Freestyle 작업에 등록된 모든 Maven 작업을 찾아 JVM 옵션을 새 값으로 변경&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#ssh-구성을-통한-게시-변경&quot;&gt;SSH 구성을 통한 게시 변경&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#21000700-및-주말에-비활성화&quot;&gt;21:00~07:00 및 주말에 비활성화&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#svn-경로의-버전-번호-변경&quot;&gt;SVN 경로의 버전 번호 변경&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#특정-보기에-속한-모든-프로젝트를-열거하고-복제&quot;&gt;특정 보기에 속한 모든 프로젝트를 열거하고 복제&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#모든-프로젝트의-메일-알림을-mail-ext-게시자-플러그인으로-대체-기존-수신자-재사용&quot;&gt;모든 프로젝트의 메일 알림을 Mail-Ext 게시자 플러그인으로 대체, 기존 수신자 재사용&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#빌드-후-작업-공간-파일-디렉토리에-남아있는-모든-tml-파일-삭제&quot;&gt;빌드 후 작업 공간 파일 디렉토리에 남아있는 모든 tml 파일 삭제&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#비활성화된-모든-작업에-대한-작업-공간-삭제&quot;&gt;비활성화된 모든 작업에 대한 작업 공간 삭제&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#jenkins-서버의-모든-작업을-비활성화&quot;&gt;Jenkins 서버의 모든 작업을 비활성화&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#모든-에이전트-노드에-대한-정보-표시&quot;&gt;모든 에이전트 노드에 대한 정보 표시&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#모든-작업에-대한-매개변수-표시&quot;&gt;모든 작업에 대한 매개변수 표시&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#사용하는-빌드-단계별로-작업-그룹-표시&quot;&gt;사용하는 빌드 단계별로 작업 그룹 표시&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#모든-작업에-대해-알림에-사용되는-메일-수신자-목록-표시&quot;&gt;모든 작업에 대해 알림에 사용되는 메일 수신자 목록 표시&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#jenkins는-모니터를-사용하여-다양한-동작을-검증-하나를-닫으면-jenkin는-다시-활성화하도록-제안하지-않음-스크립트-사용-시-모든-모니터-상태-확인-후-재활성화-가능&quot;&gt;Jenkins는 모니터를 사용하여 다양한 동작을 검증. 하나를 닫으면 Jenkin는 다시 활성화하도록 제안하지 않음. 스크립트 사용 시 모든 모니터 상태 확인 후 재활성화 가능&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#모든-작업에-대한-타이머-트리거-표시&quot;&gt;모든 작업에 대한 타이머 트리거 표시&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#모든-에이전트에서-jenkins-도구-위치-표시&quot;&gt;모든 에이전트에서 Jenkins 도구 위치 표시&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#서버의-모든-작업에서-타임스탬퍼-플러그인-활성화&quot;&gt;서버의 모든 작업에서 타임스탬퍼 플러그인 활성화&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#실패한-모든-작업-목록-표시&quot;&gt;실패한 모든 작업 목록 표시&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#--addon-restart&quot;&gt;Addon: Restart&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#현재-실행-중이며-n초-이상-실행된-빌드-찾기&quot;&gt;현재 실행 중이며 N초 이상 실행된 빌드 찾기&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#빌드-권한이-있는-사용자-및-그룹에-취소-권한-부여&quot;&gt;빌드 권한이 있는 사용자 및 그룹에 취소 권한 부여&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#jenkins-http-세션-무효화&quot;&gt;Jenkins HTTP 세션 무효화&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#모든-작업에서-수동으로-로그-회전-실행&quot;&gt;모든 작업에서 수동으로 로그 회전 실행&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#수동으로-연결이-끊어지지-않은-경우-오프라인-노드를-모니터링-후-다시-시작&quot;&gt;수동으로 연결이 끊어지지 않은 경우 오프라인 노드를 모니터링 후 다시 시작&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#모니터링-플러그인-사용-시-http-세션-스레드-메모리-jvm-또는-mbean에-대한-데이터를-표시하는-여러-스크립트&quot;&gt;모니터링 플러그인 사용 시 http 세션, 스레드, 메모리, JVM 또는 MBean에 대한 데이터를 표시하는 여러 스크립트&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#매개변수화된-시스템-groovy-script&quot;&gt;매개변수화된 시스템 Groovy Script&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#maven-release-build에서-사용자-이름-미리-선택&quot;&gt;Maven release build에서 사용자 이름 미리 선택&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#자격-증명-및-해당-id-목록-인쇄&quot;&gt;자격 증명 및 해당 ID 목록 인쇄&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#maven-작업에서-비활성화된-모든-모듈-제거&quot;&gt;Maven 작업에서 비활성화된 모든 모듈 제거&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#artifact-deployer-플러그인이-각-빌드에-대해-불필요하게-저장한-배포된-artifact-목록-제거&quot;&gt;Artifact Deployer 플러그인이 각 빌드에 대해 불필요하게 저장한 배포된 Artifact 목록 제거&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#git-플러그인이-각-빌드에-대해-불필요하게-저장한-buildsbybranch의-정적-목록-제거&quot;&gt;Git 플러그인이 각 빌드에 대해 불필요하게 저장한 BuildsByBranch의 정적 목록 제거&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#모든-저장소에-대한-사용자-정의-설정으로-gitblitrepositorybrowser-설정&quot;&gt;모든 저장소에 대한 사용자 정의 설정으로 GitBlitRepositoryBrowser 설정&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#빌드-후-단계를-설치하고-활성화하여-배포-목표가-있는-모든-maven-작업-업데이트&quot;&gt;빌드 후 단계를 설치하고 활성화하여 배포 목표가 있는 모든 Maven 작업 업데이트&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#svn-브라우저-업데이트&quot;&gt;SVN 브라우저 업데이트&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#jenkins-서버에-있는-모든-작업의-작업-공간-제거&quot;&gt;Jenkins 서버에 있는 모든 작업의 작업 공간 제거&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#모든-노드에-있는-특정-작업의-작업-공간-지우기&quot;&gt;모든 노드에 있는 특정 작업의 작업 공간 지우기&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;오래된-스크립트&quot;&gt;오래된 스크립트&lt;/h4&gt;
&lt;p&gt;Jenkins 소스코드에 직접 액세스하는 Groovy 스크립트 특성으로 인해 Script Console Script는 Jenkins 소스코드에서 쉽게 구식이 된다. Jenkins 코어 또는 Jenkins 플러그인의 공용 메소드 및 인터페이스가 변경되었으므로 스크립트를 실행하고 예외를 받는 것이 가능합니다.&lt;/p&gt;

&lt;h5 id=&quot;jenkins의-로컬-복사본-시작&quot;&gt;Jenkins의 로컬 복사본 시작&lt;/h5&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;export JENKINS_HOME=&quot;./my_jenkins_home&quot;
java -jar jenkins.war
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;blockquote&gt;
  &lt;p&gt;Jenkins 중지 시: Ctrl + C &lt;br /&gt;
프로덕션 Jenkins 인스턴스에서 Script Console 예제를 시도하는 것은 권장 X &lt;br /&gt;
Jenkins용 Groovy 스크립트 예시 &lt;br /&gt;
 &lt;a href=&quot;https://github.com/cloudbees/jenkins-scripts&quot;&gt;CloudBees 젠킨스 스트립트 저장소&lt;/a&gt; &lt;br /&gt;
 &lt;a href=&quot;https://github.com/jenkinsci/jenkins-scripts&quot;&gt;scriptler/Jenkins CI &amp;gt; jenkins-scripts 저장소&lt;/a&gt; (&lt;a href=&quot;https://plugins.jenkins.io/scriptler&quot;&gt;Scriptler 플러그인&lt;/a&gt;용 스크립트) &lt;br /&gt;
 &lt;a href=&quot;https://github.com/samrocketman/jenkins-script-console-scripts&quot;&gt;Sam Gleske의 jenkins-script-console-scripts 저장소&lt;/a&gt; &lt;br /&gt;
 &lt;a href=&quot;https://github.com/samrocketman/jenkins-bootstrap-shared&quot;&gt;Sam Gleske의 jenkins-bootstrap-shared 저장소는 scrips/디렉토리 아래에 존재&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4 id=&quot;scriptler-플러그인-groovy-script&quot;&gt;Scriptler 플러그인 Groovy Script&lt;/h4&gt;
&lt;h5 id=&quot;--jenkins-서버의-모든-작업에-대해-chuck-norris-플러그인-활성화&quot;&gt;- Jenkins 서버의 모든 작업에 대해 Chuck Norris 플러그인 활성화&lt;/h5&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;import jenkins.model.*


for(item in Jenkins.instance.items) {
     println(&quot;job $item.name&quot;)
     item.publishersList.replace(new  hudson.plugins.chucknorris.CordellWalkerRecorder());
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h5 id=&quot;모든-작업에-알림-플러그인-추가&quot;&gt;모든 작업에 알림 플러그인 추가&lt;/h5&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;for (item in Hudson.instance.items) { 
  notification = item.properties.find { it.getKey().getClass() == com.tikal.hudson.plugins.notification.HudsonNotificationPropertyDescriptor }    
  if (notification != null) {
    continue
  }

  println(&quot;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; Adding notification plugin to $item.name&quot;)   
  protocol = com.tikal.hudson.plugins.notification.Protocol.UDP
  endpoint = new com.tikal.hudson.plugins.notification.Endpoint(protocol, &apos;172.16.24.204:11337&apos;)
  notification = new com.tikal.hudson.plugins.notification.HudsonNotificationProperty([endpoint])

  item.addProperty(notification)
  item.save()
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h5 id=&quot;서버의-모든-작업에서-옵션-활성화&quot;&gt;서버의 모든 작업에서 옵션 활성화&lt;/h5&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;import hudson.model.*
import hudson.maven.*
import hudson.tasks.*

for(item in Hudson.instance.items) {
  println(&quot;job $item.name&quot;)
  hasClaim = false;
  for(p in item.publishers )
  {
    if(p instanceof hudson.plugins.claim.ClaimPublisher)
    {
      hasClaim = true;
    }
  }
  if(!hasClaim)
  {
    println(&quot;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; Adding claim right to $item.name&quot;)
    item.getPublishersList().add(new  hudson.plugins.claim.ClaimPublisher() );
    item.save()
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h5 id=&quot;hg에서-체크아웃된-branch-일괄-업데이트&quot;&gt;Hg에서 체크아웃된 branch 일괄 업데이트&lt;/h5&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;def oldBranch = &quot;NAME_OF_OLD_BRANCH&quot; // update this
def newBranch = &quot;NAME_OF_NEW_BRANCH&quot; // update this
def jobNamePattern = &quot;YourRegExPattern&quot; // update this
def freeStyleJobs = hudson.model.Hudson.instance.getItems(hudson.model.FreeStyleProject.class)
for (job in freeStyleJobs)
{
  def oldScm = job.getScm()
  if (oldScm.getType().indexOf(&quot;Mercurial&quot;) 1 &amp;amp;&amp;amp; job.name.matches(jobNamePattern))
  {
    if (oldScm.getBranch().equals(oldBranch))
    {
      print &quot;Job &apos;${job.name}&apos; has branch &apos;${oldBranch}&apos; and will be updated to &apos;${newBranch}&apos;&quot;
      // uncomment the next two lines to actually perform the operation. Else it simulates a dry-run
      //def newHgSCM = new  hudson.plugins.mercurial.MercurialSCM(oldScm.getInstallation(),  oldScm.getSource(), newBranch, oldScm.getModules(), oldScm.getSubdir(),  oldScm.getBrowser(), oldScm.isClean())
      //job.setScm(newHgSCM)      println &quot;[OK]&quot;  
    } else if (oldScm.getBranch().equals(newBranch))
    {
      println &quot;Job &apos;${job.name}&apos; already is on branch &apos;${newBranch}&apos;&quot;  
    } else
    {
      println &quot;Job &apos;${job.name}&apos; is on branch &apos;${oldScm.getBranch()}&apos; and will not be updated&quot; 
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h5 id=&quot;프로젝트-대량-이름-바꾸기&quot;&gt;프로젝트 대량 이름 바꾸기&lt;/h5&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;import hudson.model.*

disableChildren(Hudson.instance.items)

def disableChildren(items) {
  for (item in items) {
    if (item.class.canonicalName != &apos;com.cloudbees.hudson.plugins.folder.Folder&apos;) {
	if (( m = item.name =~ /^(Findur.OpenComponent)(\..*)$/)){
          println(item.name)
          println m.group(1) + &quot; &quot; + m.group(2)
          newname = m[0][1] + &apos;s&apos; + m.group(2)
          item.renameTo(newname)
      }
    } else {
	disableChildren(((com.cloudbees.hudson.plugins.folder.Folder) item).getItems())
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h5 id=&quot;freestyle-작업에-등록된-모든-maven-작업을-찾아-jvm-옵션을-새-값으로-변경&quot;&gt;Freestyle 작업에 등록된 모든 Maven 작업을 찾아 JVM 옵션을 새 값으로 변경&lt;/h5&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;import hudson.model.*
import hudson.maven.*
import hudson.tasks.*

def newJvmOptions=&quot;-Xshare:auto -Xms64m -Xmx512m -XX:MaxPermSize=256M&quot;

// For each project
for(item in Hudson.instance.allItems) {
  if(item instanceof FreeStyleProject) {
    println(&quot;JOB : &quot;+item.name);
    // Find current recipients defined in project
    println(&quot;&amp;gt;FREESTYLE PROJECT&quot;);
    for (builder in item.builders){
      println(&quot;&amp;gt;&amp;gt; &quot;+builder);
      if (builder instanceof Maven) {
        println(&quot;&amp;gt;&amp;gt;MAVEN BUILDER&quot;);
        println(&quot;&amp;gt;&amp;gt;TARGETS : &quot;+builder.targets);
        println(&quot;&amp;gt;&amp;gt;NAME : &quot;+builder.mavenName);
        println(&quot;&amp;gt;&amp;gt;POM : &quot;+builder.pom);
        // .properties is overridden by groovy
        println(&quot;&amp;gt;&amp;gt;PROPERTIES : &quot;+builder.@properties);
        println(&quot;&amp;gt;&amp;gt;JVM-OPTIONS : &quot;+builder.jvmOptions);
        println(&quot;&amp;gt;&amp;gt;USE PRIVATE REPO : &quot;+builder.usePrivateRepository);
        println(&quot;&amp;gt;&amp;gt;USER SETTINGS : &quot;+builder.settings);
        println(&quot;&amp;gt;&amp;gt;GLOBAL SETTINGS : &quot;+builder.globalSettings);
        def newBuilder = new Maven(builder.targets,builder.mavenName,builder.pom,builder.@properties,newJvmOptions,builder.usePrivateRepository,builder.settings,builder.globalSettings);
        item.buildersList.replace(newBuilder);
      }
    }
    println(&quot;\n=======\n&quot;);
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h5 id=&quot;ssh-구성을-통한-게시-변경&quot;&gt;SSH 구성을 통한 게시 변경&lt;/h5&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;import java.util.*
import hudson.model.*
import hudson.maven.*
import hudson.maven.reporters.*
import hudson.matrix.*
import hudson.tasks.*
import hudson.util.DescribableList
import jenkins.plugins.publish_over_ssh.*
import jenkins.plugins.publish_over.*

hudson.model.Hudson.instance.items.findAll{job -&amp;gt; job.isBuildable() }.each{
job -&amp;gt; 

  if(job instanceof FreeStyleProject) {
    for (builder in job.builders){
      if(builder instanceof BapSshBuilderPlugin) {
        ArrayList&amp;lt;BapPublisher&amp;gt; publishers = builder.delegate.delegate.publishers
        
        for(publisher in publishers) {
          if (publisher.configName == &quot;bad-server&quot;) {
            println &quot;Changing job: ${job.name}&quot;
            publisher.configName = &quot;good-server&quot;
          }
        }
      }
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h5 id=&quot;21000700-및-주말에-비활성화&quot;&gt;21:00~07:00 및 주말에 비활성화&lt;/h5&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;import hudson.model.*
import hudson.triggers.*


TriggerDescriptor SCM_TRIGGER_DESCRIPTOR = Hudson.instance.getDescriptorOrDie(SCMTrigger.class)
assert SCM_TRIGGER_DESCRIPTOR != null;

for(item in Hudson.instance.items)
{
  println(&quot;Working on project &amp;lt;$item.name&amp;gt;&quot;)
  
  def trigger = item.getTriggers().get(SCM_TRIGGER_DESCRIPTOR)
  if(trigger != null &amp;amp;&amp;amp; trigger instanceof SCMTrigger)
  {
    print(&quot;&amp;gt; $trigger.spec&quot;)
    String[] parts = trigger.spec.split(&quot; &quot;);
    
    //Do wanted modifs
    if(parts[1] == &quot;*&quot; )
    {
      parts[1] = &quot;7-21&quot;
    }
    if(parts[4] == &quot;*&quot;)
    {
      parts[4] = &quot;1-5&quot;
    }
    //end modifs
    
    StringBuilder newSpec = new StringBuilder();
    for(p in parts)
    {
      newSpec.append(p+&quot; &quot;);
    }
    
    println(&quot; =&amp;gt; $newSpec&quot;);

    def newTrigger = new SCMTrigger(newSpec.toString())
    newTrigger.job = item

    item.removeTrigger(SCM_TRIGGER_DESCRIPTOR)
    item.addTrigger(newTrigger)
  }
  else
  {
    println &quot;&amp;gt; Nothing to do&quot;
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h5 id=&quot;svn-경로의-버전-번호-변경&quot;&gt;SVN 경로의 버전 번호 변경&lt;/h5&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;import hudson.scm.*
//import hudson.model.*

/** Old Version for the SVN-Path */
oldVersion  = &quot;1.28&quot;

/** New Version for the SVN-Path */
newVersion  = &quot;1.29&quot;

/** Path to the SVN-Repo containing with the following */
svnpath = &quot;repo/testjob&quot;

 /** Jobs containing with */
jobs = &quot;testjob&quot;

/** Should we override existing values? */
overrideExistingValues = false

/** Display Konfiguration */
println &quot;### Overwrite SVN-Version ###&quot;
println &quot;oldVersion:     &quot; + oldVersion
println &quot;newVersion:     &quot; + newVersion
println &quot;Jobs with:      &quot; + jobs
println &quot;Repo_with_Path: &quot; + svnpath


// ----- Do the work. -----

// Access to the Hudson Singleton
hudsonInstance = hudson.model.Hudson.instance

// Retrieve all Jobs which starts with -jobs-
allItems = hudsonInstance.items
chosenJobs = allItems.findAll{job -&amp;gt; job.name.contains(jobs)}

// Table header
col1 = &quot;Job&quot;.center(35)
col2 = &quot;OldPath&quot;.center(120)
col3 = &quot;NewPath&quot;.center(120)
header = &quot;$col1 | $col2 | $col3&quot;
line = header.replaceAll(&quot;[Change Version-Number in SVN-path^|]&quot;, &quot;-&quot;).replaceAll(&quot;\\|&quot;, &quot;+&quot;)

println line
println header
println line

// Do work and create the result table
chosenJobs.each { job -&amp;gt;
 if(!(job instanceof hudson.model.ExternalJob)) {
   // No SCM-Configuration possible for External Jobs!
   if (job.scm instanceof SubversionSCM) {
     // Job has a SubversionSCM-Konfiguration
     def oldSvnPath = [][]
     def newSvnPath = [][]
     job.scm.locations.each{
       //For every Subversion-Location
       if (it.remote.contains(svnpath)) {
         //SVN-Path contains the given Path
         oldRemote = it.remote.padRight(119)
         jobname  = job.name.padRight(35)
         newRemote = it.remote
         if (it.remote.contains(oldVersion)) {
           //SVN-Path contains the old Version, which should be replaced
           newRemote = it.remote.replaceAll(/$oldVersion/,&quot;$newVersion&quot;)  //Replace
           //Build new SVN-Location (it is not possible to change a value in the existing configuration)
           newSvnPath.add(new hudson.scm.SubversionSCM.ModuleLocation(newRemote,it.local))

           //For Visualisation of the changed Value
           newRemote = newRemote.padRight(120,&quot;&amp;lt;&quot;)
           // Output Result for this Subversion-Location
           println &quot;$jobname | $oldRemote ]&amp;gt; $newRemote&quot;
         } else {
           //Visualisation of value which is not changed
           newRemote = newRemote.padRight(120)
           // Output Result for this Subversion-Location
           println &quot;$jobname | $oldRemote  | $newRemote&quot;
         }
       }

     }
     // Every Location was checked. Building new SVN-Configuration with the new SVN-Locations
     newscm = new hudson.scm.SubversionSCM(newSvnPath, job.scm.workspaceUpdater, job.scm.browser,
     job.scm.excludedRegions, job.scm.excludedUsers, job.scm.excludedRevprop, job.scm.excludedCommitMessages, job.scm.includedRegions)
     if (overrideExistingValues){
       // Only write values, when overrideExistingValues is true
       job.scm = newscm;
     }
     println line
     //Job is done
   }
 }
}
println line
//done
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h5 id=&quot;특정-보기에-속한-모든-프로젝트를-열거하고-복제&quot;&gt;특정 보기에 속한 모든 프로젝트를 열거하고 복제&lt;/h5&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;import hudson.model.*
 
def str_view = &quot;MyProduct_Release_1.0&quot;
def str_search = &quot;Rel_1.0&quot;
def str_replace = &quot;Rel_1.1&quot;
 
def view = Hudson.instance.getView(str_view)
 
//copy all projects of a view
for(item in view.getItems())
{

  //create the new project name
  newName = item.getName().replace(str_search, str_replace)

 
  // copy the job, disable and save it
  def job = Hudson.instance.copy(item, newName)
  job.disabled = true
  job.save()
  
  // update the workspace to avoid having two projects point to the same location
  AbstractProject project = job
  def new_workspace = project.getCustomWorkspace().replace(str_search, str_replace)
  project.setCustomWorkspace(new_workspace)
  project.save()
  
  println(&quot; $item.name copied as $newName&quot;)

}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h5 id=&quot;모든-프로젝트의-메일-알림을-mail-ext-게시자-플러그인으로-대체-기존-수신자-재사용&quot;&gt;모든 프로젝트의 메일 알림을 Mail-Ext 게시자 플러그인으로 대체, 기존 수신자 재사용&lt;/h5&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;import hudson.model.*
 
def str_view = &quot;MyProduct_Release_1.0&quot;
def str_search = &quot;Rel_1.0&quot;
def str_replace = &quot;Rel_1.1&quot;
 
def view = Hudson.instance.getView(str_view)
 
//copy all projects of a view
for(item in view.getItems())
{

  //create the new project name
  newName = item.getName().replace(str_search, str_replace)

 
  // copy the job, disable and save it
  def job = Hudson.instance.copy(item, newName)
  job.disabled = true
  job.save()
  
  // update the workspace to avoid having two projects point to the same location
  AbstractProject project = job
  def new_workspace = project.getCustomWorkspace().replace(str_search, str_replace)
  project.setCustomWorkspace(new_workspace)
  project.save()
  
  println(&quot; $item.name copied as $newName&quot;)

}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h5 id=&quot;빌드-후-작업-공간-파일-디렉토리에-남아있는-모든-tml-파일-삭제&quot;&gt;빌드 후 작업 공간 파일 디렉토리에 남아있는 모든 tml 파일 삭제&lt;/h5&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;import hudson.model.*

def counter = 0

// Create a ref for closure
def delClos

// Define closure
delClos = {
	it.eachDir( delClos );
	if(it.getName().contains(&quot;workspace-files&quot;)) {
		it.eachFile {
			if(it.getName().endsWith(&quot;.tmp&quot;) ){
				println &quot;Deleting file ${it.canonicalPath}&quot;;
				it.delete()
				counter++;
			}
		}
	}
}

// Apply closure
for(item in Hudson.instance.items) {
	println &quot;Applying on &quot; + item.rootDir
	delClos( item.rootDir )
}
println counter + &quot; files deleted&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h5 id=&quot;비활성화된-모든-작업에-대한-작업-공간-삭제&quot;&gt;비활성화된 모든 작업에 대한 작업 공간 삭제&lt;/h5&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;//michaeldkfowler
import jenkins.model.*
Jenkins.instance.getAllItems(AbstractProject.class)
.findAll {it.disabled}
    .each {
      println(&quot;Wiping workspace for &quot;+it.fullName)
      it.doDoWipeOutWorkspace()
    }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h5 id=&quot;jenkins-서버의-모든-작업을-비활성화&quot;&gt;Jenkins 서버의 모든 작업을 비활성화&lt;/h5&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;import hudson.model.*


disableChildren(Hudson.instance.items)

def disableChildren(items) {
  for (item in items) {
    if (item.class.canonicalName == &apos;com.cloudbees.hudson.plugins.folder.Folder&apos;) {
        disableChildren(((com.cloudbees.hudson.plugins.folder.Folder) item).getItems())
    } else if (item.class.canonicalName != &apos;org.jenkinsci.plugins.workflow.job.WorkflowJob&apos;) {
      item.disabled=true
      item.save()
      println(item.name)
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h5 id=&quot;모든-에이전트-노드에-대한-정보-표시&quot;&gt;모든 에이전트 노드에 대한 정보 표시&lt;/h5&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;for (aSlave in hudson.model.Hudson.instance.slaves) {
  println(&apos;====================&apos;);
  println(&apos;Name: &apos; + aSlave.name);
  println(&apos;getLabelString: &apos; + aSlave.getLabelString());
  println(&apos;getNumExectutors: &apos; + aSlave.getNumExecutors());
  println(&apos;getRemoteFS: &apos; + aSlave.getRemoteFS());
  println(&apos;getMode: &apos; + aSlave.getMode());
  println(&apos;getRootPath: &apos; + aSlave.getRootPath());
  println(&apos;getDescriptor: &apos; + aSlave.getDescriptor());
  println(&apos;getComputer: &apos; + aSlave.getComputer());
  println(&apos;\tcomputer.isAcceptingTasks: &apos; + aSlave.getComputer().isAcceptingTasks());
  println(&apos;\tcomputer.isLaunchSupported: &apos; + aSlave.getComputer().isLaunchSupported());
  println(&apos;\tcomputer.getConnectTime: &apos; + aSlave.getComputer().getConnectTime());
  println(&apos;\tcomputer.getDemandStartMilliseconds: &apos; + aSlave.getComputer().getDemandStartMilliseconds());
  println(&apos;\tcomputer.isOffline: &apos; + aSlave.getComputer().isOffline());
  println(&apos;\tcomputer.countBusy: &apos; + aSlave.getComputer().countBusy());
  //if (aSlave.name == &apos;NAME OF NODE TO DELETE&apos;) {
  //  println(&apos;Shutting down node!!!!&apos;);
  //  aSlave.getComputer().setTemporarilyOffline(true,null);
  //  aSlave.getComputer().doDoDelete();
  //}
  println(&apos;\tcomputer.getLog: &apos; + aSlave.getComputer().getLog());
  println(&apos;\tcomputer.getBuilds: &apos; + aSlave.getComputer().getBuilds());
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h5 id=&quot;모든-작업에-대한-매개변수-표시&quot;&gt;모든 작업에 대한 매개변수 표시&lt;/h5&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;import hudson.model.*

for(item in Hudson.instance.items) {
  prop = item.getProperty(ParametersDefinitionProperty.class)
  if(prop != null) {
    println(&quot;--- Parameters for &quot; + item.name + &quot; ---&quot;)
    for(param in prop.getParameterDefinitions()) {
      try {
        println(param.name + &quot; &quot; + param.defaultValue)
      }
      catch(Exception e) {
        println(param.name)
      }
    }
    println()
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h5 id=&quot;사용하는-빌드-단계별로-작업-그룹-표시&quot;&gt;사용하는 빌드 단계별로 작업 그룹 표시&lt;/h5&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;import hudson.model.*
import hudson.tasks.*

//All the projects on which we can apply the getBuilders method
def allProjects = Hudson.instance.items.findAll{ it instanceof Project }

//All the registered build steps in the current Jenkins Instance
def allBuilders = Builder.all()

//Group the projects by the build steps used
def projectsGroupByBuildSteps = allBuilders.inject([:]){
   map, builder -&amp;gt;   
   map[builder.clazz.name] = allProjects.findAll{it.builders.any{ it.class.name.contains(builder.clazz.name)}}.collect{it.name}
   map
}

//presentation
projectsGroupByBuildSteps.each{
   println &quot;&quot;&quot;--- $it.key ---
   \t$it.value\n&quot;&quot;&quot;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h5 id=&quot;모든-작업에-대해-알림에-사용되는-메일-수신자-목록-표시&quot;&gt;모든 작업에 대해 알림에 사용되는 메일 수신자 목록 표시&lt;/h5&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;import hudson.plugins.emailext.*
import hudson.model.*
import hudson.maven.*
import hudson.maven.reporters.*
import hudson.tasks.*

// For each project
for(item in Hudson.instance.items) {
 println(&quot;JOB : &quot;+item.name);
 // Find current recipients defined in project
 if(!(item instanceof ExternalJob)) {
 if(item instanceof MavenModuleSet) {
 println(&quot;&amp;gt;MAVEN MODULE SET&quot;);
 // Search for Maven Mailer Reporter
 println(&quot;&amp;gt;&amp;gt;Reporters&quot;);
 for(reporter in item.reporters) {
 if(reporter instanceof MavenMailer) {
 println(&quot;&amp;gt;&amp;gt;&amp;gt; reporter : &quot;+reporter+&quot; : &quot;+reporter.recipients);
 }
 }
 } else
 if(item instanceof FreeStyleProject) {
 println(&quot;&amp;gt;FREESTYLE PROJECT&quot;);
 }
 println(&quot;&amp;gt;&amp;gt;Publishers&quot;);
 for(publisher in item.publishersList) {
 // Search for default Mailer Publisher (doesn&apos;t exist for Maven projects)
 if(publisher instanceof Mailer) {
 println(&quot;&amp;gt;&amp;gt;&amp;gt; publisher : &quot;+publisher+&quot; : &quot;+publisher.recipients);
 } else
 // Or for Extended Email Publisher
 if(publisher instanceof ExtendedEmailPublisher) {
 println(&quot;&amp;gt;&amp;gt;&amp;gt; publisher : &quot;+publisher+&quot; : &quot;+publisher.recipientList);
 }
 }
 } else {
 println(&quot;External Jobs cannot have MailNotificationsRecipients&quot;)
 }
 println(&quot;\n=======\n&quot;);
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h5 id=&quot;jenkins는-모니터를-사용하여-다양한-동작을-검증-하나를-닫으면-jenkin는-다시-활성화하도록-제안하지-않음-스크립트-사용-시-모든-모니터-상태-확인-후-재활성화-가능&quot;&gt;Jenkins는 모니터를 사용하여 다양한 동작을 검증. 하나를 닫으면 Jenkin는 다시 활성화하도록 제안하지 않음. 스크립트 사용 시 모든 모니터 상태 확인 후 재활성화 가능&lt;/h5&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;hudson.model.Hudson.instance.administrativeMonitors.each{
    println &quot;* Monitor : &quot;+it.id
    println &quot;** Enabled : &quot;+it.enabled
    println &quot;** Activated : &quot;+it.activated
    println &quot;=========&quot;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h5 id=&quot;모든-작업에-대한-타이머-트리거-표시&quot;&gt;모든 작업에 대한 타이머 트리거 표시&lt;/h5&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;import hudson.model.*
import hudson.triggers.*

for(item in Hudson.instance.items) {
	for(trigger in item.triggers.values()) {
		if(trigger instanceof TimerTrigger) {
			println(&quot;--- Timer trigger for &quot; + item.name + &quot; ---&quot;)
			println(trigger.spec + &apos;\n&apos;)
		}
	}
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h5 id=&quot;모든-에이전트에서-jenkins-도구-위치-표시&quot;&gt;모든 에이전트에서 Jenkins 도구 위치 표시&lt;/h5&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;import hudson.model.*
import hudson.node_monitors.*
import hudson.slaves.*
import java.util.concurrent.*
import hudson.tools.ToolDescriptor;
import hudson.tools.ToolInstallation;
jenkins = Hudson.instance
  
TaskListener log;
  
def getEnviron(computer) {
   def env
   def thread = Thread.start(&quot;Getting env from ${computer.name}&quot;, { env = computer.environment })
   thread.join(2000)
   if (thread.isAlive()) thread.interrupt()
   env
}

def slaveAccessible(computer) {
    getEnviron(computer)?.get(&apos;PATH&apos;) != null
}

for (aSlave in jenkins.slaves) {
   def computer = aSlave.computer
  
     println &quot;Checking computer ${computer.name}:&quot;
     def isOK = (slaveAccessible(computer) &amp;amp;&amp;amp; !computer.offline)
     if (isOK) {

     
        for (ToolDescriptor&amp;lt;?&amp;gt; desc : ToolInstallation.all()) {
            for (ToolInstallation inst : desc.getInstallations()) {
                println (&apos;\tTool Name: &apos; + inst.getName());
                println (&apos;\t\tTool Home: &apos; + inst.translateFor(aSlave,log));
            }  
 }  
    } else {
        println &quot;  ERROR: can&apos;t get PATH from slave: node is offline.&quot;
    }       
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h5 id=&quot;서버의-모든-작업에서-타임스탬퍼-플러그인-활성화&quot;&gt;서버의 모든 작업에서 타임스탬퍼 플러그인 활성화&lt;/h5&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;for (item in Hudson.instance.items) {
  println(&quot;\njob: $item.name&quot;)
  hasTimestamper = false;
  item.buildWrappersList.each {
    if (it instanceof hudson.plugins.timestamper.TimestamperBuildWrapper) {
      hasTimestamper = true;
    }
  }
  if (!hasTimestamper) {
    println(&quot;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; Adding timestamper right to $item.name&quot;)
    item.buildWrappersList.add(new hudson.plugins.timestamper.TimestamperBuildWrapper());
    item.save()
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h5 id=&quot;실패한-모든-작업-목록-표시&quot;&gt;실패한 모든 작업 목록 표시&lt;/h5&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;// Get the list of failed jobs
activeJobs = hudson.model.Hudson.instance.items.findAll{job -&amp;gt; job.isBuildable()}
failedRuns = activeJobs.findAll{job -&amp;gt; job.lastBuild != null &amp;amp;&amp;amp; job.lastBuild.result == hudson.model.Result.FAILURE}
// Do something with them - e.g. listing them
failedRuns.each{run -&amp;gt; println(run.name)}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h5 id=&quot;--addon-restart&quot;&gt;&amp;gt;  Addon: Restart&lt;/h5&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;startServer = &quot;admin computer&quot;
startNote   = &quot;bulk start&quot;
cause = new hudson.model.Cause.RemoteCause(startServer, startNote)
failedRuns.each{run -&amp;gt; run.scheduleBuild(cause)}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h5 id=&quot;현재-실행-중이며-n초-이상-실행된-빌드-찾기&quot;&gt;현재 실행 중이며 N초 이상 실행된 빌드 찾기&lt;/h5&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;int MAX_ALLOWED_DURATION_IN_SECONDS = 3600 * 6 // 6 hours


  def busyExecutors = Jenkins.instance.computers
                                .collect { 
                                  c -&amp;gt; c.executors.findAll { it.isBusy() }
                                }
                                .flatten() // reminder: transforms list(list(executor)) into list(executor)

def ok = true

println &quot;Busy Executors list&quot;
busyExecutors.each { e -&amp;gt; 
  println e ; 
  int durationInSeconds = (System.currentTimeMillis() - e.executable.getTimeInMillis())/1000.0
  
  if(durationInSeconds &amp;gt; MAX_ALLOWED_DURATION_IN_SECONDS )
  {
    ok = false;
  }
  println &quot;\t duration=$durationInSeconds&quot;
  println &quot;&quot; 
}

println &quot;Done&quot;

return ok
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h5 id=&quot;빌드-권한이-있는-사용자-및-그룹에-취소-권한-부여&quot;&gt;빌드 권한이 있는 사용자 및 그룹에 취소 권한 부여&lt;/h5&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;import hudson.security.*
import jenkins.security.*
import jenkins.model.Jenkins


boolean dryrun=true

if (dryrun) {
  println &apos;&apos;.center(100,&apos;!&apos;)
  println &apos;This is a dryrun, nothing will be changed&apos;.center(100,&apos;!&apos;)
  println &apos;Change this line: boolean dryrun=false to boolean dryrun=true to make the real change&apos;.center(100,&apos;!&apos;)
  println &apos;&apos;.center(100,&apos;!&apos;)
}

switch (Jenkins.instance.authorizationStrategy){
  case GlobalMatrixAuthorizationStrategy:
    println &apos;\nGlobal Matrix Strategy defined. Fixing Cancel permissions...\n&apos;
    def sids = Jenkins.instance.authorizationStrategy.getAllSIDs().plus(&apos;anonymous&apos;)
    for (sid in sids){
      if (Jenkins.instance.authorizationStrategy.hasPermission(sid,hudson.model.Item.BUILD)){
        println &apos;----&apos;+sid+&apos; has Build permission and Cancel permission will be add&apos;
        if (!dryrun) Jenkins.instance.authorizationStrategy.add(hudson.model.Item.CANCEL,sid)
      }
    }
    if (!dryrun) Jenkins.instance.save()
  case ProjectMatrixAuthorizationStrategy:
    println &apos;\nProject Matrix Strategy defined. fixing Cancel permissions...\n&apos;
    def jobs = Jenkins.instance.items
    jobs.each {
      println it.name.center(80,&apos;-&apos;)
      def authorizationMatrixProperty = it.getProperty(AuthorizationMatrixProperty.class)
      def sids = authorizationMatrixProperty?.getAllSIDs().plus(&apos;anonymous&apos;)
      for (sid in sids){
        if (authorizationMatrixProperty?.hasPermission(sid,hudson.model.Item.BUILD)){
          println &apos;&apos;+sid+&apos; has Build permission and Cancel permission will be add&apos;
          if (!dryrun) authorizationMatrixProperty?.add(hudson.model.Item.CANCEL,sid)
        }
      }
      if (!dryrun) it.save()
    }
    break
  default:
    println &quot;No permission need to be mofdified gloabally&quot;
    break
}

return
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h5 id=&quot;jenkins-http-세션-무효화&quot;&gt;Jenkins HTTP 세션 무효화&lt;/h5&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicInteger;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionActivationListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
import net.bull.javamelody.*;
  
def chuck = SessionListener.newInstance();
println (&quot;Session Info: &quot;);
println chuck.getAllSessionsInformations();
sessionCount = chuck.getSessionCount();
println (&quot;Number of Session: &quot; + sessionCount);
maxSessionCount = 70;
if ( sessionCount &amp;gt; maxSessionCount ) {
          println (&quot;Open Session &quot; + sessionCount + &quot; more than &quot; + maxSessionCount);
          println &quot;Invalidating...&quot;;
          chuck.invalidateAllSessions();
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h5 id=&quot;모든-작업에서-수동으로-로그-회전-실행&quot;&gt;&lt;a href=&quot;https://www.jenkins.io/doc/book/managing/nodes/&quot;&gt;모든 작업에서 수동으로 로그 회전 실행&lt;/a&gt;&lt;/h5&gt;

&lt;h5 id=&quot;수동으로-연결이-끊어지지-않은-경우-오프라인-노드를-모니터링-후-다시-시작&quot;&gt;수동으로 연결이 끊어지지 않은 경우 오프라인 노드를 모니터링 후 다시 시작&lt;/h5&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;//michaeldkfowler
import jenkins.model.*
Jenkins.instance.getAllItems(AbstractProject.class)
.findAll { it.logRotator }
    .each {
      it.logRotator.perform(it)
    }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h5 id=&quot;모니터링-플러그인-사용-시-http-세션-스레드-메모리-jvm-또는-mbean에-대한-데이터를-표시하는-여러-스크립트&quot;&gt;모니터링 플러그인 사용 시 http 세션, 스레드, 메모리, JVM 또는 MBean에 대한 데이터를 표시하는 &lt;a href=&quot;https://wiki.jenkins.io/display/JENKINS/Monitoring+Scripts&quot;&gt;여러 스크립트&lt;/a&gt;&lt;/h5&gt;

&lt;h5 id=&quot;매개변수화된-시스템-groovy-script&quot;&gt;매개변수화된 시스템 Groovy Script&lt;/h5&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;import hudson.model.*

// get current thread / Executor
def thr = Thread.currentThread()
// get current build
def build = thr?.executable


// get parameters
def parameters = build?.actions.find{ it instanceof ParametersAction }?.parameters
parameters.each {
   println &quot;parameter ${it.name}:&quot;
   println it.dump()
   println &quot;-&quot; * 80
}


// ... or if you want the parameter by name ...
def hardcoded_param = &quot;FOOBAR&quot;
def resolver = build.buildVariableResolver
def hardcoded_param_value = resolver.resolve(hardcoded_param)


println &quot;param ${hardcoded_param} value : ${hardcoded_param_value}&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h5 id=&quot;maven-release-build에서-사용자-이름-미리-선택&quot;&gt;Maven release build에서 사용자 이름 미리 선택&lt;/h5&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;import hudson.model.*
import hudson.maven.*
import hudson.tasks.*
import org.jvnet.hudson.plugins.m2release.*

for(item in Hudson.instance.items) {
  if (item instanceof MavenModuleSet)
  {
    println(&quot;\njob $item.name &quot;);
    rw = item.getBuildWrappers().get(M2ReleaseBuildWrapper.class);
    if (rw == null)
    {
      println(&quot;release build not configured&quot;);
    }
    else 
    {
     println(&quot;append Username: &quot;+rw.isSelectAppendHudsonUsername())
     rw.setSelectAppendHudsonUsername(true)
     item.save()
    }
  }  
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h5 id=&quot;자격-증명-및-해당-id-목록-인쇄&quot;&gt;자격 증명 및 해당 ID 목록 인쇄&lt;/h5&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  def creds = com.cloudbees.plugins.credentials.CredentialsProvider.lookupCredentials(
      com.cloudbees.plugins.credentials.common.StandardUsernameCredentials.class,
      Jenkins.instance,
      null,
      null
  );
  for (c in creds) {
       println(c.id + &quot;: &quot; + c.description)
  }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h5 id=&quot;maven-작업에서-비활성화된-모든-모듈-제거&quot;&gt;Maven 작업에서 비활성화된 모든 모듈 제거&lt;/h5&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Jenkins.instance.getAllItems(hudson.maven.MavenModuleSet.class).findAll{job -&amp;gt; job.isBuildable()}.each{
job -&amp;gt;
  job.getDisabledModules(true).each{module -&amp;gt; module.delete()} 
  println(job.name+&quot; cleaned&quot;)
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h5 id=&quot;artifact-deployer-플러그인이-각-빌드에-대해-불필요하게-저장한-배포된-artifact-목록-제거&quot;&gt;Artifact Deployer 플러그인이 각 빌드에 대해 불필요하게 저장한 배포된 Artifact 목록 제거&lt;/h5&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;import hudson.model.*

hudsonInstance = hudson.model.Hudson.instance
allItems = hudsonInstance.items

// Iterate over all jobs and find the ones that have a org.jenkinsci.plugins.artifactdeployer.DeployedArtifacts
// as an action.

def jobCounter = 0;
def totalBuildCounter = 0;

for (job in allItems) {
  def buildCounter = 0;
  for (build in job.getBuilds()) {
    // It is possible for a build to have multiple actions
    def adActions = build.getActions(org.jenkinsci.plugins.artifactdeployer.DeployedArtifacts.class)
    if (adActions != null &amp;amp;&amp;amp; !adActions.isEmpty()) {
      for (action in adActions) {
        build.actions.remove(action)
      }
      build.save();
      buildCounter++;
    }
  }
  if (buildCounter &amp;gt; 0) {
      println(&quot;Job: &quot; + job.name + &quot; cleaned &quot; + buildCounter + &quot; builds&quot;);
      jobCounter++;
      totalBuildCounter += buildCounter;
  }  
}

println(&quot;Cleaned &quot; + jobCounter + &quot; jobs and a total of &quot; + totalBuildCounter + &quot; builds&quot;);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h5 id=&quot;git-플러그인이-각-빌드에-대해-불필요하게-저장한-buildsbybranch의-정적-목록-제거&quot;&gt;&lt;a href=&quot;https://plugins.jenkins.io/git/&quot;&gt;Git 플러그인이 각 빌드에 대해 불필요하게 저장한 BuildsByBranch의 정적 목록 제거&lt;/a&gt;&lt;/h5&gt;

&lt;h5 id=&quot;모든-저장소에-대한-사용자-정의-설정으로-gitblitrepositorybrowser-설정&quot;&gt;모든 저장소에 대한 사용자 정의 설정으로 GitBlitRepositoryBrowser 설정&lt;/h5&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;import hudson.model.*
import hudson.triggers.*
import hudson.plugins.git.browser.GitBlitRepositoryBrowser

// you might want to change here
def url = &apos;https://mygitblitserver/gitblit/&apos;
def i = 0
for(item in Hudson.instance.items) {
  def scm = item.scm
  if((scm instanceof hudson.plugins.git.GitSCM) &amp;amp;&amp;amp; !(scm.browser instanceof GitBlitRepositoryBrowser)) {
    println(&apos;##########&apos;)
    println(scm.dump())
    // you might want to change here
    def match = scm.userRemoteConfigs =~ /\/spu\/test\/git\/(.*?.git)/
    if(match) {
      i++
      def projectName = match[0][1]
      println projectName
      scm.browser = new GitBlitRepositoryBrowser(url, projectName)
    }
  }
}
println(&quot;$i projects updated&quot;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h5 id=&quot;빌드-후-단계를-설치하고-활성화하여-배포-목표가-있는-모든-maven-작업-업데이트&quot;&gt;빌드 후 단계를 설치하고 활성화하여 배포 목표가 있는 모든 Maven 작업 업데이트&lt;/h5&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;import java.util.*
import hudson.model.*
import hudson.maven.*
import hudson.maven.reporters.*
import hudson.matrix.*
import hudson.tasks.*

hudson.model.Hudson.instance.items.findAll{job -&amp;gt; job.isBuildable() &amp;amp;&amp;amp; job instanceof MavenModuleSet}.each {
job -&amp;gt; 
  println(job.name)
  if (job.goals.indexOf(&quot;deploy&quot;)&amp;gt;0) {
    println(&quot;* Must update goals (deploy -&amp;gt; install) : &quot; + job.goals)
    def newGoals = job.goals.replaceAll(&quot;deploy&quot;, &quot;install&quot;);
    println(&quot;* New goals : &quot; + newGoals)
    // Comment the 3 following lines for a first run to check goals modifications without modifying anything
    job.goals = newGoals
    job.archivingDisabled = false // It is necessary to archive artifacts to deploy them after the build
    job.publishers.replace(new hudson.maven.RedeployPublisher(null, null, true, false));
    println(&quot;* Redeploy publisher added&quot;);
  } else {
    println(&quot;* This maven job doesn&apos;t deploy its artifacts&quot;);
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h5 id=&quot;svn-브라우저-업데이트&quot;&gt;SVN 브라우저 업데이트&lt;/h5&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;import hudson.model.*
import hudson.maven.*
import hudson.tasks.*
import hudson.scm.*
import hudson.scm.browsers.*

for(item in Hudson.instance.items) {
  hasClaim = false;
  if (item.scm instanceof SubversionSCM)
  {
      println(&quot;\njob $item.name&quot;)
      println(item.scm.browser);
      if (item.scm.browser instanceof Sventon2)
      {
        println(item.scm.browser.url);
        println(item.scm.browser.repositoryInstance);
      }
      else
      {
        // add the repo browser details.
        browser = new hudson.scm.browsers.Sventon2(new URL(&quot;http://...../&quot;), &quot;.....&quot;)

        // unfortunately can&apos;t just add a browser - need to create a new scm entry, which is complex...
        scm = new  SubversionSCM(Arrays.asList(item.scm.locations), item.scm.workspaceUpdater, browser, item.scm.excludedRegions, item.scm.excludedUsers, item.scm.excludedRevprop, item.scm.excludedCommitMessages, item.scm.includedRegions, item.scm.ignoreDirPropChanges)

        item.scm = scm
        item.save()
        println(&quot;Updated repo browser&quot;);
      }
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h5 id=&quot;jenkins-서버에-있는-모든-작업의-작업-공간-제거&quot;&gt;Jenkins 서버에 있는 모든 작업의 작업 공간 제거&lt;/h5&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;import hudson.model.*
// For each project
for(item in Hudson.instance.items) {
  // check that job is not building
  if(!item.isBuilding()) {
    println(&quot;Wiping out workspace of job &quot;+item.name)
    item.doDoWipeOutWorkspace()
  }
  else {
    println(&quot;Skipping job &quot;+item.name+&quot;, currently building&quot;)
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h5 id=&quot;모든-노드에-있는-특정-작업의-작업-공간-지우기&quot;&gt;모든 노드에 있는 특정 작업의 작업 공간 지우기&lt;/h5&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;import hudson.model.*
// For each job
for (item in Hudson.instance.items)
{
  jobName = item.getFullDisplayName()
  // check that job is not building
  if (!item.isBuilding())
  {
    // TODO: Modify the following condition to select which jobs to affect
    if (jobName == &quot;MyJob&quot;)
    {
      println(&quot;Wiping out workspaces of job &quot; + jobName)
      customWorkspace = item.getCustomWorkspace()
      println(&quot;Custom workspace = &quot; + customWorkspace)

      for (node in Hudson.getInstance().getNodes())
      {
        println(&quot;  Node: &quot; + node.getDisplayName())
        workspacePath = node.getWorkspaceFor(item)
        if (workspacePath == null)
        {
          println(&quot;    Could not get workspace path&quot;)
        }
        else
        {
          if (customWorkspace != null)
          {
            workspacePath = node.getRootPath().child(customWorkspace)
          }

          pathAsString = workspacePath.getRemote()
          if (workspacePath.exists())
          {
            workspacePath.deleteRecursive()
            println(&quot;    Deleted from location &quot; + pathAsString)
          }
          else
          {
            println(&quot;    Nothing to delete at &quot; + pathAsString)
          }
        }
      }
    }
  }
  else
  {
    println(&quot;Skipping job &quot; + jobName + &quot;, currently building&quot;)
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Thu, 09 Nov 2023 00:00:00 +0900</pubDate>
        <link>https://oblsoun.github.io/2023-11/study-groovyScriptEx</link>
        <guid isPermaLink="true">https://oblsoun.github.io/2023-11/study-groovyScriptEx</guid>
        
        
        <category>Study</category>
        
      </item>
    
      <item>
        <title>Groovy 사용을 가능하게 하는 플러그인</title>
        <description>&lt;h4 id=&quot;개요&quot;&gt;개요&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;#개요&quot;&gt;개요&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#구성-파일-제공자-플러그인&quot;&gt;구성 파일 제공자 플러그인&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#글로벌-포스트-스크립트-플러그인&quot;&gt;글로벌 포스트 스크립트 플러그인&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#groovy-플러그인&quot;&gt;Groovy 플러그인&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#groovy-postbuild-플러그인&quot;&gt;Groovy Postbuild 플러그인&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#groovy-remote-control-플러그인&quot;&gt;Groovy Remote Control 플러그인&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#matrix-groovy-execution-strategy-플러그인&quot;&gt;Matrix Groovy Execution Strategy 플러그인&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#scriptler-플러그인&quot;&gt;Scriptler 플러그인&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;구성-파일-제공자-플러그인&quot;&gt;&lt;a href=&quot;https://plugins.jenkins.io/config-file-provider&quot;&gt;구성 파일 제공자 플러그인&lt;/a&gt;&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;Jenkins UI를 통해 로드된 구성파일(ex. Maven, XML, Groovy, 사용자 정의 파일 등에 대한 settings.xml)을 제공하는 기능 추가&lt;/li&gt;
  &lt;li&gt;이 파일은 작업의 작업공간에 복사&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;글로벌-포스트-스크립트-플러그인&quot;&gt;&lt;a href=&quot;https://plugins.jenkins.io/global-post-script/&quot;&gt;글로벌 포스트 스크립트 플러그인&lt;/a&gt;&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;Jenkins가 관리하는 각 작업을 빌드 후에 글로벌로 구성된 Groovy Script 실행&lt;/li&gt;
  &lt;li&gt;동일한 Jenkins가 관리하는 다운스트림 작업을 트리거하거나 매개변수화된 작업에 전달된 매개변수를 기반으로 하는 원격 작업을 트리거하는 등 공유 매개변수 세트를 기반으로 작업을 수행해야 하는 경우&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;groovy-플러그인&quot;&gt;&lt;a href=&quot;https://plugins.jenkins.io/groovy/&quot;&gt;Groovy 플러그인&lt;/a&gt;&lt;/h4&gt;

&lt;h4 id=&quot;groovy-postbuild-플러그인&quot;&gt;&lt;a href=&quot;https://plugins.jenkins.io/groovy-postbuild&quot;&gt;Groovy Postbuild 플러그인&lt;/a&gt;&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;Jenkins JVM에서 Groovy Script 실행&lt;/li&gt;
  &lt;li&gt;일부 조건 확인 후 빌드 결과 변경, 빌드 기록에서 빌드 옆에 배지를 표시하거나 빌드 요약 페이지에 정보 표시&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;groovy-remote-control-플러그인&quot;&gt;&lt;a href=&quot;https://plugins.jenkins.io/groovy-remote&quot;&gt;Groovy Remote Control 플러그인&lt;/a&gt;&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://groovy.codehaus.org/modules/remote/&quot;&gt;Groovy Remote Control&lt;/a&gt; 수신기를 제공하고 Jenkins에서 외부 애플리케이션 제어 가능하게 해&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;matrix-groovy-execution-strategy-플러그인&quot;&gt;&lt;a href=&quot;https://plugins.jenkins.io/matrix-groovy-execution-strategy&quot;&gt;Matrix Groovy Execution Strategy 플러그인&lt;/a&gt;&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;매트릭스 프로젝트의 실행 순서와 유효한 조합을 결정&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;scriptler-플러그인&quot;&gt;&lt;a href=&quot;https://plugins.jenkins.io/scriptler&quot;&gt;Scriptler 플러그인&lt;/a&gt;&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;Scriptler 사용 시 Groovy Script를 저장/편집하고 모든 노드에서 실행 가능&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Thu, 09 Nov 2023 00:00:00 +0900</pubDate>
        <link>https://oblsoun.github.io/2023-11/study-groovyPlugin</link>
        <guid isPermaLink="true">https://oblsoun.github.io/2023-11/study-groovyPlugin</guid>
        
        
        <category>Study</category>
        
      </item>
    
      <item>
        <title>Jenkins Script Console</title>
        <description>&lt;h4 id=&quot;개요&quot;&gt;개요&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;#개요&quot;&gt;개요&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#Jenkins-Script-Console&quot;&gt;Jenkins Script Console&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#다중-컨텍스트&quot;&gt;다중 컨텍스트&lt;/a&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#컨트롤러에서-스크립트-콘솔-실행&quot;&gt;컨트롤러에서 스크립트 콘솔 실행&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#에이전트에서-스크립트-콘솔-실행&quot;&gt;에이전트에서 스크립트 콘솔 실행&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#에이전트의-컨트롤러-스크립트-콘솔에서-스크립트-실행&quot;&gt;에이전트의 컨트롤러 스크립트 콘솔에서 스크립트 실행&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#파일-읽기-및-쓰기&quot;&gt;파일 읽기 및 쓰기&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#원격-액세스&quot;&gt;원격 액세스&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#제출할-스크립트-콘솔의-단축키&quot;&gt;제출할 스크립트 콘솔의 단축키&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#비디오-튜토리얼-및-추가-학습-자료&quot;&gt;비디오 튜토리얼 및 추가 학습 자료&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;jenkins-script-console&quot;&gt;Jenkins Script Console&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;액세스는 권한에 따라 제어됨(Administer)&lt;/li&gt;
  &lt;li&gt;Jenkins 런타임에 대한 웹 기반 Groovy Shell&lt;/li&gt;
  &lt;li&gt;Groovy: 자바가 할 수 있는 거의 모든 작업을 수행할 수 있는 기능을 제공하는 언어
    &lt;blockquote&gt;
      &lt;ul&gt;
        &lt;li&gt;Jenkins 컨트롤러 및 에이전트에서 하위 프로세스를 생성, 임의 명령 실행&lt;/li&gt;
        &lt;li&gt;Jenkins 컨트롤러가 호스트에서 액세스할 수 있는 파일(ex. /etc/passwd:) 읽기 가능&lt;/li&gt;
        &lt;li&gt;Jenkins 내 구성된 자격 증명 해독&lt;/li&gt;
      &lt;/ul&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
  &lt;li&gt;Jenkins 인프라의 모든 부분에 영향을 주지 않도록 스크립트 콘솔을 실행할 수 있는 사용자(또는 관리자)를 중지하는 관리 제어 기능을 제공하지 않음
    &lt;blockquote&gt;
      &lt;ul&gt;
        &lt;li&gt;일반 Jenkins 사용자에게 스크립트 콘솔 액세스 권한을 부여하는 것은 기본적으로 Jenkins 내에서 관리자 권한을 부여하는 것과 동일&lt;/li&gt;
      &lt;/ul&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
  &lt;li&gt;Jenkins 설정 구성 가능
    &lt;blockquote&gt;
      &lt;ul&gt;
        &lt;li&gt;보안을 비활성화, 보안 재구성, Jenkins 프로세스 외부에서 호스트 운영 체제의 백도어 열기 가능&lt;/li&gt;
        &lt;li&gt;많은 조직이 인프라에서 Jenkins를 중요하게 생각하기 때문에 공격자가 노력하지 않아도 인프라 내에서 수평으로 이동 가능하기 때문에 중요함&lt;/li&gt;
      &lt;/ul&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
  &lt;li&gt;원래 Jenkins 개발자를 위한 디버깅 인터페이스로 의도되었지만 이후 Jenkins 관리자가 Jenkins를 구성하고 Jenkins 런타임 문제를 디버깅하는 데 사용하는 인터페이스로 성장했기 때문에 매우 강력&lt;/li&gt;
  &lt;li&gt;Jenkins Script Console이 제공하는 기능으로 인해 Jenkins와 해당 에이전트는 root 사용자(Linux) 또는 다른 OS의 시스템 관리자로 실행되어서는 안 됨&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;다중-컨텍스트&quot;&gt;다중 컨텍스트&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;Jenkins Script Console은 컨트롤러나 구성된 에이전트에서 실행 가능&lt;/li&gt;
&lt;/ul&gt;

&lt;h5 id=&quot;컨트롤러에서-스크립트-콘솔-실행&quot;&gt;컨트롤러에서 스크립트 콘솔 실행&lt;/h5&gt;
&lt;ul&gt;
  &lt;li&gt;Jenkins 관리 &amp;gt; 스크립트 콘솔 접근 가능&lt;/li&gt;
  &lt;li&gt;/script 또는 Jenkins 인스턴스의 하위 URL 방문&lt;/li&gt;
&lt;/ul&gt;

&lt;h5 id=&quot;에이전트에서-스크립트-콘솔-실행&quot;&gt;에이전트에서 스크립트 콘솔 실행&lt;/h5&gt;
&lt;ul&gt;
  &lt;li&gt;Jenkins 관리 &amp;gt; 노드 관리 방문&lt;/li&gt;
  &lt;li&gt;상태 페이지를 보려면 노드 선택&lt;/li&gt;
  &lt;li&gt;왼쪽 메뉴에는 해당 특정 에이전트의 “스크립트 콘솔”을 열 수 있는 메뉴 항목 존재&lt;/li&gt;
&lt;/ul&gt;

&lt;h5 id=&quot;에이전트의-컨트롤러-스크립트-콘솔에서-스크립트-실행&quot;&gt;에이전트의 컨트롤러 스크립트 콘솔에서 스크립트 실행&lt;/h5&gt;
&lt;ul&gt;
  &lt;li&gt;개별 에이전트의 컨트롤러 스크립트 콘솔에서 스크립트 실행 가능&lt;/li&gt;
  &lt;li&gt;마스터 스크립트 콘솔의 에이전트에서 스크립트 실행&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;// 예시

import hudson.util.RemotingDiagnostics
import jenkins.model.Jenkins

String agentName = &apos;your agent name&apos;
//groovy script you want executed on an agent
groovy_script = &apos;&apos;&apos;
println System.getenv(&quot;PATH&quot;)
println &quot;uname -a&quot;.execute().text
&apos;&apos;&apos;.trim()

String result
Jenkins.instance.slaves.find { agent -&amp;gt;
    agent.name == agentName
}.with { agent -&amp;gt;
    result = RemotingDiagnostics.executeGroovy(groovy_script, agent.channel)
}
println result
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h5 id=&quot;파일-읽기-및-쓰기&quot;&gt;파일 읽기 및 쓰기&lt;/h5&gt;
&lt;ul&gt;
  &lt;li&gt;컨트롤러 스크립트 콘솔을 통해 컨트롤러나 에이전트에서 직접 파일을 읽고 쓰기 가능&lt;/li&gt;
  &lt;li&gt;Jenkins 컨트롤러에 파일 쓰기&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;new File(&apos;/tmp/file.txt&apos;).withWriter(&apos;UTF-8&apos;) { writer -&amp;gt;
    try {
        writer &amp;lt;&amp;lt; &apos;hello world\n&apos;
    } finally {
        writer.close()
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;Jenkins 컨트롤러에서 파일 읽기&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;new File(&apos;/tmp/file.txt&apos;).text
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;에이전트 채널을 통해 에이전트에 파일 쓰기&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;import hudson.FilePath
import hudson.remoting.Channel
import jenkins.model.Jenkins

String agentName = &apos;some-agent&apos;
String filePath = &apos;/tmp/file.txt&apos;

Channel agentChannel = Jenkins.instance.slaves.find { agent -&amp;gt;
    agent.name == agentName
}.channel

new FilePath(agentChannel, filePath).write().with { os -&amp;gt;
    try {
        os &amp;lt;&amp;lt; &apos;hello world\n&apos;
    } finally {
        os.close()
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;에이전트 채널을 통해 에이전트에서 파일 읽기&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;import hudson.FilePath
import hudson.remoting.Channel
import jenkins.model.Jenkins

import java.io.BufferedReader
import java.io.InputStreamReader
import java.nio.charset.StandardCharsets
import java.util.stream.Collectors

String agentName = &apos;some-agent&apos;
String filePath = &apos;/tmp/file.txt&apos;

Channel agentChannel = Jenkins.instance.slaves.find { agent -&amp;gt;
    agent.name == agentName
}.channel

String fileContents = &apos;&apos;
new FilePath(agentChannel, filePath).read().with { is -&amp;gt;
    try {
        fileContents = new BufferedReader(
            new InputStreamReader(is, StandardCharsets.UTF_8))
                .lines()
                .collect(Collectors.joining(&quot;\n&quot;))
    } finally {
        is.close()
    }
}

// print contents of the file from the agent
println &apos;===&apos;
println(fileContents)
println &apos;===&apos;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;원격-액세스&quot;&gt;원격 액세스&lt;/h4&gt;
&lt;p&gt;Jenkins 관리자는 HTTP POST 요청을 /script/url 또는 /scriptText/.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Bash를 통한 curl 예제&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;curl -d &quot;script=&amp;lt;your_script_here&amp;gt;&quot; https://jenkins/script
# or to get output as a plain text result (no HTML)
curl -d &quot;script=&amp;lt;your_script_here&amp;gt;&quot; https://jenkins/scriptText
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;bash를 통해 Groovy 파일을 제출하는 Curl&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;curl --data-urlencode &quot;script=$(&amp;lt; ./somescript.groovy)&quot; https://jenkins/scriptText
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;bash를 통해 사용자 이름과 API 토큰을 제공하는 Groovy 파일을 제출하는 Curl&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;curl --user &apos;username:api-token&apos; --data-urlencode \
  &quot;script=$(&amp;lt; ./somescript.groovy)&quot; https://jenkins/scriptText
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;사용자 이름과 API 토큰을 제공하는 그루비 파일을 제출하는 Python&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;with open(&apos;somescript.groovy&apos;, &apos;r&apos;) as fd:
    data = fd.read()
r = requests.post(&apos;https://jenkins/scriptText&apos;, auth=(&apos;username&apos;, &apos;api-token&apos;), data={&apos;script&apos;: data})
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;제출할-스크립트-콘솔의-단축키&quot;&gt;제출할 스크립트 콘솔의 단축키&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;윈도우/리눅스: Ctrl + Enter&lt;/li&gt;
  &lt;li&gt;맥: Command + Enter&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;비디오-튜토리얼-및-추가-학습-자료&quot;&gt;비디오 튜토리얼 및 추가 학습 자료&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;Jenkins Script Console 녹화 영상
    &lt;blockquote&gt;
      &lt;ul&gt;
        &lt;li&gt;&lt;a href=&quot;https://youtu.be/qaUPESDcsGg?feature=shared&quot;&gt;Jenkins World 2017: Jenkins Script Console 마스터하기&lt;/a&gt; - 44분 - 샘플 사용 및 보안 토론&lt;/li&gt;
        &lt;li&gt;&lt;a href=&quot;[https://www.youtube.com/watch?v=T1x2kCGRY1w](https://youtu.be/T1x2kCGRY1w?feature=shared)https://youtu.be/T1x2kCGRY1w?feature=shared&quot;&gt;LA Jenkins Area Meetup 2016 - Jenkins 내부 해킹 - Jenkins 스크립트 콘솔&lt;/a&gt; - 39분 - 샘플 사용&lt;/li&gt;
      &lt;/ul&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
  &lt;li&gt;Script Console에서 스크립트 작성 능력 확장
    &lt;blockquote&gt;
      &lt;ul&gt;
        &lt;li&gt;&lt;a href=&quot;https://groovy-lang.org/learn.html&quot;&gt;Groovy 배우기&lt;/a&gt; / &lt;a href=&quot;https://www.jenkins.io/doc/book/pipeline/&quot;&gt;Groovy Pipeline 및 공유 Pipeline Library&lt;/a&gt; / &lt;a href=&quot;https://plugins.jenkins.io/groovy/&quot;&gt;Groovy 플러그인&lt;/a&gt; / &lt;a href=&quot;https://plugins.jenkins.io/job-dsl/&quot;&gt;Job DSL 플러그인&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&quot;https://www.mdoninger.de/2011/11/07/write-groovy-scripts-for-jenkins-with-code-completion.html&quot;&gt;코드 완성 기능을 갖춘 Jenkins용 Groovy Script 작성&lt;/a&gt;
          &lt;blockquote&gt;
            &lt;ul&gt;
              &lt;li&gt;IDE 내에서 Maven 프로젝트 생성&lt;/li&gt;
              &lt;li&gt;org.jenkins-ci.main:jenkins-core(및 현재 예상되는 기타 플러그인)에 의존&lt;/li&gt;
              &lt;li&gt;Jenkins API 개체 및 메서드의 코드 완성 기능을 사용하여 Groovy Script 작성 가능&lt;/li&gt;
            &lt;/ul&gt;
          &lt;/blockquote&gt;
        &lt;/li&gt;
      &lt;/ul&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Sat, 04 Nov 2023 00:00:00 +0900</pubDate>
        <link>https://oblsoun.github.io/2023-11/study-jenkinsScriptConsole</link>
        <guid isPermaLink="true">https://oblsoun.github.io/2023-11/study-jenkinsScriptConsole</guid>
        
        
        <category>Study</category>
        
      </item>
    
      <item>
        <title>Jenkins Pipeline</title>
        <description>&lt;h4 id=&quot;개요&quot;&gt;개요&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;#개요&quot;&gt;개요&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#정의&quot;&gt;정의&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#역할&quot;&gt;역할&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#목적&quot;&gt;목적&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#pipeline-생성-방법&quot;&gt;Pipeline 생성 방법&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#jenkins-file-작성-방법&quot;&gt;Jenkins File 작성 방법&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#scripted-pipeline&quot;&gt;Scripted Pipeline&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#pipeline-생성-방법-1&quot;&gt;Pipeline 생성 방법&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h4 id=&quot;정의&quot;&gt;정의&lt;/h4&gt;
&lt;p&gt;젠킨스의 플러그인&lt;/p&gt;

&lt;h4 id=&quot;역할&quot;&gt;역할&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;연속적인 이벤트&lt;/li&gt;
  &lt;li&gt;Job의 그룹 실행&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;목적&quot;&gt;목적&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;단순한 Job들이 많아지는 경우 Job을 관리하기 어려움&lt;/li&gt;
  &lt;li&gt;Pipeline으로 작성 시 하나의 Job으로 묶으면 관리하기 편함&lt;/li&gt;
  &lt;li&gt;진행 상황, 직관적인 파악 가능&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;pipeline-생성-방법&quot;&gt;Pipeline 생성 방법&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;WEB UI를 통해 Job 구성에서 Script 코드 작성&lt;/li&gt;
  &lt;li&gt;SCM을 이용해 Jenkinsfile에 DSL(Domain-Specific Language)로 작성된 스크립트 코드 작성 필요&lt;/li&gt;
  &lt;li&gt;Blueocean 플러그인으로 UI를 통해 스크립트 코드 작성&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;jenkins-file-작성-방법&quot;&gt;Jenkins File 작성 방법&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;Groovy Script로 작성&lt;/li&gt;
  &lt;li&gt;Declarative Pipeline
    &lt;blockquote&gt;
      &lt;ul&gt;
        &lt;li&gt;Scripted Pipeline보다 쉽게 작성 가능&lt;/li&gt;
        &lt;li&gt;Groovy 문법 기반&lt;/li&gt;
        &lt;li&gt;최상단에 pipeline이라고 되어 있으면 declarative 문법으로 작성된 것&lt;/li&gt;
      &lt;/ul&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
  &lt;li&gt;Scripted Pipeline
    &lt;blockquote&gt;
      &lt;ul&gt;
        &lt;li&gt;Declarative보다 효과적이고 많은 기능 포함 작성 가능&lt;/li&gt;
        &lt;li&gt;Groovy 문법 기반&lt;/li&gt;
        &lt;li&gt;최상단에 node 지시어가 있으면 scripted 문법으로 작성된 것&lt;/li&gt;
      &lt;/ul&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
  &lt;li&gt;Declarative Pipeline와 Scripted Pipeline 동시 작성 불가&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;scripted-pipeline&quot;&gt;Scripted Pipeline&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Directive(지시어)&lt;/strong&gt;
    &lt;blockquote&gt;
      &lt;ul&gt;
        &lt;li&gt;node: Scripted Pipeline을 실행하는 Jenkins 에이전트 / 최상단에 선언&lt;/li&gt;
        &lt;li&gt;dir: 명령어를 수행할 directory(폴더) 정의&lt;/li&gt;
        &lt;li&gt;stage: 파이프라인 각 단계, 어떤 작업을 할지 선언(작업 내용 작성)&lt;/li&gt;
        &lt;li&gt;git: git 원격 저장소에서 프로젝트 clone&lt;/li&gt;
        &lt;li&gt;sh: unix 환경에서 실행할 명령어 실행(윈도우: bat)&lt;/li&gt;
        &lt;li&gt;def: groovy 변수, 함수 선언(javascript에서 var)&lt;/li&gt;
      &lt;/ul&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;작성 방법&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;node(&apos;worker&apos;){
  stage(&apos;source&apos;){
    // stage에서 수행할 코드 작성
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;// 예시 1
pipeline {
  agent any

  stages() {
    stage(&apos;git clone&apos;){
      steps() {
        git &apos;https://github.com/git아이디/git레포지토리.git&apos;
      }
    }

    stage(&apos;Test&apos;) {
      steps{
        echo &apos;Testing..&apos;
      }
    }

    stage(&apos;execute sh&apos;) {
      steps {
        sh &apos;chmod 774 ./파일이름&quot;
        sh &apos;./파일이름&quot;
      }
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;// 예시 2
node {
    stage(&apos;git clone&apos;) {
        git &apos;https://github.com/git아이디/git레포지토리.git&apos;
    }
    stage(&apos;Test&apos;) {
        echo &apos;Testing....&apos;
    }
    stage(&apos;execute sh&apos;) {
		sh &quot;chmod 774 ./파일이름&quot;
        sh &quot;./파일이&quot;
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Flow Control&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;// if문 사용 가능

node {
    stage(&apos;Example&apos;) {
        if (env.BRANCH_NAME == &apos;메인브랜치&apos;) {
            echo &apos;메인 브랜치&apos;
        } else {
            echo &apos;다른 브랜치&apos;
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;// 예외 처리 가능

node {
    stage(&apos;Example&apos;) {
        try {
            sh &apos;exit 1&apos;
        }
        catch (exc) {
            echo &apos;error&apos;
            throw
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;pipeline-생성-방법-1&quot;&gt;Pipeline 생성 방법&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Web UI에서 Jenkinsfile 작성&lt;/strong&gt;
    &lt;blockquote&gt;
      &lt;ul&gt;
        &lt;li&gt;Jenkins 대시보드에서 새로운 Item 선택 &amp;gt; Pipeline 선택&lt;/li&gt;
        &lt;li&gt;설명 작성 후 Pipeline 탭 선택 &amp;gt; Definition에서 Pipeline script 선택 &amp;gt; 스크립트 작성 후 저장&lt;/li&gt;
        &lt;li&gt;Build Now 클릭&lt;/li&gt;
      &lt;/ul&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;SCM을 이용해 Jenkinsfile 작성&lt;/strong&gt;
    &lt;blockquote&gt;
      &lt;ul&gt;
        &lt;li&gt;테스트할 Repository에 Jenkinsfile 생성 후 샘플 코드 작성&lt;/li&gt;
        &lt;li&gt;Jenkins 대시코드에서 새로운 Item 선택 &amp;gt; 아이템 이름 작성 후 Pipeline 선택&lt;/li&gt;
        &lt;li&gt;Definition에서 Pipeline script from SCM 선택 &amp;gt; SCM 항목에서 Git 선택 &amp;gt; 원격 저장소 작성 &amp;gt; Credentials에서 계정 선택 &amp;gt; Branches to build에서 메인 branch 작성 &amp;gt; Script Path에서 Jenkinsfile 위치 작성(최상단일 경우 Default)&lt;/li&gt;
        &lt;li&gt;Build Triggers 항목에서 Github hook trigger for GITScm Polling 체크(메인 브랜치에 Push 했을 때 Build 됨)&lt;/li&gt;
        &lt;li&gt;Build Now 클릭(최초 1회 빌드됨)&lt;/li&gt;
        &lt;li&gt;아무 파일 생성, 수정 후 원격 저장소의 메인 branch에 push, build 확인&lt;/li&gt;
      &lt;/ul&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Fri, 03 Nov 2023 00:00:00 +0900</pubDate>
        <link>https://oblsoun.github.io/2023-11/study-jenkinsPipeline</link>
        <guid isPermaLink="true">https://oblsoun.github.io/2023-11/study-jenkinsPipeline</guid>
        
        
        <category>Study</category>
        
      </item>
    
      <item>
        <title>Groovy Script</title>
        <description>&lt;h4 id=&quot;개요&quot;&gt;개요&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;#개요&quot;&gt;개요&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#groovy란&quot;&gt;Groovy란&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#장점&quot;&gt;장점&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#단점&quot;&gt;단점&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#문법&quot;&gt;문법&lt;/a&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#문자열&quot;&gt;문자열&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#메소드-호출&quot;&gt;메소드 호출&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#형-생략&quot;&gt;형 생략&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#클로저closure&quot;&gt;클로저(Closure)&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h4 id=&quot;groovy란&quot;&gt;Groovy란&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;Java에 Python, Ruby 등의 특징을 더한 동적 객체 지향 프로그래밍 언어&lt;/li&gt;
  &lt;li&gt;JVM에서 실행되는 스크립트 언어&lt;/li&gt;
  &lt;li&gt;Java 호환 가능(Java Class 사용 가능)&lt;/li&gt;
  &lt;li&gt;단순화된 문법을 지원&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;장점&quot;&gt;장점&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;코드를 읽고 유지보수하기 편함&lt;/li&gt;
  &lt;li&gt;더 많은 절차적인 코드를 작성 가능&lt;/li&gt;
  &lt;li&gt;프로그램 작성과 흡사&lt;/li&gt;
  &lt;li&gt;기존 파이프 라인 문법이라 친숙하고 이전 버전과 호환 가능&lt;/li&gt;
  &lt;li&gt;필요한 경우 커스텀한 작업 생성이 가능하기 때문에 유연성 좋음&lt;/li&gt;
  &lt;li&gt;보다 복잡한 워크 플로우 및 파이프 라인 모델링 가능&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;단점&quot;&gt;단점&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;일반적으로 더 많은 프로그래밍이 필요&lt;/li&gt;
  &lt;li&gt;Groovy 언어 및 환경으로 제한된 구문 검사&lt;/li&gt;
  &lt;li&gt;전통적인 Jenkins 모델과는 맞지 않음&lt;/li&gt;
  &lt;li&gt;같은 작업이라면 Declarative 문법보다 잠재적으로 더 복잡&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;문법&quot;&gt;문법&lt;/h4&gt;

&lt;h5 id=&quot;문자열&quot;&gt;문자열&lt;/h5&gt;
&lt;p&gt;&lt;strong&gt;문자열 표기 방법&lt;/strong&gt;: ‘‘(작은 따옴표) OR ““(큰 따옴표)&lt;/p&gt;

&lt;p&gt;’‘(작은 따옴표): 단순한 문자열 출력&lt;/p&gt;

&lt;p&gt;”“(큰 따옴표): 문자열 출력, 문자열 내부에 $변수를 이용해 동적인 내용을 표시하는데에 사용 가능&lt;/p&gt;

&lt;p&gt;’’’ ‘’’ (작은 따옴표 3개) OR “”” “”“(큰 따옴표 3개로 열고닫기): 여러 행 출력&lt;/p&gt;

&lt;h5 id=&quot;메소드-호출&quot;&gt;메소드 호출&lt;/h5&gt;

&lt;p&gt;괄호 생략 가능&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;println (&apos;hello&apos;)
println &apos;hello&apos;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h5 id=&quot;형-생략&quot;&gt;형 생략&lt;/h5&gt;

&lt;p&gt;def 사용 시 모든 타입 변수 생성 가능&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;String message = &apos;hi&apos;
def message = &apos;hi&apos;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h5 id=&quot;클로저closure&quot;&gt;클로저(Closure)&lt;/h5&gt;

&lt;p&gt;클로저: Java의 Lambda(람다)와 매우 유사한 성격의 기능, 어떤 메소드의 인수로 전달할 처리문&lt;/p&gt;

&lt;p&gt;실행 방법: &lt;클로저이름&gt;.call() OR &lt;클로저이름&gt;() 으로 실행 가능&lt;/클로저이름&gt;&lt;/클로저이름&gt;&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;def clos1 = {
    println &apos;hi&apos;
}
​
// 실행
clos1.call()
clos1()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Thu, 02 Nov 2023 00:00:00 +0900</pubDate>
        <link>https://oblsoun.github.io/2023-11/study-groovyscript</link>
        <guid isPermaLink="true">https://oblsoun.github.io/2023-11/study-groovyscript</guid>
        
        
        <category>Study</category>
        
      </item>
    
      <item>
        <title>3D Contribution 적용법</title>
        <description>&lt;h4 id=&quot;개요&quot;&gt;개요&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;#개요&quot;&gt;개요&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#사용-계기&quot;&gt;사용 계기&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#목적&quot;&gt;목적&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#사용-방법&quot;&gt;사용 방법&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#느낀점&quot;&gt;느낀점&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h4 id=&quot;사용-계기&quot;&gt;사용 계기&lt;/h4&gt;

&lt;p&gt;Github 프로필을 작성하는 도중 여러 Github 사용자들의 README.md 파일을 구경하게 되었다.&lt;/p&gt;

&lt;p&gt;이때 시각적으로 Contribution을 확인할 수 있는 프로필을 보고 나도 하고 싶다는 생각에 3D Contribution을 찾아보게 되었다.&lt;/p&gt;

&lt;hr /&gt;

&lt;h4 id=&quot;목적&quot;&gt;목적&lt;/h4&gt;

&lt;p&gt;Github 프로필에 시각적으로 Contribution을 보여주기 위함&lt;/p&gt;

&lt;hr /&gt;

&lt;h4 id=&quot;사용-방법&quot;&gt;사용 방법&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;1. Repository 생성&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Repository name = Owner&lt;/p&gt;

&lt;p&gt;(참고) 이미 존재하는 Repository이기 때문에 경고 표시가 뜸&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://ifh.cc/g/nq0nLX.png&quot; alt=&quot;Repository 생성&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Token 생성&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Settings &amp;gt; Developer Settings&lt;/p&gt;

&lt;p&gt;Personal access tokens &amp;gt; Tokens(classic)&lt;/p&gt;

&lt;p&gt;Generate new token &amp;gt; Generate new token(classic)&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://ifh.cc/g/OCfzOV.png&quot; alt=&quot;Token 생성&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Settings 설정&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;본인 Repository 내 Settings&lt;/p&gt;

&lt;p&gt;Security &amp;gt; Secrets and variables &amp;gt; Action&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://ifh.cc/g/nCS3TL.png&quot; alt=&quot;Action&quot; /&gt;&lt;/p&gt;

&lt;p&gt;New repository secret 클릭&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://ifh.cc/g/r9CYbd.png&quot; alt=&quot;New repository secret&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Name: Token&lt;/p&gt;

&lt;p&gt;Secret: Token 복사/붙여넣기&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://ifh.cc/g/F1ZbfL.png&quot; alt=&quot;Action Token&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Add secret 클릭&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Action 설정&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Action 클릭&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://ifh.cc/g/2Fh4xn.png&quot; alt=&quot;Action&quot; /&gt;&lt;/p&gt;

&lt;p&gt;New workflow 클릭&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://ifh.cc/g/vh2kpg.png&quot; alt=&quot;New workflow&quot; /&gt;&lt;/p&gt;

&lt;p&gt;set up a workflow yourself 클릭&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://ifh.cc/g/pa09F8.png&quot; alt=&quot;set up a workflow yourself&quot; /&gt;&lt;/p&gt;

&lt;p&gt;파일 이름: main.yml &amp;gt; profile-3d.yml 변경&lt;/p&gt;

&lt;p&gt;아래 내용 복사/붙여넣기&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;깃허브이름&lt;/strong&gt;, &lt;strong&gt;깃허브이메일&lt;/strong&gt; 이라고 작성된 부분은 각자 Github name, email로 수정&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;name: GitHub-Profile-3D-Contrib

on:
  schedule: # 03:00 JST == 18:00 UTC
    - cron: &quot;0 18 * * *&quot;
  workflow_dispatch:

jobs:
  build:
    runs-on: ubuntu-latest
    name: generate-github-profile-3d-contrib
    steps:
      - uses: actions/checkout@v2
      - uses: yoshi389111/github-profile-3d-contrib@0.6.0
        env:
          GITHUB_TOKEN: $
          USERNAME: $
      - name: Commit &amp;amp; Push
        run: |
          git config user.name 깃허브이름
          git config user.email 깃허브이메일
          git add -A .
          git commit -m &quot;generated&quot;
          git push
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Run workflow &amp;gt; Run workflow&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://ifh.cc/g/RWaWFF.png&quot; alt=&quot;Run workflow&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. README 파일에 추가&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;아래 코드 복사/붙여넣기(적용한 테마: south-season-animate)&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;![](./profile-3d-contrib/profile-south-season-animate.svg)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;원하는 테마 적용&lt;/p&gt;

&lt;p&gt;샘플 &lt;a href=&quot;https://github.com/yoshi389111/github-profile-3d-contrib&quot;&gt;https://github.com/yoshi389111/github-profile-3d-contrib.git&lt;/a&gt;&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;profile-3d-contrib/profile-green-animate.svg
profile-3d-contrib/profile-green.svg
profile-3d-contrib/profile-season-animate.svg
profile-3d-contrib/profile-season.svg
profile-3d-contrib/profile-south-season-animate.svg
profile-3d-contrib/profile-south-season.svg
profile-3d-contrib/profile-night-view.svg
profile-3d-contrib/profile-night-green.svg
profile-3d-contrib/profile-night-rainbow.svg
profile-3d-contrib/profile-gitblock.svg
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;hr /&gt;

&lt;h4 id=&quot;느낀점&quot;&gt;느낀점&lt;/h4&gt;

&lt;p&gt;Github Action 기능을 시도해 보지 않았을 때는 어려울 거라고 생각했다. 이 기회에 처음 시도해 보는 기능이었지만 사용하면 편리한 기능임을 깨달았다. 앞으로는 Workflow를 자동화할 때 자주 사용하려 한다.&lt;/p&gt;
</description>
        <pubDate>Sat, 28 Oct 2023 00:00:00 +0900</pubDate>
        <link>https://oblsoun.github.io/2023-10/study-3D_contribution</link>
        <guid isPermaLink="true">https://oblsoun.github.io/2023-10/study-3D_contribution</guid>
        
        
        <category>Study</category>
        
      </item>
    
      <item>
        <title>.env 파일 사용법</title>
        <description>&lt;h4 id=&quot;개요&quot;&gt;개요&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;#개요&quot;&gt;개요&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#사용-계기&quot;&gt;사용 계기&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#목적&quot;&gt;목적&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#사용-방법&quot;&gt;사용 방법&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#느낀점&quot;&gt;느낀점&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h4 id=&quot;사용-계기&quot;&gt;사용 계기&lt;/h4&gt;

&lt;p&gt;&lt;a href=&quot;https://oblsoun.github.io/2023-10/project-vov&quot;&gt;프로젝트&lt;/a&gt;를 진행하면서 AWS S3, RDS를 활용하기 위한 AWS 계정의 Access Key, SMTP 기능을 구현하기 위한 포트 번호, 비밀번호를 안전하게 저장하는 것이 중요했다. 하지만 프로젝트 초기에 보안 문제를 해결하지 않고 Public으로 설정한 Github Repository에 commit 및 push 했다. 이때 민감한 정보가 노출되어 보안 문제가 발생했다.&lt;/p&gt;

&lt;p&gt;이 문제를 해결하기 위해 .env 파일에 대해 조사하였다.&lt;/p&gt;

&lt;hr /&gt;

&lt;h4 id=&quot;목적&quot;&gt;목적&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;SECRET_KEY, AWS_ACCESS_KEY, EMAIL_HOST, 포트 번호 등 외부에 알려지면 안 되는 값들을 보안, 유지보수를 용이하게 하기 위함&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h4 id=&quot;사용-방법&quot;&gt;사용 방법&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;1. decouple 설치&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;// Terminal 창

pip install python-decouple
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;2. 프로젝트 최상위 루트 경로에 .env 파일 생성&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Django Framework를 사용한 프로젝트는 manage.py와 같은 경로에 위치&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://ifh.cc/g/TVhaxQ.png&quot; alt=&quot;env파일경로&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. .env 파일에 보안이 필요한 정보 작성&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;// 예시 

SECRET_KEY = 

DATABASE_NAME = 
DATABASE_USER = 
DATABASE_PASSWORD = 
DATABASE_HOST = 
DATABASE_PORT = 

EMAIL_HOST = 
EMAIL_PORT = 
EMAIL_USER = 
EMAIL_PASSWORD = 

AWS_REGION = 
AWS_STORAGE_BUCKET_NAME = 
AWS_ACCESS_KEY_ID = 
AWS_SECRET_ACCESS_KEY = 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;span style=&quot;color:red&quot;&gt; 주의사항 &lt;/span&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Key=Value (O)&lt;/p&gt;

  &lt;p&gt;Key=”Value” (X)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;4. .env 파일 정보 사용&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Django Framework를 사용한 프로젝트는 settings.py에 설정값 작성&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;// import 설정
from decouple import config

// 코드 내 작성 예시
SECRET_KEY = config(&apos;SECRET_KEY&apos;)

DATABASES = {
    &apos;default&apos;: {
        &apos;ENGINE&apos;: &apos;django.db.backends.mysql&apos;,
        &apos;NAME&apos;: config(&apos;DATABASE_NAME&apos;),
        &apos;USER&apos;: config(&apos;DATABASE_USER&apos;),
        &apos;PASSWORD&apos;: config(&apos;DATABASE_PASSWORD&apos;),
        &apos;HOST&apos;: config(&apos;DATABASE_HOST&apos;),
        &apos;PORT&apos;: config(&apos;DATABASE_PORT&apos;),
        &apos;OPTIONS&apos;: {
            &apos;init_command&apos;: &quot;SET sql_mode=&apos;STRICT_TRANS_TABLES&apos;&quot;,
        }
    }
}

EMAIL_BACKEND = &apos;django.core.mail.backends.smtp.EmailBackend&apos;
EMAIL_HOST = config(&apos;EMAIL_HOST&apos;)
EMAIL_USE_TLS = True
EMAIL_PORT = config(&apos;EMAIL_PORT&apos;)
DEFAULT_FROM_EMAIL = config(&apos;EMAIL_USER&apos;)
EMAIL_HOST_USER = config(&apos;EMAIL_USER&apos;)
EMAIL_HOST_PASSWORD = config(&apos;EMAIL_PASSWORD&apos;)

AWS_REGION = config(&apos;AWS_REGION&apos;)
AWS_STORAGE_BUCKET_NAME = config(&apos;AWS_STORAGE_BUCKET_NAME&apos;)
AWS_ACCESS_KEY_ID = config(&apos;AWS_ACCESS_KEY_ID&apos;)
AWS_SECRET_ACCESS_KEY = config(&apos;AWS_SECRET_ACCESS_KEY&apos;)

AWS_S3_CUSTOM_DOMAIN = f&quot;{AWS_STORAGE_BUCKET_NAME}.s3.{AWS_REGION}.amazonaws.com&quot;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;5. .gitignore 파일에 .env 파일 추가&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;// .gitignore 파일

.env
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;hr /&gt;

&lt;h4 id=&quot;느낀점&quot;&gt;느낀점&lt;/h4&gt;

&lt;p&gt;초기에 보안 문제를 간과하면 나중에 해킹이나 개인정보 유출 문제로 이어질 수 있음을 깨달았다. 앞으로는 보안 검토를 강화하고, 민감한 데이터를 안전하게 보호하려 한다.&lt;/p&gt;
</description>
        <pubDate>Mon, 23 Oct 2023 00:00:00 +0900</pubDate>
        <link>https://oblsoun.github.io/2023-10/study-env</link>
        <guid isPermaLink="true">https://oblsoun.github.io/2023-10/study-env</guid>
        
        
        <category>Study</category>
        
      </item>
    
      <item>
        <title>Github Pull Request 사용 방법</title>
        <description>&lt;h4 id=&quot;개요&quot;&gt;개요&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;#개요&quot;&gt;개요&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#용어-설명&quot;&gt;용어 설명&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#목적&quot;&gt;목적&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#설정&quot;&gt;설정&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#사용-방법&quot;&gt;사용 방법&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h4 id=&quot;용어-설명&quot;&gt;용어 설명&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Pull Request&lt;/strong&gt;: Repository에 대한 제안된 변경 사항&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Repository&lt;/strong&gt;: 프로젝트 파일, 각 파일의 수정 기록(Issue), 프로젝트의 작업을 논의하고 관리할 수 있는 공간&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;branch&lt;/strong&gt;: Repository에 적용하는 변경 사항과 별도로 기능 개발, 버그 수정을 안전하게 작업할 수 있는 작업 영역&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;push&lt;/strong&gt;: branch에서 만든 commit을 repository에 적용&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;commit&lt;/strong&gt;: 변경 사항 기록&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;merge&lt;/strong&gt;: 기본 branch에 변경 사항을 병합&lt;/p&gt;

&lt;hr /&gt;

&lt;h4 id=&quot;목적&quot;&gt;목적&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;Github Repository의 개인 branch에 push한 변경 사항을 다른 사람에게 알림&lt;/li&gt;
  &lt;li&gt;공동 작업자와 변경 사항을 논의 및 검토&lt;/li&gt;
  &lt;li&gt;변경 사항을 기본 branch에 merge&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h4 id=&quot;설정&quot;&gt;설정&lt;/h4&gt;

&lt;p&gt;branch 보호 설정&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;1. [Settings] &amp;gt; [Branches] &amp;gt; [Add branch protection rule]&lt;/strong&gt;&lt;/p&gt;

  &lt;p&gt;&lt;img src=&quot;https://ifh.cc/g/gD740g.png&quot; alt=&quot;1&quot; /&gt;&lt;/p&gt;

  &lt;p&gt;&lt;strong&gt;2. Branch name pattern 설정, Protect matching branches 내 Require a pull request before merging 체크박스 선택&lt;/strong&gt;&lt;/p&gt;

  &lt;p&gt;&lt;img src=&quot;https://ifh.cc/g/6w7vDp.png&quot; alt=&quot;2&quot; /&gt;&lt;/p&gt;

  &lt;p&gt;&lt;strong&gt;3. 승인 인원 설정&lt;/strong&gt;&lt;/p&gt;

  &lt;p&gt;&lt;img src=&quot;https://ifh.cc/g/x0JFxb.png&quot; alt=&quot;3&quot; /&gt;&lt;/p&gt;

  &lt;p&gt;&lt;strong&gt;4. create 버튼 클릭&lt;/strong&gt;&lt;/p&gt;

  &lt;p&gt;&lt;img src=&quot;https://ifh.cc/g/fWz421.png&quot; alt=&quot;4&quot; /&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;hr /&gt;

&lt;h4 id=&quot;사용-방법&quot;&gt;사용 방법&lt;/h4&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;1. Git Push&lt;/strong&gt;&lt;/p&gt;

  &lt;p&gt;&lt;strong&gt;2. Branches 확인&lt;/strong&gt;&lt;/p&gt;

  &lt;p&gt;&lt;img src=&quot;https://ifh.cc/g/tbYdJP.png&quot; alt=&quot;5&quot; /&gt;&lt;/p&gt;

  &lt;p&gt;&lt;strong&gt;3. Compare &amp;amp; pull request 버튼 클릭&lt;/strong&gt;&lt;/p&gt;

  &lt;p&gt;&lt;img src=&quot;https://ifh.cc/g/rB3WRt.png&quot; alt=&quot;6&quot; /&gt;&lt;/p&gt;

  &lt;p&gt;&lt;strong&gt;4. merge할 브랜치 확인&lt;/strong&gt;&lt;/p&gt;

  &lt;p&gt;&lt;img src=&quot;https://ifh.cc/g/4mH2WW.png&quot; alt=&quot;7&quot; /&gt;&lt;/p&gt;

  &lt;p&gt;&lt;strong&gt;5. 필요 내용 입력 후 Create pull request 클릭&lt;/strong&gt;&lt;/p&gt;

  &lt;p&gt;필요 내용: 제목, 설명, Reviewers, Assignees, Labels, Projects, Milestone&lt;/p&gt;

  &lt;p&gt;&lt;img src=&quot;https://ifh.cc/g/F3oOm3.png&quot; alt=&quot;8&quot; /&gt;&lt;/p&gt;

  &lt;p&gt;&lt;strong&gt;6. Merge pull request 클릭&lt;/strong&gt;&lt;/p&gt;

  &lt;p&gt;&lt;img src=&quot;https://ifh.cc/g/YLZ4SP.png&quot; alt=&quot;9&quot; /&gt;&lt;/p&gt;

  &lt;p&gt;&lt;strong&gt;6-1. Merge pull request가 비활성화일 때&lt;/strong&gt;&lt;/p&gt;

  &lt;p&gt;&lt;a href=&quot;https://docs.github.com/ko/pull-requests/collaborating-with-pull-requests/addressing-merge-conflicts/resolving-a-merge-conflict-on-github&quot;&gt;해결 방법&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
</description>
        <pubDate>Fri, 20 Oct 2023 00:00:00 +0900</pubDate>
        <link>https://oblsoun.github.io/2023-10/study-pullrequest</link>
        <guid isPermaLink="true">https://oblsoun.github.io/2023-10/study-pullrequest</guid>
        
        
        <category>Study</category>
        
      </item>
    
      <item>
        <title>안전네컷</title>
        <description>&lt;p&gt;&lt;a href=&quot;https://oblsoun.github.io/2023-10/project-vov&quot;&gt;VOV 프로젝트&lt;/a&gt; ‘실시간’ 기능을 활용한 사진 촬영 프로젝트(포토부스)&lt;/p&gt;

&lt;p&gt;개발 기간: 2023. 10. ~ 2023. 10.&lt;/p&gt;

&lt;p&gt;개발 인원: 2&lt;/p&gt;

&lt;p&gt;개발 언어: Python&lt;/p&gt;

&lt;p&gt;Dataset: &lt;a href=&quot;https://universe.roboflow.com/fingerprint-nze3i/vov-k9idv&quot;&gt;Roboflow&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Model: Yolov5m&lt;/p&gt;

&lt;p&gt;Framework: Django&lt;/p&gt;

&lt;p&gt;IDE: Visual Studio Code&lt;/p&gt;

&lt;p&gt;Library: OpenCV, Mediapipe, Numpy, PIL&lt;/p&gt;

&lt;p&gt;ETC: SMTP, JQuery&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://youtu.be/UCxkyX-NQD4&quot;&gt;시연 영상&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/oblsoun/VOVsnap&quot;&gt;Github Link&lt;/a&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;👀 &lt;strong&gt;담당 역할&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;팀장&lt;/p&gt;

&lt;p&gt;데이터셋 구축 100% &lt;a href=&quot;https://universe.roboflow.com/fingerprint-nze3i/vov-k9idv&quot;&gt;Roboflow 링크&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;모델 구축(하이퍼 파라미터 조정 및 모델 추출) 100% &lt;a href=&quot;https://colab.research.google.com/drive/1dKO153AU2HZRUqF23diTxx2qycikQkzL?usp=sharing&quot;&gt;COLAB 링크&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;촬영 효과 100%&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;✔️ &lt;strong&gt;프로젝트 목적&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;기획 의도&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
  &lt;ul&gt;
    &lt;li&gt;
      &lt;p&gt;AI 기반의 생채 정보 보안을 위한 지문 비식별화&lt;/p&gt;
    &lt;/li&gt;
    &lt;li&gt;
      &lt;p&gt;개인정보 데이터 관리의 중요성 인식 확산&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
  &lt;li&gt;프로젝트 내용&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
  &lt;ul&gt;
    &lt;li&gt;
      &lt;p&gt;지문 영역 인지 및 지문 식별 정보 추출&lt;/p&gt;
    &lt;/li&gt;
    &lt;li&gt;
      &lt;p&gt;추출된 지문 비식별화&lt;/p&gt;
    &lt;/li&gt;
    &lt;li&gt;
      &lt;p&gt;후처리된 파일 이메일 전송&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;

&lt;hr /&gt;

&lt;p&gt;✔️ &lt;strong&gt;프로젝트 특장점&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Mediapipe 라이브러리 및 YOLOv5 모델로 높은 정확도와 빠른 속도로 지문 추출&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;p&gt;✔️ &lt;strong&gt;주요 기술&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Mediapipe 라이브러리를 사용하여 손 끝 위치를 감지&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://colab.research.google.com/drive/1dKO153AU2HZRUqF23diTxx2qycikQkzL?usp=sharing&quot;&gt;Custom YOLOv5m&lt;/a&gt; 모델을 사용하여 지문 식별(mAP50 0.903)&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;p&gt;✔️ &lt;strong&gt;기타 링크&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://universe.roboflow.com/fingerprint-nze3i/vov-k9idv&quot;&gt;Custom Dataset - Roboflow&lt;/a&gt;&lt;/p&gt;
</description>
        <pubDate>Tue, 17 Oct 2023 00:00:00 +0900</pubDate>
        <link>https://oblsoun.github.io/2023-10/project-safesnap</link>
        <guid isPermaLink="true">https://oblsoun.github.io/2023-10/project-safesnap</guid>
        
        
        <category>Project</category>
        
      </item>
    
      <item>
        <title>VOV</title>
        <description>&lt;p&gt;개인정보 비식별화 지원 서비스 개발 프로젝트 VOV&lt;/p&gt;

&lt;p&gt;개발 기간: 2023. 08. ~ 2023. 10.&lt;/p&gt;

&lt;p&gt;개발 인원: 4&lt;/p&gt;

&lt;p&gt;개발 언어: Python&lt;/p&gt;

&lt;p&gt;Dataset: &lt;a href=&quot;https://universe.roboflow.com/fingerprint-nze3i/vov-k9idv&quot;&gt;Roboflow&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Model: Yolov5m&lt;/p&gt;

&lt;p&gt;Framework: Django&lt;/p&gt;

&lt;p&gt;DB: AWS RDS(mariaDB)&lt;/p&gt;

&lt;p&gt;IDE: Visual Studio Code&lt;/p&gt;

&lt;p&gt;Library: OpenCV, Mediapipe, Numpy&lt;/p&gt;

&lt;p&gt;ETC: UML, SonarQube, S3, SMTP, JQuery&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://youtu.be/z_S71TbysyU&quot;&gt;시연 영상&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/oblsoun/VOV&quot;&gt;Github Link&lt;/a&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;👀 &lt;strong&gt;담당 역할&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;팀장&lt;/p&gt;

&lt;p&gt;문서 작업 25% &lt;a href=&quot;https://github.com/oblsoun/VOV/tree/main/doc&quot;&gt;링크&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;데이터셋 구축 100% &lt;a href=&quot;https://universe.roboflow.com/fingerprint-nze3i/vov-k9idv&quot;&gt;Roboflow 링크&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;모델 구축(하이퍼 파라미터 조정 및 모델 추출) 100% &lt;a href=&quot;https://colab.research.google.com/drive/1dKO153AU2HZRUqF23diTxx2qycikQkzL?usp=sharing&quot;&gt;COLAB 링크&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;실시간 촬영 시 모델 이용하여 지문 감지 100% &lt;a href=&quot;https://github.com/oblsoun/VOV/tree/main/src/VOVmainProject/realTimeDeidentificationApp&quot;&gt;Github 링크&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;실시간 촬영 시 감지된 지문 후처리(블러) 100% &lt;a href=&quot;https://github.com/oblsoun/VOV/tree/main/src/VOVmainProject/realTimeDeidentificationApp&quot;&gt;Github 링크&lt;/a&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;✔️ &lt;strong&gt;프로젝트 목적&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;기획 의도&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
  &lt;ul&gt;
    &lt;li&gt;
      &lt;p&gt;AI 기반의 생채 정보 보안을 위한 지문 비식별화&lt;/p&gt;
    &lt;/li&gt;
    &lt;li&gt;
      &lt;p&gt;개인정보 데이터 관리의 중요성 인식 확산&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
  &lt;li&gt;프로젝트 내용&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
  &lt;ul&gt;
    &lt;li&gt;
      &lt;p&gt;지문 영역 인지 및 지문 식별 정보 추출&lt;/p&gt;
    &lt;/li&gt;
    &lt;li&gt;
      &lt;p&gt;추출된 지문 비식별화&lt;/p&gt;
    &lt;/li&gt;
    &lt;li&gt;
      &lt;p&gt;후처리된 파일 저장 및 전송&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;

&lt;hr /&gt;

&lt;p&gt;✔️ &lt;strong&gt;프로젝트 특장점&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Mediapipe 라이브러리 및 YOLOv5m 모델로 높은 정확도와 빠른 속도로 지문 추출&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;기존 지문 인식 시스템의 부족한 보호 기능 보완&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;보안을 위해 후처리된 이미지만 데이터베이스에 저장&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;안정적인 AWS 인프라 및 다양한 산업 분야에서 활용 가능&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;사용자 친화적 환경으로 업로드 및 결과 처리 용이&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;p&gt;✔️ &lt;strong&gt;주요 기술&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Mediapipe 라이브러리를 사용하여 손 끝 위치를 감지&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://colab.research.google.com/drive/1dKO153AU2HZRUqF23diTxx2qycikQkzL?usp=sharing&quot;&gt;Custom YOLOv5m&lt;/a&gt; 모델을 사용하여 지문 식별(mAP50 0.903)&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;AWS 인프라를 활용한 무중단 배포와 S3, RDS를 이용한 데이터 저장 및 클라우드 서비스 제공&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;p&gt;✔️ &lt;strong&gt;기술 스택&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;서비스 구성도&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;https://ifh.cc/g/KSLTG7.png&quot; alt=&quot;서비스 구성도&quot; /&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;메뉴 구성도&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;https://ifh.cc/g/p6jAbb.png&quot; alt=&quot;메뉴 구성도&quot; /&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Usecase&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;https://ifh.cc/g/CO21JA.png&quot; alt=&quot;Usecase&quot; /&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;알고리즘 명세서&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;https://ifh.cc/g/D0KyKQ.jpg&quot; alt=&quot;알고리즘 명세서&quot; /&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;✔️ &lt;strong&gt;테이블 설계&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://ifh.cc/g/CT7lMw.png&quot; alt=&quot;ERD&quot; /&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;✔️ &lt;strong&gt;기타 링크&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/oblsoun/VOVsnap&quot;&gt;활용 예시&lt;/a&gt;&lt;/p&gt;
</description>
        <pubDate>Fri, 13 Oct 2023 00:00:00 +0900</pubDate>
        <link>https://oblsoun.github.io/2023-10/project-vov</link>
        <guid isPermaLink="true">https://oblsoun.github.io/2023-10/project-vov</guid>
        
        
        <category>Project</category>
        
      </item>
    
      <item>
        <title>Chroma Lens</title>
        <description>&lt;p&gt;색약자를 위한 이미지 색채 감지 프로젝트&lt;/p&gt;

&lt;p&gt;개발 기간: 2023. 06. ~ 2023. 06&lt;/p&gt;

&lt;p&gt;개발 인원: 2&lt;/p&gt;

&lt;p&gt;개발 언어: Python&lt;/p&gt;

&lt;p&gt;Dataset: &lt;a href=&quot;https://universe.roboflow.com/msa-ciwxj/yoon-2&quot;&gt;Roboflow&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Model: Yolov8m&lt;/p&gt;

&lt;p&gt;Framework: Django&lt;/p&gt;

&lt;p&gt;IDE: Google COLAB, Pycharm&lt;/p&gt;

&lt;p&gt;Library: OpenCV, PIL&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://youtu.be/LGonUX21H74&quot;&gt;시연 영상&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/oblsoun/chromalens&quot;&gt;Github Link&lt;/a&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;👀 &lt;strong&gt;담당 역할&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;데이터셋 구축 50% &lt;a href=&quot;https://universe.roboflow.com/msa-ciwxj/yoon-2&quot;&gt;Roboflow 링크&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;모델 구축(하이퍼 파라미터 조정 및 모델 추출) 50% &lt;a href=&quot;https://colab.research.google.com/drive/12toM9X_22CyYPObbtlJzoKYNFA7JG5yb?usp=sharing&quot;&gt;Colab 링크&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Django 환경 Setting 100%&lt;/p&gt;

&lt;p&gt;파일 업로드 시 Bounding Box 50% &lt;a href=&quot;https://github.com/oblsoun/chromalens/tree/main/colordetection&quot;&gt;Github 링크&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;실시간 촬영 시 Bounding Box 100% &lt;a href=&quot;https://github.com/oblsoun/chromalens/tree/main/webcam&quot;&gt;Github 링크&lt;/a&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;✔️ &lt;strong&gt;개발 배경&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;색약자들이 일상생활 속에서 불분명한 색채 인식으로 인해 겪을 수 있는 불편함 해소&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;p&gt;✔️ &lt;strong&gt;개발 필요성&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;색상을 추출하는 인공지능 서비스는 많지만 색 공간을 명시하고, 라벨링하는 서비스는 미흡&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;자율주행기술이 대두되면서 색을 감지하고 경계선을 인식하는 인공지능 개발 필요성 등장&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;p&gt;✔️ &lt;strong&gt;프로그램 특장점&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;간편한 이미지 업로드&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;즉각적인 이미지 분석&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;색상 분류 및 색 공간 형태 명시&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;실시간 처리 가능&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;p&gt;✔️ &lt;strong&gt;개발 과정&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/113246634/273899408-91c2d309-ed02-471d-85d5-c2fe122c4324.jpg&quot; alt=&quot;개발 과정&quot; /&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;✔️ &lt;strong&gt;사용 과정&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://github-production-user-asset-6210df.s3.amazonaws.com/113246634/273899491-eec13495-c49b-427a-93c3-e2f23f32d157.jpg&quot; alt=&quot;사용 과정&quot; /&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;✔️ &lt;strong&gt;모델 구현&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;데이터셋 구축&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
  &lt;ul&gt;
    &lt;li&gt;
      &lt;p&gt;&lt;a href=&quot;https://universe.roboflow.com/msa-ciwxj/yoon-2&quot;&gt;Roboflow 링크&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li&gt;
      &lt;p&gt;6개 클래스(brown, green, orange, purple, red, yellow)에 해당하는 색 이미지를 수집&lt;/p&gt;
    &lt;/li&gt;
    &lt;li&gt;
      &lt;p&gt;Poligon Tool로 라벨링 작업&lt;/p&gt;
    &lt;/li&gt;
    &lt;li&gt;
      &lt;p&gt;신뢰도, 정확도를 낮추거나 과적합을 일으키는 데이터셋 필터링&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;

&lt;ol&gt;
  &lt;li&gt;모델 설계&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
  &lt;ul&gt;
    &lt;li&gt;
      &lt;p&gt;&lt;a href=&quot;https://colab.research.google.com/drive/12toM9X_22CyYPObbtlJzoKYNFA7JG5yb?usp=sharing&quot;&gt;Colab 링크&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li&gt;
      &lt;p&gt;Confusion Matrix(혼동행렬)&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ul&gt;

  &lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/113246634/273897986-bd9d81f8-0b73-4a59-8426-ae3c54b3cd06.png&quot; alt=&quot;confusion_matrix_normalized&quot; /&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;hr /&gt;

&lt;p&gt;✔️ &lt;strong&gt;기대효과 및 활용분야&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;색 인식에 보다 원활한 시각적 의사소통을 보편적으로 가능하게 함&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;기계장치, 자율주행 차량 등이 중앙선, 신호등, 경고등 등을 인식&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Fri, 30 Jun 2023 00:00:00 +0900</pubDate>
        <link>https://oblsoun.github.io/2023-06/project-chromalens</link>
        <guid isPermaLink="true">https://oblsoun.github.io/2023-06/project-chromalens</guid>
        
        
        <category>Project</category>
        
      </item>
    
      <item>
        <title>Varda</title>
        <description>&lt;p&gt;스킨케어 화장품 구매 사이트&lt;/p&gt;

&lt;p&gt;개발 기간: 2023. 04 ~ 2023. 05&lt;/p&gt;

&lt;p&gt;개발 인원: 5&lt;/p&gt;

&lt;p&gt;개발 언어: Java&lt;/p&gt;

&lt;p&gt;Framework: Spring boot&lt;/p&gt;

&lt;p&gt;DB: MyBatis&lt;/p&gt;

&lt;p&gt;IDE: Eclipse&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/oblsoun/varda&quot;&gt;Github Link&lt;/a&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;👀 &lt;strong&gt;담당 역할&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;부팀장&lt;/p&gt;

&lt;p&gt;와이어프레임 100%&lt;/p&gt;

&lt;p&gt;데이터베이스 100%&lt;/p&gt;

&lt;p&gt;장바구니 프론트(.jsp) 100% &lt;a href=&quot;https://github.com/oblsoun/varda/tree/main/src/main/webapp/WEB-INF/views/cart&quot;&gt;Github 링크&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;장바구니 백엔드(.java) 100% &lt;a href=&quot;https://github.com/oblsoun/varda/tree/main/src/main/java/com/msa/varda/cart&quot;&gt;Github 링크&lt;/a&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;✔️ &lt;strong&gt;개발 배경&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;기초케어 화장품만 판매하는 사이트는 존재하지 않음&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;타사 홈페이지에서는 기초케어 화장품에 관한 카테고리가 단순&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;p&gt;✔️ &lt;strong&gt;프로젝트 목적&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;스킨케어 위주의 제품 판매&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;카테고리 세분화로 목적에 따른 상품 구매 가능&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;p&gt;✔️ &lt;strong&gt;프로젝트 설명&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;기술 스택&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/113246634/273930720-318d2d99-fb0d-440f-b5f0-7a391d60216d.jpg&quot; alt=&quot;기술스택&quot; /&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;메뉴 구성&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
  &lt;p&gt;Product&lt;/p&gt;

  &lt;p&gt;Skin Type&lt;/p&gt;

  &lt;p&gt;Men/Women&lt;/p&gt;

&lt;/blockquote&gt;

&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/113246634/273927908-ba6f2b63-d58b-4d58-9049-08fbfd7f9e21.jpg&quot; alt=&quot;메뉴구성&quot; /&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;테이블 구성&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/113246634/273931825-574b516e-efcb-4336-b15f-c480f3c9612c.jpg&quot; alt=&quot;테이블 구성&quot; /&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;✔️ &lt;strong&gt;개발 절차&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/113246634/273932507-8ddc507b-da6f-4589-bcfe-d12b98c6ffa9.jpg&quot; alt=&quot;개발 절차&quot; /&gt;&lt;/p&gt;
</description>
        <pubDate>Fri, 19 May 2023 00:00:00 +0900</pubDate>
        <link>https://oblsoun.github.io/2023-05/project-varda</link>
        <guid isPermaLink="true">https://oblsoun.github.io/2023-05/project-varda</guid>
        
        
        <category>Project</category>
        
      </item>
    
      <item>
        <title>SWIF</title>
        <description>&lt;p&gt;스터디매칭 어플리케이션&lt;/p&gt;

&lt;p&gt;개발 기간: 2022. 03. ~ 2022. 10.&lt;/p&gt;

&lt;p&gt;개발 인원: 4&lt;/p&gt;

&lt;p&gt;개발 언어: Java&lt;/p&gt;

&lt;p&gt;DB: Firebase&lt;/p&gt;

&lt;p&gt;IDE: Android Studio&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://youtu.be/STS_tqPen94&quot;&gt;시연 영상&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/oblsoun/SWIF&quot;&gt;Github Link&lt;/a&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;👀 &lt;strong&gt;담당 역할&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;팀원&lt;/p&gt;

&lt;p&gt;UI/UX 20%&lt;/p&gt;

&lt;p&gt;매칭페이지 기능 100% &lt;a href=&quot;https://github.com/oblsoun/SWIF/blob/main/app/src/main/java/com/example/swip/MatchingMainActivity.java&quot;&gt;Github 링크&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;메인페이지 달력 및 투두 100% &lt;a href=&quot;https://github.com/oblsoun/SWIF/blob/main/app/src/main/java/com/example/swip/MainActivity.java&quot;&gt;Github 링크&lt;/a&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;✔️ &lt;strong&gt;개발 배경&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;코로나19 확산 이후 온라인 독서실 및 스터디앱 사용량 증가&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;SWOT 분석&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/113246634/273862371-f37f81f5-d7f9-4cbe-94ff-260f992364fb.jpg&quot; alt=&quot;swot&quot; /&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;✔️ &lt;strong&gt;개발 필요성&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;오프라인 독서실 사용 대비 비용 절감&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;p&gt;✔️ &lt;strong&gt;핵심 기능&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;타이머로 간단하게 총 공부 시간 기록&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;채팅을 통해 타 사용자와 서로 스터디 결과물 확인&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;게시판을 통한 사용자와 정보 공유&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;p&gt;✔️ &lt;strong&gt;사용 프로그램&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/113246634/273866575-4e3423b4-7263-4607-88a9-d6a29312baca.jpg&quot; alt=&quot;use&quot; /&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;✔️ &lt;strong&gt;UI/UX&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.figma.com/file/11UPpZ3Bjcf419xwidDnb3/%EC%A1%B8%EC%9E%91-%EB%B0%B1%EC%97%85?type=design&amp;amp;node-id=0%3A1&amp;amp;mode=design&amp;amp;t=bUwRK2DXZ5DGuHzQ-1&quot;&gt;클릭 시 Figma 이동&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/113246634/273867377-ef2ded5a-fb71-40f6-a61a-142446d9e315.jpg&quot; alt=&quot;uiux&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/113246634/273867445-fc35fd5c-f827-4dbd-97c2-e3d05dd687cd.jpg&quot; alt=&quot;uiux&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/113246634/273867648-3dc0a0fa-37f5-499c-8195-92eb2e258f8b.jpg&quot; alt=&quot;uiux&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/113246634/273867562-52eac18f-9f8a-4a62-85fb-cf2855849b11.jpg&quot; alt=&quot;uiux&quot; /&gt;&lt;/p&gt;
</description>
        <pubDate>Thu, 15 Dec 2022 00:00:00 +0900</pubDate>
        <link>https://oblsoun.github.io/2022-12/project-swif</link>
        <guid isPermaLink="true">https://oblsoun.github.io/2022-12/project-swif</guid>
        
        
        <category>Project</category>
        
      </item>
    
  </channel>
</rss>