에이전트 사이에 사진 전달하기

JenkinsBeginner
지금 연습하기

소개

이제 Fieldlight Studio에는 완전한 사진 패키지가 필요합니다. 작은 사진 세 장, 콘택트 시트, 설명, 다운로드 후에도 작동하는 갤러리를 포함해야 합니다. Jenkins 에이전트 하나는 사진을 준비할 수 있고, 다른 에이전트에는 제공된 패키징 도구가 있습니다. 두 에이전트를 올바르게 선택해도 작업 공간 사이에 파일이 공유되는 것은 아닙니다.

이 실습에서는 파일이 없는 문제를 관찰하고, 하나의 Pipeline 실행 안에서 실제 임시 전달을 추가한 다음, 결과 ZIP을 독립적으로 사용할 수 있도록 보관합니다. 이 실습은 자체 원본, 연결된 에이전트, 아직 빌드하지 않은 작업으로 시작합니다. 이전 실습의 파일이나 빌드를 사용하지 않습니다.

전제 지식은 사진 처리 에이전트 선택하기에서 배운 에이전트 레이블, 단계별 에이전트 할당, 너비 옵션, Jenkins 자체 아티팩트, 지문 설정, 작업 공간 정리와 기본적인 Jenkins 탐색입니다. Java 프로그래밍이나 에이전트 설치는 필요하지 않습니다. 두 에이전트는 같은 훈련용 VM에서 독립된 파일시스템을 가진 별도 컨테이너이며, 커널은 공유합니다. Fieldlight와 AI로 생성한 학습용 사진은 실제 고객이나 행사를 나타내지 않습니다. 소요 시간은 작성자의 예상치이며, 초보자를 대상으로 측정한 값은 아닙니다.

분리된 작업 공간 관찰하기

이 단계에서는 이미지 에이전트에서 패키징 에이전트로 작업 흐름을 따라가며, 준비 단계의 성공만으로는 사용할 수 있는 결과물이 전달되지 않는 이유를 관찰합니다. Photo Desk에서 시작하세요.

Garden Stories 원본 세 장인 라벤더, 정원 길, 물뿌리개를 살펴보세요. 각 이미지를 열고 브라우저의 Back 동작으로 돌아오세요. 데스크에는 No completed collection yet가 표시됩니다. 이 원본들은 변경하지 않아야 합니다. 원하는 결과물은 가로세로 비율을 유지한 정확히 320 pixels wide, 즉 너비 320픽셀의 미리보기를 사용합니다.

Jenkins로 전환하고 build-photo-pack을 여세요. Configure → Pipeline을 선택하세요. 준비된 Script를 읽으세요. 최상위 agent none은 각 단계가 해당 능력을 가진 에이전트를 따로 할당할 수 있게 합니다. Prepare photos는 photo-imaging을 요청하고 /opt/fieldlight/prepare-photos --width 320을 실행합니다. Pack collection은 photo-packing을 요청하고 /opt/fieldlight/pack-photos를 실행합니다.

각 단계는 deleteDir()로 시작하며, 자체 post { always { deleteDir() } } 정리 작업을 가집니다. 작업 공간은 작업에 할당된 에이전트에 속한 디렉터리입니다. 두 단계가 같은 작업 이름을 사용하더라도 디렉터리는 서로 다른 컨테이너 파일시스템에 있습니다. 하나의 공유 디렉터리에 붙인 두 이름이 아닙니다. 읽기 전용 원본은 이미지 에이전트의 /opt/fieldlight/originals 아래에 있으며, 작업 공간 밖에 있습니다.

이미지 프로그램은 현재 작업 공간을 기준으로 다음 여섯 파일을 작성합니다.

prepared/
  images/
    garden-01.png
    garden-02.png
    garden-03.png
  contact-sheet.png
  captions.csv
  preparation.json

미리보기 세 장은 320 × 213픽셀입니다. 콘택트 시트는 세 장을 함께 보여 줍니다. CSV는 각 파일 이름을 설명 및 크기와 연결하고, JSON은 컬렉션, 요청된 너비, 원본 이미지 해시를 식별합니다. 제공된 패키징 도구는 자체 작업 공간에서 이 실제 파일들을 사용합니다. 다른 에이전트나 Photo Desk에서 누락된 파일을 가져오지 않습니다.

스크립트를 편집하지 않고 작업 페이지로 돌아가 Build Now를 한 번 선택하세요. Build History에서 새 번호의 빌드를 연 다음 Console Output을 여세요. 예상된 FAILURE를 기다리세요. 먼저 image-studio가 3 previews at 320 pixels wide를 보고합니다. 해당 작업 공간이 정리된 뒤 pack-studio가 패키징 명령을 실행하고 Missing prepared/preparation.json in this agent's workspace를 보고합니다. 마지막 정리 작업도 실행됩니다.

이는 파일 위치 문제이며, 원본이 손상되거나 프로그램이 없는 문제가 아닙니다. 준비 단계는 완료되었지만 전달 과정이 없었습니다. 파일을 수동으로 복사하거나, 마운트를 공유하거나, 정리를 제거하거나, 두 단계를 모두 이미지 에이전트에 배치하면 의도한 두 에이전트 워크플로를 완성하지 않은 채 학습할 문제를 우회하게 됩니다. 두 단계의 에이전트 할당과 두 정리 섹션을 그대로 두세요.

빌드가 아직 실행 중이거나 대기 중이면 최종 상태가 나올 때까지 기다린 뒤 검사하세요. 실수로 편집하여 다른 오류가 발생했다면 아래 설정의 원래 스크립트를 복원하고 저장한 다음 한 번 실행하여, 예상된 파일 누락 실패를 관찰하세요.

pipeline {
    agent none
    stages {
        stage('Prepare photos') {
            agent { label 'photo-imaging' }
            steps {
                deleteDir()
                sh '/opt/fieldlight/prepare-photos --width 320'
            }
            post {
                always { deleteDir() }
            }
        }
        stage('Pack collection') {
            agent { label 'photo-packing' }
            steps {
                deleteDir()
                sh '/opt/fieldlight/pack-photos'
                archiveArtifacts artifacts: 'photo-pack.zip', fingerprint: true
            }
            post {
                always { deleteDir() }
            }
        }
    }
}

실패한 실행과 콘솔을 유지하세요. Photo Desk로 전환하고 새로 고침하세요. 여전히 완료된 컬렉션이 없다고 표시되어야 합니다. 전체 원본 세 장은 계속 사용할 수 있습니다. 다음 단계에서는 준비된 작은 결과물만 전달한 뒤, 보관할 아카이브를 만듭니다.

사진을 전달하고 패키지 보관하기

이 단계에서는 같은 Pipeline 실행 안에서 준비된 여섯 파일을 전달하고, 완성된 ZIP을 보관한 다음 독립적으로 살펴봅니다. Jenkins에서 시작하고 build-photo-pack으로 돌아간 뒤 Configure → Pipeline을 선택하세요.

stash는 나중에 동일한 Pipeline 실행 안에서 사용할 작은 파일 묶음을 선택하여 저장합니다. 이름과 includes 패턴을 지정하세요. 여기서 prepared/**는 prepared 폴더의 파일과 하위 images/ 파일들을 포함합니다. 상대 경로가 유지되므로 stash를 복원하면 받는 쪽 작업 공간에 prepared/가 만들어집니다. 작은 파생 결과물만 stash로 저장하세요. 원본, Java 런타임, 도구 디렉터리는 포함하지 마세요.

unstash는 해당 이름의 묶음을 현재 에이전트의 작업 공간에 복원합니다. 이름은 앞서 저장한 stash와 같아야 합니다. 받는 쪽 단계의 첫 deleteDir() 뒤, 패키징 명령 앞에 배치하세요. stash는 이미지 처리 뒤, 이미지 단계의 정리 앞에 배치하세요. 그렇지 않으면 파일이 아직 없거나, 이미 제거되었거나, 복원 직후 제거됩니다.

stash는 임시 전달 수단이며 다운로드용 아카이브가 아닙니다. 일반적으로 Jenkins는 해당 실행이 끝난 뒤 stash를 폐기합니다. 반면 archiveArtifacts는 최종 ZIP을 빌드와 함께 보관합니다. 두 연산을 모두 유지하면 전달은 임시로 이루어지고, 결과물은 나중에도 사용할 수 있습니다.

Script 안을 클릭하고 Windows/Linux에서는 Ctrl+A, macOS에서는 Command+A로 모두 선택한 다음, 다음 전체 버전으로 바꾸세요.

pipeline {
    agent none
    stages {
        stage('Prepare photos') {
            agent { label 'photo-imaging' }
            steps {
                deleteDir()
                sh '/opt/fieldlight/prepare-photos --width 320'
                stash name: 'prepared-photos', includes: 'prepared/**'
            }
            post {
                always { deleteDir() }
            }
        }
        stage('Pack collection') {
            agent { label 'photo-packing' }
            steps {
                deleteDir()
                unstash 'prepared-photos'
                sh '/opt/fieldlight/pack-photos'
                archiveArtifacts artifacts: 'photo-pack.zip', fingerprint: true
            }
            post {
                always { deleteDir() }
            }
        }
    }
}

새로 추가한 두 줄은 이름을 지정한 stash와 그에 맞는 unstash입니다. 제공된 이미지 및 패키징 명령, 올바른 에이전트, 원본 파일의 보호 범위, 정리 작업은 유지됩니다. archiveArtifacts 설정은 photo-pack.zip을 보관하고 Jenkins 자체 파일 지문을 기록합니다. 지문은 파일 식별 정보를 추적하며, 고객 승인이나 전자 서명이 아닙니다.

Save를 선택한 다음 Build Now를 선택하세요. 새 실행이 SUCCESS로 끝날 때까지 기다리세요. Console Output을 열고 순서를 읽으세요. image-studio가 320픽셀 사진을 준비하고, Jenkins가 **Stashed 6 file(s)**를 보고한 뒤 이미지 작업 공간이 비워집니다. 그런 다음 pack-studio가 stash를 복원하고, 패키징 도구가 Packed 9 collection files into photo-pack.zip을 보고하며, Jenkins가 ZIP을 보관하고 지문을 기록한 뒤 패키징 작업 공간을 비웁니다.

콘솔에 No such saved stash가 표시되면 두 stash 이름과 순서를 비교하고, 전체 스크립트를 복원하여 저장한 뒤 다시 실행하세요. 준비된 파일이 없다는 오류가 계속되면 includes 패턴이 prepared/**인지, unstash가 받는 쪽 정리 뒤에 오는지 확인하세요. 새 빌드마다 새로운 전달이 시작됩니다. 이전 빌드의 stash로 대신할 수 없습니다. Groovy 구문 오류가 나면 전체 스크립트를 복원하고 중괄호, 따옴표, 쉼표를 유지하세요. 실패와 성공을 포함한 모든 실행을 보관하세요. 일반적인 실수 때문에 VM을 초기화할 필요는 없습니다.

성공한 빌드 페이지에서 photo-pack.zip 아티팩트를 선택하여 저장하세요. 자신의 컴퓨터에서 ZIP 전체를 새 폴더에 추출하세요. 압축 파일 뷰어 안의 HTML 파일만 열지 마세요. 주변 파일도 함께 추출해야 합니다. 폴더에는 다음 항목이 있어야 합니다.

index.html
styles.css
delivery.txt
captions.csv
preparation.json
contact-sheet.png
images/
  garden-01.png
  garden-02.png
  garden-03.png

추출한 index.html을 브라우저에서 여세요. Fieldlight Studio 갤러리에는 올바른 정원 사진 세 장과 해당 설명이 모두 표시되어야 합니다. 각 사진을 열고 브라우저의 Back으로 돌아오세요. Open contact sheet를 선택하여 실제 세 사진의 개요 이미지를 본 다음, 브라우저의 Back으로 갤러리로 돌아오세요. 추출한 폴더에서 captions.csv, preparation.json, delivery.txt를 텍스트 편집기로 여세요. 갤러리 링크는 이와 같은 파일들을 가리킵니다. CSV 파일 이름은 실제 images/ 파일들을 가리켜야 하고, 모든 미리보기는 320 × 213픽셀이어야 하며, JSON은 garden과 너비 320을 식별해야 합니다. 안내문은 실제로 사용한 Jenkins 작업, 빌드, 패키징 에이전트를 식별해야 합니다.

완성된 Fieldlight Studio 사진 갤러리

완전한 갤러리에는 정원 사진 세 장, 콘택트 시트 링크, 실제 설명 표·이미지 세부 정보·전달 파일로 연결되는 링크가 있습니다. 추출한 사본을 열 때 주변 파일들을 함께 유지하세요.

추출한 폴더 전체를 함께 유지하세요. Photo Desk를 사용하지 않고 새 비공개 브라우저 창에서 여세요. 모든 사진, 스타일, 파일 링크가 로컬 파일만으로 계속 작동해야 합니다. 갤러리는 원격 글꼴이나 온라인 대체 이미지를 사용하지 않습니다. 로컬 이미지가 깨지면 실제 전달 파일이 없거나 잘못된 위치에 있다는 뜻입니다. 원본 웹사이트에서 누락된 파일을 복사하지 말고, 원래 ZIP 전체를 새 폴더에 추출하세요.

Photo Desk로 전환하고 새로 고침한 다음 Open prepared collection을 선택하세요. 이 화면은 실제 Jenkins 자체 아카이브에서 파일을 읽습니다. 사진과 첨부 파일을 살펴본 뒤 브라우저의 Back 동작으로 돌아가 Download complete ZIP을 선택하세요. 바이트는 Jenkins에서 다운로드한 아티팩트와 일치해야 합니다. 데스크로 돌아가 전체 원본 세 장이 모두 변경되지 않았는지 확인하세요.

마지막으로 Jenkins로 전환하세요. 성공한 빌드를 다시 열고 정리 후에도 아티팩트를 계속 다운로드할 수 있는지 확인하세요. 처음 파일 누락으로 실패한 실행, 모든 이력, 원본, 도구, 노드 연결, 능력 레이블을 보존하세요. 스크립트를 다시 편집하면 저장하고 새 빌드를 성공적으로 완료한 뒤 검사하세요. 이제 실제 두 에이전트 간 전달과 완전하게 보관된 결과물이 있습니다.

요약

독립된 Jenkins 작업 공간을 관찰한 다음, 하나의 실행 안에서 이름을 지정한 stash와 일치하는 unstash로 필요한 사진 결과물만 전달했습니다. 패키징 에이전트는 완전한 로컬 갤러리를 만들었으며, Jenkins 자체 아티팩트 보관 덕분에 두 단계의 작업 공간이 모두 비워진 뒤에도 계속 사용할 수 있었습니다. 독립 챌린지는 여기서 배운 같은 메커니즘을 다시 사용하면서 컬렉션과 너비를 바꿉니다.